Currently, combining type
and choices
in an argparse Action
gives weird usage strings.
As a toy example:
import argparse
parser = argparse.ArgumentParser()
names = ["mo", "tu", "we", "th", "fr", "sa", "su"]
days = [1,2,3,4,5,6,7]
def name_day(value):
return names.index(value) + 1
parser.add_argument(
'--days',
type=name_day,
choices=days,
default=["mo"],
)
parser.parse_args()
This will result in the following usage message:
usage: example.py [-h] [--days {1,2,3,4,5,6,7}]
This is because the check against choices
is performed after type conversion.
The problem is also present for other type conversions, for instance when the target types are locations on a map, or dates on a calendar.
Proposal:
Allow the developer to specify choices in the same language as the users inputs arguments. This will allow the developer to rewrite the above example to the following:
day_names = ["mo", "tu", "we", "th", "fr", "sa", "su"]
def name_day(value):
return day_names.index(value) + 1
parser.add_argument(
'--days',
type=name_day,
choices=day_names,
)
parser.parse_args()
Instead of validating the converted value against the available choices, validate the user supplied value against the available choices. Because this can break existing code, the feature will only be enabled by a parser option: convert_choices
.
Motivation:
The reworked example is slightly more concise and (at least in my mind) more intuitive. It is also consistent with how the default
value is specified, which is also before conversion.
By implementing the proposed behavior, we also get better error
and usage
messages. We don’t break existing code, because the behavior is only enabled by a feature flag.