New submission from shangxiao <shang.xiao.sand...@gmail.com>:

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

----------
components: Library (Lib)
messages: 382051
nosy: shangxiao
priority: normal
severity: normal
status: open
title: Improve error messages for argparse choices using enum
type: behavior
versions: Python 3.10

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue42501>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to