Package: argparse_config
Theargparse_configutility reads defaults for commandline args from a
config file. The cute thing is, it figures out what config options to expect
based on yourargparsecommandline args definition.Let’s say I’m reimplementing the Mercurial commandline client. I specify the
commandline argument processing withargparse, of course:>>> arg_parser = ArgumentParser('hg')
>>> arg_parser.add_argument('--repository')
>>> sub_parsers = arg_parser.add_subparsers()
>>>
>>> merge_parser = sub_parsers.add_parser('merge')
>>> merge_parser.add_argument('--tool')
>>> merge_parser.add_argument('--force', action='store_true', default=False)
>>>
>>> commit_parser = sub_parsers.add_parser('commit')
>>> commit_parser.add_argument('--user')
>>> commit_parser.add_argument('--message')When I go to use this client, though, I have to keep specifying my--userwith every commit, and--toolwith every merge. That sucks! What I want is
to have my client understand a simple config file format:[merge]
tool: meld

[commit]
user: Tikitu de Jager <tikitu@logophile.org>And obviously, as I add more arguments and subcommands to my client, it should
allow me to add defaults in the config file without writing more code.This is whatargparse_configgives you. To use it with the mercurial clientarg_parserabove:>>> import argparse_config
>>> argparse_config.read_config_file(arg_parser, '/home/tikitu/.my_hg.cfg')… and that’s it. Callingarg_parser.parse_args()will parse args as usual,
but thedefaultvalues will be taken from the config file, if they are given
there:>>> parsed_args = arg_parser.parse_args(['merge'])
>>> parsed_args.tool
'meld'What can I put in the config file?Under the hoodargparse_configuses the standard libraryConfigParser.
Arguments that aren’t for a subcommand go in the section[default]. The
names are munged from the commandline argument, removing leading dashes and
converting internal dashes to underscores (e.g.--log-levelbecomeslog_level:).Flags (i.e. commandline args that take no parameters) are turned on if present
in the config, just like the commandline:[default]
verboseis the equivalent of--verbose. Eitherverbose:orverbosewill work,
but (watch out!)verbose:a-valuedoesn’t do anything different toverbose.Writing a config file from some commandline argumentsIncluded in the package is a utility to generate a config file following these
rules, from a given set of commandline arguments. The easy way to use it is to
let it add a command to your args parsing:>>> config_parser = get_config_parser('/home/tikitu/.my_hg.cfg')
>>> add_config_block_subcommand(arg_parser, sub_parsers, config_parser=config_parser)and use it on the commandline:$ hg.py config default --repository ssh://hg@bitbucket.org/tikitu/argparse_config > new_config.rc
$ hg.py config commit --username 'Tikitu de Jager <tikitu@logophile.org>' >> new_config.rc
$ cat new_config.rc
[default]
repository: ssh://hg@bitbucket.org/tikitu/argparse_config
[commit]
username: Tikitu de Jager <tikitu@logophile.org>You can also use it programatically, if you like. That looks like this:>>> parsed_args = arg_parser.parse_args(['--repository', 'https://bitbucket.org/tikitu/argparse_config', 'merge'])
>>> print argparse_config.generate_config(arg_parser, parsed_args, section='default', only_non_defaults=True)
[default]
repository: https://bitbucket.org/tikitu/argparse_configSome complications make this less useful than it could be, sadly:If you use subcommands, you can only parse the args for one of them at a time
(use thesectionargument to specify which, or leave it off to get the[default]section).We can’t tell the difference between default values written in code (which should
not be added to the config file) and written in a previously-read-in config file
(which should). This is whyonly_non_defaultsexists.How does it work?By gudgeling about in the private internals ofargparse. Yes, that’s not
pretty.GotchasAny required arguments that are present in a config file will show as optional,
not required, in the--helpoutput. (This is a bug-by-design, due to not
having any clever idea about how to do it better.) It may help to tell
yourself, “It’s not requiredon the commandlinebecause I gave it in the
config file.” (I will gladly make this dodgy rationalisation disappear if I
figure out how to handle required arguments more tidily.)HackingIt’s onBitBucket. Feel free to play. It comes with a handyzc.buildoutwrapper too, overkill though that clearly is.TODOIt’s “alpha software” at present; likely to be buggy and lots of stuff ain’t
there yet. Check theissues listto stay up to date. Some remaining open issues:How to deal with multi-value args? (The config-file library this is built on doesn’t support them.)The “write me a config file” support is scrappy. Can we do better?