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.
main
Fabien Benureau 9 years ago
parent 4b21fa1355
commit eaa6ca8dab

@ -28,13 +28,13 @@ class PapersPlugin(object):
raise RuntimeError("{} instance not created".format(cls.__name__)) 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 """Imports the modules for a sequence of plugin names. Each name
must be the name of a Python module under the "PLUGIN_NAMESPACE" namespace must be the name of a Python module under the "PLUGIN_NAMESPACE" namespace
package in sys.path; the module indicated should contain the package in sys.path; the module indicated should contain the
PapersPlugin subclasses desired. PapersPlugin subclasses desired.
""" """
for name in names: for name in conf['plugins']['active']:
modname = '%s.%s.%s.%s' % ('pubs', PLUGIN_NAMESPACE, name, name) modname = '%s.%s.%s.%s' % ('pubs', PLUGIN_NAMESPACE, name, name)
try: try:
namespace = importlib.import_module(modname) namespace = importlib.import_module(modname)
@ -49,7 +49,7 @@ def load_plugins(ui, names):
if isinstance(obj, type) and issubclass(obj, PapersPlugin) \ if isinstance(obj, type) and issubclass(obj, PapersPlugin) \
and obj != PapersPlugin: and obj != PapersPlugin:
_classes.append(obj) _classes.append(obj)
_instances[obj] = obj() _instances[obj] = obj(conf)
def get_plugins(): def get_plugins():

@ -18,7 +18,7 @@ class Alias(object):
p.add_argument('arguments', nargs='*', p.add_argument('arguments', nargs='*',
help="arguments to be passed to the user defined command") help="arguments to be passed to the user defined command")
def run(self, args): def command(self, conf, args):
raise NotImplementedError raise NotImplementedError
@classmethod @classmethod
@ -35,7 +35,7 @@ class CommandAlias(Alias):
- other arguments are passed to the command - other arguments are passed to the command
""" """
def run(self, args): def command(self, conf, args):
raw_args = ([args.prog] raw_args = ([args.prog]
+ shlex.split(self.definition + shlex.split(self.definition
+ ' ' + ' '
@ -45,7 +45,7 @@ class CommandAlias(Alias):
class ShellAlias(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 """Uses a shell function so that arguments can be used in the command
as shell arguments. as shell arguments.
""" """
@ -59,12 +59,13 @@ class AliasPlugin(PapersPlugin):
name = 'alias' name = 'alias'
def __init__(self): def __init__(self, conf):
self.aliases = [] self.aliases = []
for name, definition in config('alias').items(): for name, definition in conf['alias'].items():
self.aliases.append(Alias.create_alias(name, definition)) self.aliases.append(Alias.create_alias(name, definition))
def get_commands(self, parser): def update_parser(self, subparsers):
for a in self.aliases: """Add subcommand to the provided subparser"""
a.parser(parser) for alias in self.aliases:
return [(a.name, a.run) for a in self.aliases] alias_parser = alias.parser(parser)
alias_parser.set_defaults(func=alias.command)

@ -42,7 +42,7 @@ def execute(raw_args=sys.argv):
else: else:
conf_path = config.get_confpath(verify=False) # will be checked on load 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': if len(remaining_args) > 0 and remaining_args[0] != 'init':
try: try:
conf = config.load_conf(path=conf_path, check=False) conf = config.load_conf(path=conf_path, check=False)
@ -63,19 +63,18 @@ def execute(raw_args=sys.argv):
prog="pubs", add_help=True) prog="pubs", add_help=True)
parser.add_argument('--version', action='version', version=__version__) parser.add_argument('--version', action='version', version=__version__)
subparsers = parser.add_subparsers(title="valid commands", dest="command") 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(): for cmd_name, cmd_mod in CORE_CMDS.items():
cmd_mod.parser(subparsers) cmd_parser = cmd_mod.parser(subparsers)
cmd_funcs[cmd_name] = cmd_mod.command cmd_parser.set_defaults(func=cmd_mod.command)
# Extend with plugin commands # Extend with plugin commands
plugins.load_plugins(ui, conf['plugins']['active']) plugins.load_plugins(conf, ui)
for p in plugins.get_plugins().values(): 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 = parser.parse_args(remaining_args)
args.prog = parser.prog # Hack: there might be a better way... args.func(conf, args)
cmd = args.command
del args.command
cmd_funcs[cmd](conf, args)

Loading…
Cancel
Save