From eaa6ca8dab192467b2f07a373a777d6b05357f13 Mon Sep 17 00:00:00 2001 From: Fabien Benureau Date: Thu, 10 Dec 2015 22:14:38 +0100 Subject: [PATCH] Proper error message when no subcommand is provided On Python 3, invoking `pubs` would display a stacktrace, because the subparser was not required. This commit also simplifies the parser code by using .set_default() to specify which command should be run. This prompted changes in the plugin code. The code is still not functioning, but many fixes in this commit bring the code closer to a working state. --- pubs/plugins.py | 6 +++--- pubs/plugs/alias/alias.py | 19 ++++++++++--------- pubs/pubs_cmd.py | 21 ++++++++++----------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/pubs/plugins.py b/pubs/plugins.py index d7c54cd..20653bb 100644 --- a/pubs/plugins.py +++ b/pubs/plugins.py @@ -28,13 +28,13 @@ class PapersPlugin(object): raise RuntimeError("{} instance not created".format(cls.__name__)) -def load_plugins(ui, names): +def load_plugins(conf, ui): """Imports the modules for a sequence of plugin names. Each name must be the name of a Python module under the "PLUGIN_NAMESPACE" namespace package in sys.path; the module indicated should contain the PapersPlugin subclasses desired. """ - for name in names: + for name in conf['plugins']['active']: modname = '%s.%s.%s.%s' % ('pubs', PLUGIN_NAMESPACE, name, name) try: namespace = importlib.import_module(modname) @@ -49,7 +49,7 @@ def load_plugins(ui, names): if isinstance(obj, type) and issubclass(obj, PapersPlugin) \ and obj != PapersPlugin: _classes.append(obj) - _instances[obj] = obj() + _instances[obj] = obj(conf) def get_plugins(): diff --git a/pubs/plugs/alias/alias.py b/pubs/plugs/alias/alias.py index 0c6da43..131b716 100644 --- a/pubs/plugs/alias/alias.py +++ b/pubs/plugs/alias/alias.py @@ -18,7 +18,7 @@ class Alias(object): p.add_argument('arguments', nargs='*', help="arguments to be passed to the user defined command") - def run(self, args): + def command(self, conf, args): raise NotImplementedError @classmethod @@ -35,7 +35,7 @@ class CommandAlias(Alias): - other arguments are passed to the command """ - def run(self, args): + def command(self, conf, args): raw_args = ([args.prog] + shlex.split(self.definition + ' ' @@ -45,7 +45,7 @@ class CommandAlias(Alias): class ShellAlias(Alias): - def run(self, args): + def command(self, conf, args): """Uses a shell function so that arguments can be used in the command as shell arguments. """ @@ -59,12 +59,13 @@ class AliasPlugin(PapersPlugin): name = 'alias' - def __init__(self): + def __init__(self, conf): self.aliases = [] - for name, definition in config('alias').items(): + for name, definition in conf['alias'].items(): self.aliases.append(Alias.create_alias(name, definition)) - def get_commands(self, parser): - for a in self.aliases: - a.parser(parser) - return [(a.name, a.run) for a in self.aliases] + def update_parser(self, subparsers): + """Add subcommand to the provided subparser""" + for alias in self.aliases: + alias_parser = alias.parser(parser) + alias_parser.set_defaults(func=alias.command) diff --git a/pubs/pubs_cmd.py b/pubs/pubs_cmd.py index a4854a2..0f94e50 100644 --- a/pubs/pubs_cmd.py +++ b/pubs/pubs_cmd.py @@ -42,7 +42,7 @@ def execute(raw_args=sys.argv): else: conf_path = config.get_confpath(verify=False) # will be checked on load - # loading config + # Loading config if len(remaining_args) > 0 and remaining_args[0] != 'init': try: conf = config.load_conf(path=conf_path, check=False) @@ -63,19 +63,18 @@ def execute(raw_args=sys.argv): prog="pubs", add_help=True) parser.add_argument('--version', action='version', version=__version__) subparsers = parser.add_subparsers(title="valid commands", dest="command") - cmd_funcs = collections.OrderedDict() + subparsers.required = True + + # Populate the parser with core commands for cmd_name, cmd_mod in CORE_CMDS.items(): - cmd_mod.parser(subparsers) - cmd_funcs[cmd_name] = cmd_mod.command + cmd_parser = cmd_mod.parser(subparsers) + cmd_parser.set_defaults(func=cmd_mod.command) # Extend with plugin commands - plugins.load_plugins(ui, conf['plugins']['active']) + plugins.load_plugins(conf, ui) for p in plugins.get_plugins().values(): - cmd_funcs.update(p.get_commands(subparsers)) + p.update_parser(subparsers) + # Parse and run appropriate command args = parser.parse_args(remaining_args) - args.prog = parser.prog # Hack: there might be a better way... - cmd = args.command - del args.command - - cmd_funcs[cmd](conf, args) + args.func(conf, args)