Mercurial > piecrust2
changeset 57:c8c522dacfea
Add `help` function, cleanup argument handling.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Tue, 26 Aug 2014 23:18:32 -0700 |
parents | 2d617b889b00 |
children | 95590732e4c9 |
files | piecrust/commands/base.py piecrust/main.py |
diffstat | 2 files changed, 63 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/piecrust/commands/base.py Tue Aug 26 23:17:20 2014 -0700 +++ b/piecrust/commands/base.py Tue Aug 26 23:18:32 2014 -0700 @@ -1,4 +1,5 @@ import logging +import argparse import functools from piecrust.pathutil import SiteNotFoundError @@ -7,10 +8,10 @@ class CommandContext(object): - def __init__(self, app, args): + def __init__(self, app, parser, args): self.app = app + self.parser = parser self.args = args - self.result = 0 class ChefCommand(object): @@ -23,14 +24,13 @@ raise NotImplementedError() def run(self, ctx): - raise NotImplementedError() + raise NotImplementedError("Command '%s' doesn't implement the `run` " + "method." % type(self)) - def _runFromChef(self, app, res): - if app.root_dir is None and self.requires_website: + def checkedRun(self, ctx): + if ctx.app.root_dir is None and self.requires_website: raise SiteNotFoundError() - ctx = CommandContext(app, res) - self.run(ctx) - return ctx.result + return self.run(ctx) class ExtendableChefCommand(ChefCommand): @@ -44,7 +44,7 @@ for e in self._extensions: p = subparsers.add_parser(e.name, help=e.description) e.setupParser(p, app) - p.set_defaults(func=e._runFromChef) + p.set_defaults(func=e.checkedRun) def _loadExtensions(self, app): if self._extensions is not None: @@ -64,6 +64,50 @@ return True +class HelpCommand(ChefCommand): + def __init__(self): + super(HelpCommand, self).__init__() + self.name = 'help' + self.description = "Prints help about PieCrust's chef." + self._topic_providers = {} + + @property + def has_topics(self): + return any(self._topic_providers) + + def addTopic(self, name, provider): + self._topic_providers[name] = provider + + def getTopicNames(self): + return self._topic_providers.keys() + + def setupParser(self, parser, app): + parser.add_argument('topic', nargs='?', + help="The command name or topic on which to get help.") + + def run(self, ctx): + topic = ctx.args.topic + + if topic is None: + ctx.parser.print_help() + return 0 + + if topic in self._topic_providers: + print(self._topic_providers[topic].getHelpTopic(topic, ctx.app)) + return 0 + + for c in ctx.app.plugin_loader.getCommands(): + if c.name == topic: + fake = argparse.ArgumentParser( + prog='%s %s' % (ctx.parser.prog, c.name), + description=c.description) + c.setupParser(fake, ctx.app) + fake.print_help() + return 0 + + raise Exception("No such command or topic: %s" % topic) + + class _WrappedCommand(ChefCommand): def __init__(self, func, name, description): super(_WrappedCommand, self).__init__()
--- a/piecrust/main.py Tue Aug 26 23:17:20 2014 -0700 +++ b/piecrust/main.py Tue Aug 26 23:18:32 2014 -0700 @@ -6,6 +6,7 @@ import colorama from piecrust.app import PieCrust, PieCrustConfiguration, APP_VERSION from piecrust.chefutil import format_timed, log_friendly_exception +from piecrust.commands.base import CommandContext from piecrust.environment import StandardEnvironment from piecrust.pathutil import SiteNotFoundError, find_app_root from piecrust.plugins.base import PluginLoader @@ -151,6 +152,7 @@ # Setup the arg parser. parser = argparse.ArgumentParser( + prog='chef', description="The PieCrust chef manages your website.") parser.add_argument('--version', action='version', version=('%(prog)s ' + APP_VERSION)) parser.add_argument('--root', help="The root directory of the website.") @@ -166,13 +168,19 @@ for c in commands: p = subparsers.add_parser(c.name, help=c.description) c.setupParser(p, app) - p.set_defaults(func=c._runFromChef) + p.set_defaults(func=c.checkedRun) + help_cmd = next(filter(lambda c: c.name == 'help', commands), None) + if help_cmd and help_cmd.has_topics: + parser.epilog = ("Additional help topics: " + + ', '.join(help_cmd.getTopicNames())) + # Parse the command line. result = parser.parse_args() logger.debug(format_timed(start_time, 'initialized PieCrust', colored=False)) # Run the command! - exit_code = result.func(app, result) + ctx = CommandContext(app, parser, result) + exit_code = result.func(ctx) return exit_code