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.

Author shangxiao
Recipients shangxiao
Date 2020-11-29.10:20:30
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1606645231.03.0.116650247289.issue42501@roundup.psfhosted.org>
In-reply-to
Content
Summary
-------

The argparse module mentions that it will happily accept an enum for the choices argument option [1].  There are currently 2 issues with this:

1. The usage displays non user-friendly values for the enum;
2. The error message for invalid values is not consistent with those provided by iterable-based choices in that it doesn't show the list of available choices. This becomes a problem when you specify the metavar as no choices are displayed at all.


Example of 1
------------

For example using the GameMove example in the argparse documentation:

    class GameMove(Enum):
         ROCK = 'rock'
         PAPER = 'paper'
         SCISSORS = 'scissors'

    parser = argparse.ArgumentParser(prog='game.py')
    parser.add_argument('move', type=GameMove, choices=GameMove)
    parser.print_help()


Gives the usage:

    usage: game.py [-h] {GameMove.ROCK,GameMove.PAPER,GameMove.SCISSORS}

    positional arguments:
      {GameMove.ROCK,GameMove.PAPER,GameMove.SCISSORS}

    optional arguments:
      -h, --help            show this help message and exit


As you can see, the string representations of the valid enum members is used instead of the values.



Example of 2
------------

Below is an example of the error message shown for invalid enum values, with metavar specified:

    parser = argparse.ArgumentParser(prog='game.py')
    parser.add_argument('move', metavar='your-move', type=GameMove, choices=GameMove)
    parser.parse_args(['asdf'])

Gives the following output:

    usage: game.py [-h] your-move
    game.py: error: argument your-move: invalid GameMove value: 'asdf'


This is in contrast with using standard iterable-based choices:

    parser = argparse.ArgumentParser(prog='game.py')
    parser.add_argument('move', metavar='your-move', choices=[x.value for x in GameMove])
    parser.parse_args(['asdf'])

Gives the following output:

    usage: game.py [-h] your-move
    game.py: error: argument your-move: invalid choice: 'asdf' (choose from 'rock', 'paper', 'scissors')


Analysis of 2
--------------

The reason for this behaviour is because argparse attempts to convert to the correct type before checking the choices membership and an invalid enum value results in the first error message.

It would be helpful (& consistent) if the choices are also displayed along with the invalid value message.


Possible Solution
-----------------

I believe that both issues could be solved by using the enum member values in the choices and then checking for choice membership _before_ the value is converted to an enum (ie for enums only).



[1] https://docs.python.org/3/library/argparse.html#choices
History
Date User Action Args
2020-11-29 10:20:31shangxiaosetrecipients: + shangxiao
2020-11-29 10:20:31shangxiaosetmessageid: <1606645231.03.0.116650247289.issue42501@roundup.psfhosted.org>
2020-11-29 10:20:31shangxiaolinkissue42501 messages
2020-11-29 10:20:30shangxiaocreate