This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: No way to alternate options
Type: Stage: resolved
Components: Library (Lib) Versions: Python 3.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: josh.r, paul.j3, porton
Priority: normal Keywords:

Created on 2018-08-22 00:13 by porton, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (3)
msg323857 - (view) Author: Victor Porton (porton) Date: 2018-08-22 00:13
I have:

parser.add_argument('-p', '--preload', help='preload asset', action='append', metavar='NAMESPACE')

I want also add:

parser.add_argument('-f', '--file', help='preload file', action='append', metavar='FILE', dest='preload')

This way I could specify -p and/or -f options in any order (like: first -p then -f then -p again) and store then in 'preload' field in the order which the user specified the options.

But I have no way to know if an option is -p or -f :-(

Please add something to argparse to solve this problem.
msg323888 - (view) Author: Josh Rosenberg (josh.r) * (Python triager) Date: 2018-08-22 14:57
That's a *really* niche use case; you want to store everything to a common destination list, in order, but distinguish which switch added each one? I don't know of any programs that use such a design outside of Python (and therefore, it seems unlikely there would be enough demand from argparse users to justify the development, maintenance, and complexity cost of adding it).

argparse does support defining custom Actions, so it's wholly possible to add this sort of support for yourself if there isn't enough demand to add it to argparse itself. For example, a simple implementation would be:

class AppendWithSwitchAction(argparse.Action):
    def __init__(self, option_strings, dest, *args, **kwargs):
        super().__init__(option_strings, dest, *args, **kwargs)
        # Map all possible switches to the final switch provided
        # so we store a consistent switch name
        self.option_map = dict.fromkeys(option_strings, option_strings[-1])

    def __call__(self, parser, namespace, values, option_string=None):
        option = self.option_map.get(option_string)
        try:
            getattr(namespace, self.dest).append((option, value))
        except AttributeError:
            setattr(namespace, self.dest, [(option, value)])

then use it with:

parser.add_argument('-p', '--preload', help='preload asset', action=AppendWithSwitchAction, metavar='NAMESPACE')

parser.add_argument('-f', '--file', help='preload file', action=AppendWithSwitchAction, metavar='FILE', dest='preload')

All that does is append ('--preload', argument) or ('--file', argument) instead of just appending the argument, so you can distinguish one from the other (for switch, arg in args.preload:, then test if switch=='--preload' or '--file'). It's bare bones (the actual class underlying the 'append' action ensures nargs isn't 0, and that if const is provided, nargs is '?'), but it would serve.
msg323892 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2018-08-22 16:15
I agree that a custom Action subclass like this is the way to go.

The regular 'append' is implemented in _AppendAction class, which is different from the default _StoreAction.  So even if there was enough demand for this new idea to be put into development, it would be implemented as subclass (along with a registry entry).
History
Date User Action Args
2022-04-11 14:59:05adminsetgithub: 78639
2018-09-23 01:22:16paul.j3setresolution: not a bug
2018-09-20 19:16:04paul.j3setstatus: open -> closed
stage: resolved
2018-08-22 16:15:22paul.j3setnosy: + paul.j3
messages: + msg323892
2018-08-22 14:57:21josh.rsetnosy: + josh.r
messages: + msg323888
2018-08-22 00:13:51portoncreate