Collection type argument for argparse where nargs != None

A friend of mine (@bcjbcjbcj on twitter) came up with an idea for an argparse improvement that I'd like to propose for inclusion. Currently, argparse with nargs=<anything but None> collects arguments into a list (or a list of lists in the case of action="append"). I would like to propose adding a "collection type" argument to the store and append actions and to add_argument, consisting of a callable that would be applied to the list of type-converted args before adding them to the Namespace. This would allow for alternate constructors (e.g. set), for modifying the list (e.g. with sorted), or to do checking of properties expected across all components of the argument at parse time. I've worked up a set of examples in this gist: https://gist.github.com/ pobocks/bff0bea494f2b7ec7eba1e8ae281b888 And a rough implementation here: https://github.com/python/ cpython/compare/master...pobocks:argparse_colltype I think this would be genuinely useful, and would require very little change to argparse, which should be backwards compatible provided that the default for the collection type is list, or None with list specified if None. Thank you all for your time in considering this, - Dave Mayo @pobocks on twitter, github, various others

I'm not a heavy argparse user so take my opinion with a grain of salt (and I do appreciate the time you put into proposing this), but I'm not seeing the usefulness to classify this as so pragmatic as to outweigh adding one more thing to explain about argparse. Since you're proposing just having a callable to use after constructing the list couldn't you just do e.g. `args.stuff = frozenset(args.stuff)` instead and just be explicit about it? On Fri, Aug 4, 2017, 06:01 David Mayo, <pobocks@gmail.com> wrote:

I mean, it's definitely possible, but I'd argue that's actually not any more explicit - and, in fact, args.stuff = something(args.stuff) is arguably less explicit because it's just an arbitrary transform, rather than being called out as "this is the wrapper element for these args." The places where I see doing transforms after as substantially worse than this: 1. any case where a single parser is being used in multiple scripts, or being extended. Moving this kind of thing out of the parser means the logic has to be replicated outside the parser everywhere it's called. 2. validation of multiple arguments against each other - once you're out of the parser, you have to write separate error handling code instead of just throwing the right exception. - Dave On Fri, Aug 4, 2017 at 12:33 PM, Brett Cannon <brett@python.org> wrote:

David Mayo writes:
The problem is third parties trying to read and work with the code, who now have to go read not only the definition of the parser, but the definition of the wrapper element (which is an arbitrary transform with a specified role). I think argparse is complex enough already. For both of your use cases (argparsers as reusable components and validation of collection arguments), I don't see why they can't be done in a subclass. This argument doesn't kill your proposal, and I'm just one rando, but FWIW I'm -0.5 on it for now. Steve

I'm not a heavy argparse user so take my opinion with a grain of salt (and I do appreciate the time you put into proposing this), but I'm not seeing the usefulness to classify this as so pragmatic as to outweigh adding one more thing to explain about argparse. Since you're proposing just having a callable to use after constructing the list couldn't you just do e.g. `args.stuff = frozenset(args.stuff)` instead and just be explicit about it? On Fri, Aug 4, 2017, 06:01 David Mayo, <pobocks@gmail.com> wrote:

I mean, it's definitely possible, but I'd argue that's actually not any more explicit - and, in fact, args.stuff = something(args.stuff) is arguably less explicit because it's just an arbitrary transform, rather than being called out as "this is the wrapper element for these args." The places where I see doing transforms after as substantially worse than this: 1. any case where a single parser is being used in multiple scripts, or being extended. Moving this kind of thing out of the parser means the logic has to be replicated outside the parser everywhere it's called. 2. validation of multiple arguments against each other - once you're out of the parser, you have to write separate error handling code instead of just throwing the right exception. - Dave On Fri, Aug 4, 2017 at 12:33 PM, Brett Cannon <brett@python.org> wrote:

David Mayo writes:
The problem is third parties trying to read and work with the code, who now have to go read not only the definition of the parser, but the definition of the wrapper element (which is an arbitrary transform with a specified role). I think argparse is complex enough already. For both of your use cases (argparsers as reusable components and validation of collection arguments), I don't see why they can't be done in a subclass. This argument doesn't kill your proposal, and I'm just one rando, but FWIW I'm -0.5 on it for now. Steve
participants (3)
-
Brett Cannon
-
David Mayo
-
Stephen J. Turnbull