annotate 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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
1 import logging
57
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
2 import argparse
3
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
3 import functools
1
aaa8fb7c8918 Re-arranged modules to reduce dependencies to builtin stuff.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
4 from piecrust.pathutil import SiteNotFoundError
0
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
5
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
6
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
7 logger = logging.getLogger(__name__)
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
8
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
9
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
10 class CommandContext(object):
57
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
11 def __init__(self, app, parser, args):
1
aaa8fb7c8918 Re-arranged modules to reduce dependencies to builtin stuff.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
12 self.app = app
57
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
13 self.parser = parser
0
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
14 self.args = args
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
15
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
16
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
17 class ChefCommand(object):
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
18 def __init__(self):
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
19 self.name = '__unknown__'
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
20 self.description = '__unknown__'
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
21 self.requires_website = True
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
22
3
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
23 def setupParser(self, parser, app):
0
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
24 raise NotImplementedError()
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
25
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
26 def run(self, ctx):
57
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
27 raise NotImplementedError("Command '%s' doesn't implement the `run` "
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
28 "method." % type(self))
0
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
29
57
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
30 def checkedRun(self, ctx):
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
31 if ctx.app.root_dir is None and self.requires_website:
1
aaa8fb7c8918 Re-arranged modules to reduce dependencies to builtin stuff.
Ludovic Chabant <ludovic@chabant.com>
parents: 0
diff changeset
32 raise SiteNotFoundError()
57
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
33 return self.run(ctx)
3
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
34
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
35
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
36 class ExtendableChefCommand(ChefCommand):
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
37 def __init__(self):
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
38 super(ExtendableChefCommand, self).__init__()
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
39 self._extensions = None
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
40
99
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
41 def getExtensions(self, app):
3
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
42 self._loadExtensions(app)
99
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
43 return self._extensions
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
44
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
45 def setupExtensionParsers(self, subparsers, app):
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
46 for e in self.getExtensions(app):
3
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
47 p = subparsers.add_parser(e.name, help=e.description)
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
48 e.setupParser(p, app)
99
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
49 p.set_defaults(sub_func=e.checkedRun)
3
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
50
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
51 def _loadExtensions(self, app):
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
52 if self._extensions is not None:
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
53 return
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
54 self._extensions = []
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
55 for e in app.plugin_loader.getCommandExtensions():
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
56 if e.command_name == self.name and e.supports(app):
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
57 self._extensions.append(e)
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
58
0
a212a3f2e3ee Initial commit.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff changeset
59
99
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
60 class ChefCommandExtension(object):
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
61 command_name = '__unknown__'
3
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
62
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
63 def supports(self, app):
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
64 return True
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
65
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
66
99
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
67 class HelpCommand(ExtendableChefCommand):
57
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
68 def __init__(self):
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
69 super(HelpCommand, self).__init__()
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
70 self.name = 'help'
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
71 self.description = "Prints help about PieCrust's chef."
99
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
72 self._topic_providers = []
57
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
73
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
74 @property
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
75 def has_topics(self):
99
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
76 return len(self._topic_providers) > 0
57
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
77
99
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
78 def getTopics(self):
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
79 return [(n, d) for (n, d, e) in self._topic_providers]
57
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
80
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
81 def setupParser(self, parser, app):
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
82 parser.add_argument('topic', nargs='?',
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
83 help="The command name or topic on which to get help.")
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
84
99
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
85 extensions = self.getExtensions(app)
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
86 for ext in extensions:
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
87 for name, desc in ext.getHelpTopics():
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
88 self._topic_providers.append((name, desc, ext))
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
89
57
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
90 def run(self, ctx):
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
91 topic = ctx.args.topic
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
92
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
93 if topic is None:
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
94 ctx.parser.print_help()
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
95 return 0
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
96
99
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
97 for name, desc, ext in self._topic_providers:
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
98 if name == topic:
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
99 print(ext.getHelpTopic(topic, ctx.app))
8703be118430 Changes to `help` command and extendable commands:
Ludovic Chabant <ludovic@chabant.com>
parents: 57
diff changeset
100 return 0
57
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
101
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
102 for c in ctx.app.plugin_loader.getCommands():
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
103 if c.name == topic:
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
104 fake = argparse.ArgumentParser(
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
105 prog='%s %s' % (ctx.parser.prog, c.name),
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
106 description=c.description)
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
107 c.setupParser(fake, ctx.app)
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
108 fake.print_help()
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
109 return 0
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
110
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
111 raise Exception("No such command or topic: %s" % topic)
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
112
c8c522dacfea Add `help` function, cleanup argument handling.
Ludovic Chabant <ludovic@chabant.com>
parents: 3
diff changeset
113
3
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
114 class _WrappedCommand(ChefCommand):
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
115 def __init__(self, func, name, description):
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
116 super(_WrappedCommand, self).__init__()
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
117 self.func = func
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
118 self.name = name
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
119 self.description = description
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
120
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
121 def run(self, ctx):
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
122 self.func(ctx)
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
123
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
124
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
125 def simple_command(f, name, description=None):
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
126 @functools.wraps(f)
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
127 def wrapper(*args, **kwargs):
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
128 return f(*args, **kwargs)
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
129 cmd = _WrappedCommand(f, name, description)
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
130 f.__command_class__ = cmd
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
131 return wrapper
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
132
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
133
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
134 def get_func_command(f):
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
135 return getattr(f, '__command_class__')
f485ba500df3 Gigantic change to basically make PieCrust 2 vaguely functional.
Ludovic Chabant <ludovic@chabant.com>
parents: 1
diff changeset
136