-
-
Save sampsyo/471779 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python | |
"""Aliases for argparse positional arguments.""" | |
import argparse | |
class AliasedSubParsersAction(argparse._SubParsersAction): | |
class _AliasedPseudoAction(argparse.Action): | |
def __init__(self, name, aliases, help): | |
dest = name | |
if aliases: | |
dest += ' (%s)' % ','.join(aliases) | |
sup = super(AliasedSubParsersAction._AliasedPseudoAction, self) | |
sup.__init__(option_strings=[], dest=dest, help=help) | |
def add_parser(self, name, **kwargs): | |
if 'aliases' in kwargs: | |
aliases = kwargs['aliases'] | |
del kwargs['aliases'] | |
else: | |
aliases = [] | |
parser = super(AliasedSubParsersAction, self).add_parser(name, **kwargs) | |
# Make the aliases work. | |
for alias in aliases: | |
self._name_parser_map[alias] = parser | |
# Make the help text reflect them, first removing old help entry. | |
if 'help' in kwargs: | |
help = kwargs.pop('help') | |
self._choices_actions.pop() | |
pseudo_action = self._AliasedPseudoAction(name, aliases, help) | |
self._choices_actions.append(pseudo_action) | |
return parser | |
if __name__ == '__main__': | |
# An example parser with subcommands. | |
parser = argparse.ArgumentParser() | |
parser.register('action', 'parsers', AliasedSubParsersAction) | |
parser.add_argument("--library", metavar="libfile", type=str, | |
help="library database filename") | |
subparsers = parser.add_subparsers(title="commands", metavar="COMMAND") | |
p_import = subparsers.add_parser("import", help="add files to library", | |
aliases=('imp', 'im')) | |
p_import.add_argument("filename", metavar="file", type=str, nargs="+", | |
help="the files to import") | |
p_remove = subparsers.add_parser("remove", aliases=('rm',), | |
help="remove items") | |
args = parser.parse_args() | |
print args |
Since I've gotten this question a few times: I dedicate this code to the public domain. You can use it freely for any purpose.
Thanks for the snippet!
if 'aliases' in kwargs:
aliases = kwargs['aliases']
del kwargs['aliases']
else:
aliases = []
could simply be:
aliases = kwargs.pop('aliases', [])
Nice! Thanks for sharing.
If I might add an updated version, the following includes xiaket's modification, and also overrides the default parsers action so you don't have to register it per parser.
I don't know much about python importing practices - this may be a horrible idea, but it works for me regardless of whether this file or argparse is imported first in another file, and works for recursive subparsers, so if you're lazy like me, maybe give it a try.
class AliasedSubParsersAction(argparse._SubParsersAction):
old_init = staticmethod(argparse._ActionsContainer.__init__)
@staticmethod
def _containerInit(self, description, prefix_chars, argument_default, conflict_handler):
AliasedSubParsersAction.old_init(self, description, prefix_chars, argument_default, conflict_handler)
self.register('action', 'parsers', AliasedSubParsersAction)
class _AliasedPseudoAction(argparse.Action):
def __init__(self, name, aliases, help):
dest = name
if aliases:
dest += ' (%s)' % ','.join(aliases)
sup = super(AliasedSubParsersAction._AliasedPseudoAction, self)
sup.__init__(option_strings=[], dest=dest, help=help)
def add_parser(self, name, **kwargs):
aliases = kwargs.pop('aliases', [])
parser = super(AliasedSubParsersAction, self).add_parser(name, **kwargs)
# Make the aliases work.
for alias in aliases:
self._name_parser_map[alias] = parser
# Make the help text reflect them, first removing old help entry.
if 'help' in kwargs:
help = kwargs.pop('help')
self._choices_actions.pop()
pseudo_action = self._AliasedPseudoAction(name, aliases, help)
self._choices_actions.append(pseudo_action)
return parser
# override argparse to register new subparser action by default
argparse._ActionsContainer.__init__ = AliasedSubParsersAction._containerInit
Works very nicely @LiamGow
@sampsyo Thank you so much! This is just what I needed :-)
Python now supports this built-in. Does anyone know in which exact version it was added to Python?
(And again, thank you for this gist.)
Thanks for that! What license is this code? Can I use it in GPL or BSD code? How do I have to credit you?