У меня есть решение, основанное на предложенном hpaulj улучшении argparse usage_tests .
Как и во вдохновляющем алгоритме, оно состоит в использовании _ActionsContainer._registries
для хранения некоторых 'usage_tests'
, запускаемых после всего процесса ArgumentParser.parse_known_args
. Но, разумеется, я не переписывал исходный метод, вместо этого я просто создал свой собственный подкласс ArgumentParser
, чтобы обернуть функцию, проверяя и запуская зарегистрированный usage_tests
class MyArgumentParser(ArgumentParser):
def parse_known_args(self, args=None, namespace=None):
namespace, argv = super(MyArgumentParser, self).parse_known_args(args, namespace)
for test in self._registries.get('usage_tests', {}).values():
test(self, args or sys.argv[1:], namespace)
return namespace, argv
def add_required_group(self, *args, **kwargs):
group = _RequiredGroup(self, *args, **kwargs)
self._action_groups.append(group)
return group
Таким образом, я до сих пор нет доступа к переменной seen_non_default_actions
, я работаю над этим, используя аргументы catch через sys.argv[1:]
class _RequiredGroup(_ArgumentGroup):
def __init__(self, container, **kwargs):
super(_RequiredGroup, self).__init__(container, **kwargs)
name = str(id(self)) # a unique key for this test
self.register('usage_tests', name, self.test)
@property
def _option_strings(self):
option_strings = []
for action in self._group_actions:
option_strings += action.option_strings
return option_strings
def test(self, parser, args, namespace):
for option in self._option_strings:
if option in args:
break
else: # if no actions were used, report the error
if self._option_strings:
parser.error(f"one of the arguments {' '.join(self._option_strings)} is required")