Reputation: 69
I have a CLI argument parser and I'm trying to build the parts that adds the specifications of the arguments dynamically with a pre defined dictionary that contains those details. This is dictionary with the details:
paramsDetails = {
'inputpath': {
'-': 'i',
'--': '--inputpath',
'dest': 'userinputpath',
'type': 'str',
'metavar': 'PATH',
'help': 'REQUIRED, input path of base folder of the files in which to scan. ',
'required': True
},
'depth': {
'-': 'd',
'--': '--depth',
'dest': 'directorydepth',
'type': 'int',
'metavar': 'INT',
'help': 'depth to do down in path. ',
}
}
The "paramsDetails" dictionary details are retrieved from a external source out of my control and it might change without my knowledge at any time so I can't be manually hard coding it in my code. I need to be able to build the "parser.add_argument" call dynamically without knowing the content of "paramsDetails". I don't necessarily need to "parser.add_argument" for this buy DO need to use the "paramsDetails" dict.
This is what I got so far:
from argparse import ArgumentParser
parser = ArgumentParser(description='My test')
for currentParamDetails in paramsDetails:
parser.add_argument(currentParamDetails)
args = parser.parse_args()
the "parser.add_argument(currentParamDetails)" doesn't work. I get:
usage: tests.py [-h] -i PATH [-d INT] inputpath depth
tests.py: error: the following arguments are required: inputpath, depth
which means it all went wrong.
of course typing the arguments manually works as so:
from argparse import ArgumentParser
parser = ArgumentParser(description='My test')
parser.add_argument("-i", "--inputpath", dest="userinputpath", type=str, metavar="PATH", help="REQUIRED, input path of base folder of the files in which to scan. ", required=True)
parser.add_argument("-d", "--depth", dest="directorydepth", type=int, metavar="INT", default=2, help="depth to do down in path. ")
args = parser.parse_args()
but that's not what I want, I want to use the dict.
How can this be done?
The Python version I'm using is 3.6.
Upvotes: 0
Views: 136
Reputation: 3462
Here's something you can do. Missing the "-" on the short flag seems kinda strange to me but it is not a big deal. Having the "type" as a string instead of an object is more problematic, but assuming they are always builtin types (like in your examples) this should work:
parser = ArgumentParser(description='My test')
for definition in paramsDetails.values():
flags = []
flag_short = definition.pop("-", None)
if flag_short:
flags.append(f"-{flag_short}")
flag_long = definition.pop("--", None)
if flag_long:
flags.append(flag_long)
if "type" in definition:
definition["type"] = getattr(__builtins__, definition["type"])
parser.add_argument(*flags, **definition)
args = parser.parse_args(["-h"])
Upvotes: 1