Case insensitive argparse choices
Question:
Is it possible to check argparse choices in case-insensitive manner?
import argparse
choices = ["win64", "win32"]
parser = argparse.ArgumentParser()
parser.add_argument("-p", choices=choices)
print(parser.parse_args(["-p", "Win32"]))
results in:
usage: choices.py [-h] [-p {win64,win32}]
choices.py: error: argument -p: invalid choice: 'Win32' (choose from 'win64','win32')
Answers:
Using lower
in the type
is nice way of doing this, if you don’t mind loosing the case information.
If you want to retain the case, you could define a custom choices
class. The choices
needs two methods, __contains__
(for testing in
), and iteration (to list the choices).
class mylist(list):
# list subclass that uses lower() when testing for 'in'
def __contains__(self, other):
return super(mylist,self).__contains__(other.lower())
choices=mylist(['win64','win32'])
parser = argparse.ArgumentParser()
parser.add_argument("-p", choices=choices)
print(parser.parse_args(["-p", "Win32"]))
# Namespace(p='Win32')
The help is:
usage: ipython [-h] [-p {win64,win32}]
optional arguments:
-h, --help show this help message and exit
-p {win64,win32}
Keeping the case information would also be possible with a one liner:
type = lambda arg: {x.lower(): x for x in choices}[arg.lower()],
Where choices would be the same list as passed to the choices parameter.
To clarify @5gon12eder’s answer, you need to include the "type" as another paramater to add_argument
:
parser.add_argument("-p", choices=choices, type=str.lower)
This will make sure that the input is lowercased.
Make sure to NOT add parentheses after lower
.
Is it possible to check argparse choices in case-insensitive manner?
import argparse
choices = ["win64", "win32"]
parser = argparse.ArgumentParser()
parser.add_argument("-p", choices=choices)
print(parser.parse_args(["-p", "Win32"]))
results in:
usage: choices.py [-h] [-p {win64,win32}]
choices.py: error: argument -p: invalid choice: 'Win32' (choose from 'win64','win32')
Using lower
in the type
is nice way of doing this, if you don’t mind loosing the case information.
If you want to retain the case, you could define a custom choices
class. The choices
needs two methods, __contains__
(for testing in
), and iteration (to list the choices).
class mylist(list):
# list subclass that uses lower() when testing for 'in'
def __contains__(self, other):
return super(mylist,self).__contains__(other.lower())
choices=mylist(['win64','win32'])
parser = argparse.ArgumentParser()
parser.add_argument("-p", choices=choices)
print(parser.parse_args(["-p", "Win32"]))
# Namespace(p='Win32')
The help is:
usage: ipython [-h] [-p {win64,win32}]
optional arguments:
-h, --help show this help message and exit
-p {win64,win32}
Keeping the case information would also be possible with a one liner:
type = lambda arg: {x.lower(): x for x in choices}[arg.lower()],
Where choices would be the same list as passed to the choices parameter.
To clarify @5gon12eder’s answer, you need to include the "type" as another paramater to add_argument
:
parser.add_argument("-p", choices=choices, type=str.lower)
This will make sure that the input is lowercased.
Make sure to NOT add parentheses after lower
.