comparison piecrust/commands/base.py @ 99:8703be118430

Changes to `help` command and extendable commands: - The `help` command has a prettier output, with descriptions of help topics. - `ExtendableChefCommand` is not assuming extensions are sub-commands anymore.
author Ludovic Chabant <ludovic@chabant.com>
date Sat, 13 Sep 2014 14:47:01 -0700
parents c8c522dacfea
children 028df35a690e
comparison
equal deleted inserted replaced
98:5959a117a943 99:8703be118430
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__()
39 self._extensions = None 39 self._extensions = None
40 40
41 def setupParser(self, parser, app): 41 def getExtensions(self, app):
42 self._loadExtensions(app) 42 self._loadExtensions(app)
43 subparsers = parser.add_subparsers() 43 return self._extensions
44 for e in self._extensions: 44
45 def setupExtensionParsers(self, subparsers, app):
46 for e in self.getExtensions(app):
45 p = subparsers.add_parser(e.name, help=e.description) 47 p = subparsers.add_parser(e.name, help=e.description)
46 e.setupParser(p, app) 48 e.setupParser(p, app)
47 p.set_defaults(func=e.checkedRun) 49 p.set_defaults(sub_func=e.checkedRun)
48 50
49 def _loadExtensions(self, app): 51 def _loadExtensions(self, app):
50 if self._extensions is not None: 52 if self._extensions is not None:
51 return 53 return
52 self._extensions = [] 54 self._extensions = []
53 for e in app.plugin_loader.getCommandExtensions(): 55 for e in app.plugin_loader.getCommandExtensions():
54 if e.command_name == self.name and e.supports(app): 56 if e.command_name == self.name and e.supports(app):
55 self._extensions.append(e) 57 self._extensions.append(e)
56 58
57 59
58 class ChefCommandExtension(ChefCommand): 60 class ChefCommandExtension(object):
59 def __init__(self): 61 command_name = '__unknown__'
60 super(ChefCommandExtension, self).__init__()
61 self.command_name = '__unknown__'
62 62
63 def supports(self, app): 63 def supports(self, app):
64 return True 64 return True
65 65
66 66
67 class HelpCommand(ChefCommand): 67 class HelpCommand(ExtendableChefCommand):
68 def __init__(self): 68 def __init__(self):
69 super(HelpCommand, self).__init__() 69 super(HelpCommand, self).__init__()
70 self.name = 'help' 70 self.name = 'help'
71 self.description = "Prints help about PieCrust's chef." 71 self.description = "Prints help about PieCrust's chef."
72 self._topic_providers = {} 72 self._topic_providers = []
73 73
74 @property 74 @property
75 def has_topics(self): 75 def has_topics(self):
76 return any(self._topic_providers) 76 return len(self._topic_providers) > 0
77 77
78 def addTopic(self, name, provider): 78 def getTopics(self):
79 self._topic_providers[name] = provider 79 return [(n, d) for (n, d, e) in self._topic_providers]
80
81 def getTopicNames(self):
82 return self._topic_providers.keys()
83 80
84 def setupParser(self, parser, app): 81 def setupParser(self, parser, app):
85 parser.add_argument('topic', nargs='?', 82 parser.add_argument('topic', nargs='?',
86 help="The command name or topic on which to get help.") 83 help="The command name or topic on which to get help.")
84
85 extensions = self.getExtensions(app)
86 for ext in extensions:
87 for name, desc in ext.getHelpTopics():
88 self._topic_providers.append((name, desc, ext))
87 89
88 def run(self, ctx): 90 def run(self, ctx):
89 topic = ctx.args.topic 91 topic = ctx.args.topic
90 92
91 if topic is None: 93 if topic is None:
92 ctx.parser.print_help() 94 ctx.parser.print_help()
93 return 0 95 return 0
94 96
95 if topic in self._topic_providers: 97 for name, desc, ext in self._topic_providers:
96 print(self._topic_providers[topic].getHelpTopic(topic, ctx.app)) 98 if name == topic:
97 return 0 99 print(ext.getHelpTopic(topic, ctx.app))
100 return 0
98 101
99 for c in ctx.app.plugin_loader.getCommands(): 102 for c in ctx.app.plugin_loader.getCommands():
100 if c.name == topic: 103 if c.name == topic:
101 fake = argparse.ArgumentParser( 104 fake = argparse.ArgumentParser(
102 prog='%s %s' % (ctx.parser.prog, c.name), 105 prog='%s %s' % (ctx.parser.prog, c.name),