您的后解析测试很好,特别是如果使用 is None 测试默认值符合您的需求。
http://bugs.python.org/issue11588 'Add "necessarily inclusive" groups to argparse' 研究使用groups 机制(mutuall_exclusive_groups 的泛化)实现这样的测试。
我编写了一组 UsageGroups 来实现像 xor(互斥)、and、or 和 not 这样的测试。我认为那些很全面,但我无法用这些操作来表达你的情况。 (看起来我需要nand - 不是和,见下文)
此脚本使用自定义Test 类,它实质上实现了您的解析后测试。 seen_actions 是解析器看到的操作列表。
class Test(argparse.UsageGroup):
def _add_test(self):
self.usage = '(if --argument then -a and -b are required)'
def testfn(parser, seen_actions, *vargs, **kwargs):
"custom error"
actions = self._group_actions
if actions[0] in seen_actions:
if actions[1] not in seen_actions or actions[2] not in seen_actions:
msg = '%s - 2nd and 3rd required with 1st'
self.raise_error(parser, msg)
return True
self.testfn = testfn
self.dest = 'Test'
p = argparse.ArgumentParser(formatter_class=argparse.UsageGroupHelpFormatter)
g1 = p.add_usage_group(kind=Test)
g1.add_argument('--argument')
g1.add_argument('-a')
g1.add_argument('-b')
print(p.parse_args())
示例输出为:
1646:~/mypy/argdev/usage_groups$ python3 issue25626109.py --arg=1 -a1
usage: issue25626109.py [-h] [--argument ARGUMENT] [-a A] [-b B]
(if --argument then -a and -b are required)
issue25626109.py: error: group Test: argument, a, b - 2nd and 3rd required with 1st
usage 和错误消息仍然需要处理。而且它没有做任何解析后测试做不到的事情。
如果(argument & (!a or !b)),您的测试会引发错误。相反,允许的是!(argument & (!a or !b)) = !(argument & !(a and b))。通过将nand 测试添加到我的UsageGroup 类中,我可以将您的案例实现为:
p = argparse.ArgumentParser(formatter_class=argparse.UsageGroupHelpFormatter)
g1 = p.add_usage_group(kind='nand', dest='nand1')
arg = g1.add_argument('--arg', metavar='C')
g11 = g1.add_usage_group(kind='nand', dest='nand2')
g11.add_argument('-a')
g11.add_argument('-b')
用法是(使用!()标记'nand'测试):
usage: issue25626109.py [-h] !(--arg C & !(-a A & -b B))
我认为这是使用通用使用组来表达这个问题的最短、最清晰的方式。
在我的测试中,成功解析的输入是:
''
'-a1'
'-a1 -b2'
'--arg=3 -a1 -b2'
应该引发错误的是:
'--arg=3'
'--arg=3 -a1'
'--arg=3 -b2'