Mercurial > piecrust2
comparison piecrust/commands/base.py @ 57:c8c522dacfea
Add `help` function, cleanup argument handling.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Tue, 26 Aug 2014 23:18:32 -0700 |
parents | f485ba500df3 |
children | 8703be118430 |
comparison
equal
deleted
inserted
replaced
56:2d617b889b00 | 57:c8c522dacfea |
---|---|
1 import logging | 1 import logging |
2 import argparse | |
2 import functools | 3 import functools |
3 from piecrust.pathutil import SiteNotFoundError | 4 from piecrust.pathutil import SiteNotFoundError |
4 | 5 |
5 | 6 |
6 logger = logging.getLogger(__name__) | 7 logger = logging.getLogger(__name__) |
7 | 8 |
8 | 9 |
9 class CommandContext(object): | 10 class CommandContext(object): |
10 def __init__(self, app, args): | 11 def __init__(self, app, parser, args): |
11 self.app = app | 12 self.app = app |
13 self.parser = parser | |
12 self.args = args | 14 self.args = args |
13 self.result = 0 | |
14 | 15 |
15 | 16 |
16 class ChefCommand(object): | 17 class ChefCommand(object): |
17 def __init__(self): | 18 def __init__(self): |
18 self.name = '__unknown__' | 19 self.name = '__unknown__' |
21 | 22 |
22 def setupParser(self, parser, app): | 23 def setupParser(self, parser, app): |
23 raise NotImplementedError() | 24 raise NotImplementedError() |
24 | 25 |
25 def run(self, ctx): | 26 def run(self, ctx): |
26 raise NotImplementedError() | 27 raise NotImplementedError("Command '%s' doesn't implement the `run` " |
28 "method." % type(self)) | |
27 | 29 |
28 def _runFromChef(self, app, res): | 30 def checkedRun(self, ctx): |
29 if app.root_dir is None and self.requires_website: | 31 if ctx.app.root_dir is None and self.requires_website: |
30 raise SiteNotFoundError() | 32 raise SiteNotFoundError() |
31 ctx = CommandContext(app, res) | 33 return self.run(ctx) |
32 self.run(ctx) | |
33 return ctx.result | |
34 | 34 |
35 | 35 |
36 class ExtendableChefCommand(ChefCommand): | 36 class ExtendableChefCommand(ChefCommand): |
37 def __init__(self): | 37 def __init__(self): |
38 super(ExtendableChefCommand, self).__init__() | 38 super(ExtendableChefCommand, self).__init__() |
42 self._loadExtensions(app) | 42 self._loadExtensions(app) |
43 subparsers = parser.add_subparsers() | 43 subparsers = parser.add_subparsers() |
44 for e in self._extensions: | 44 for e in self._extensions: |
45 p = subparsers.add_parser(e.name, help=e.description) | 45 p = subparsers.add_parser(e.name, help=e.description) |
46 e.setupParser(p, app) | 46 e.setupParser(p, app) |
47 p.set_defaults(func=e._runFromChef) | 47 p.set_defaults(func=e.checkedRun) |
48 | 48 |
49 def _loadExtensions(self, app): | 49 def _loadExtensions(self, app): |
50 if self._extensions is not None: | 50 if self._extensions is not None: |
51 return | 51 return |
52 self._extensions = [] | 52 self._extensions = [] |
60 super(ChefCommandExtension, self).__init__() | 60 super(ChefCommandExtension, self).__init__() |
61 self.command_name = '__unknown__' | 61 self.command_name = '__unknown__' |
62 | 62 |
63 def supports(self, app): | 63 def supports(self, app): |
64 return True | 64 return True |
65 | |
66 | |
67 class HelpCommand(ChefCommand): | |
68 def __init__(self): | |
69 super(HelpCommand, self).__init__() | |
70 self.name = 'help' | |
71 self.description = "Prints help about PieCrust's chef." | |
72 self._topic_providers = {} | |
73 | |
74 @property | |
75 def has_topics(self): | |
76 return any(self._topic_providers) | |
77 | |
78 def addTopic(self, name, provider): | |
79 self._topic_providers[name] = provider | |
80 | |
81 def getTopicNames(self): | |
82 return self._topic_providers.keys() | |
83 | |
84 def setupParser(self, parser, app): | |
85 parser.add_argument('topic', nargs='?', | |
86 help="The command name or topic on which to get help.") | |
87 | |
88 def run(self, ctx): | |
89 topic = ctx.args.topic | |
90 | |
91 if topic is None: | |
92 ctx.parser.print_help() | |
93 return 0 | |
94 | |
95 if topic in self._topic_providers: | |
96 print(self._topic_providers[topic].getHelpTopic(topic, ctx.app)) | |
97 return 0 | |
98 | |
99 for c in ctx.app.plugin_loader.getCommands(): | |
100 if c.name == topic: | |
101 fake = argparse.ArgumentParser( | |
102 prog='%s %s' % (ctx.parser.prog, c.name), | |
103 description=c.description) | |
104 c.setupParser(fake, ctx.app) | |
105 fake.print_help() | |
106 return 0 | |
107 | |
108 raise Exception("No such command or topic: %s" % topic) | |
65 | 109 |
66 | 110 |
67 class _WrappedCommand(ChefCommand): | 111 class _WrappedCommand(ChefCommand): |
68 def __init__(self, func, name, description): | 112 def __init__(self, func, name, description): |
69 super(_WrappedCommand, self).__init__() | 113 super(_WrappedCommand, self).__init__() |