New submission from pkkm <[email protected]>:
This is a feature request for options that would work like the "find" program's
"-exec" option, which takes the arguments following it unconditionally until it
encounters a ";" or a "+".
There are multiple ways to achieve this, but I think a good general solution
would be to let "nargs" take a function. This function would receive a list of
all arguments following the current one and return the number of arguments that
the current one should take. An example usage would be:
def command_nargs(args_after):
for i, arg in enumerate(args_after):
if arg in [';', '+']:
return i + 1
raise argparse.ArgumentTypeError(
'Expected a command terminated with `;` or `+`.')
parser = argparse.ArgumentParser()
parser.add_argument('--command', nargs=command_nargs)
parser.add_argument('--option')
parser.parse_args(['--command', 'echo', 'hello', ';', '--option', 'value'])
# => Namespace(command=['echo', 'hello', ';'], option='value')
parser.parse_args(['--command', 'program', '--option', '+'])
# => Namespace(command=['program', '--option', '+'], option=None)
The crucial difference between this and the current behavior of "nargs" is that
the requested number of arguments would be taken unconditionally, even if the
arguments looked like options:
parser = argparse.ArgumentParser()
parser.add_argument('--nargs-function', nargs=lambda _: 1)
parser.add_argument('--nargs-number', nargs=1)
parser.add_argument('--option')
parser.parse_args(['--nargs-function', '--option'])
# => Namespace(nargs_function=['--option'], option=None)
parser.parse_args(['--nargs-number', '--option'])
# => error: argument --nargs-number: expected 1 argument
Alternatively, if the difference between the behavior of "nargs=number" and
"nargs=function" is judged to be too large, an optional argument "greedy" could
be added to "ArgumentParser" and "add_argument".
With "greedy=False" (the default), argparse would behave like it currently
does. With "greedy=True", options would be processed left to right and would be
assigned values unconditionally, even if these values looked like other
options. An option with "nargs='*', greedy=True" or "nargs='+', greedy=True"
would take all arguments to its right. An option with "nargs=function,
greedy=False" would stop taking arguments when it encountered an option, while
with "greedy=True" it would have the behavior proposed in the previous
paragraphs.
An example usage would then be:
parser = argparse.ArgumentParser()
parser.add_argument('--nargs-function', nargs=lambda _: 1)
parser.add_argument('--nargs-number', nargs=1)
parser.add_argument('--option')
parser.parse_args(['--nargs-function', '--option'])
# => error: argument --nargs-function: expected 1 argument
parser.parse_args(['--nargs-number', '--option'])
# => error: argument --nargs-number: expected 1 argument
####################
parser = argparse.ArgumentParser()
parser.add_argument('--nargs-function', nargs=lambda _: 1, greedy=True)
parser.add_argument('--nargs-number', nargs=1, greedy=True)
parser.add_argument('--option')
parser.parse_args(['--nargs-function', '--option'])
# => Namespace(nargs_function=['--option'], option=None)
parser.parse_args(['--nargs-number', '--option'])
# => Namespace(nargs_number=['--option'], option=None)
and:
parser = argparse.ArgumentParser()
parser.add_argument('--command', nargs=command_nargs)
parser.add_argument('--option')
parser.add_argument('arg', nargs='?')
parser.parse_args(['--command', 'program', '--option', 'value', '+'])
# => Namespace(arg='+', command=['program'], option='value')
####################
parser = argparse.ArgumentParser(greedy=True)
parser.add_argument('--command', nargs=command_nargs)
parser.add_argument('--option')
parser.add_argument('arg', nargs='?')
parser.parse_args(['--command', 'program', '--option', 'value', '+'])
# => Namespace(arg=None, command=['program', '--option', 'value', '+'],
option=None)
Both of the alternatives in this feature request have the upside of making the
behaviors requested in #9334 and #14364 possible.
----------
components: Library (Lib)
messages: 386662
nosy: pkkm
priority: normal
severity: normal
status: open
title: argparse: support options similar to find's -exec
type: enhancement
versions: Python 3.10
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue43169>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com