New submission from pkkm <paul.krasni...@gmail.com>:
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 <rep...@bugs.python.org> <https://bugs.python.org/issue43169> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com