##// END OF EJS Templates
add descriptions for the various help sections
MinRK -
Show More
@@ -1,190 +1,231 b''
1 1 # encoding: utf-8
2 2 """
3 3 A base class for a configurable application.
4 4
5 5 Authors:
6 6
7 7 * Brian Granger
8 8 """
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Copyright (C) 2008-2011 The IPython Development Team
12 12 #
13 13 # Distributed under the terms of the BSD License. The full license is in
14 14 # the file COPYING, distributed as part of this software.
15 15 #-----------------------------------------------------------------------------
16 16
17 17 #-----------------------------------------------------------------------------
18 18 # Imports
19 19 #-----------------------------------------------------------------------------
20 20
21 21 from copy import deepcopy
22 22 import logging
23 23 import sys
24 24
25 25 from IPython.config.configurable import SingletonConfigurable
26 26 from IPython.config.loader import (
27 27 KeyValueConfigLoader, PyFileConfigLoader
28 28 )
29 29
30 30 from IPython.utils.traitlets import (
31 31 Unicode, List, Int, Enum, Dict
32 32 )
33 33 from IPython.utils.text import indent
34 34
35 35 #-----------------------------------------------------------------------------
36 # Descriptions for
37 #-----------------------------------------------------------------------------
38
39 macro_description = """
40 Flags are command-line arguments passed as '--<flag>'.
41 These take no parameters, unlike regular key-value arguments.
42 They are typically used for setting boolean flags, or enabling
43 modes that involve setting multiple options together.
44 """.strip() # trim newlines of front and back
45
46 shortname_description = """
47 These are commonly set parameters, given abbreviated aliases for convenience.
48 They are set in the same `name=value` way as class parameters, where
49 <name> is replaced by the real parameter for which it is an alias.
50 """.strip() # trim newlines of front and back
51
52 keyvalue_description = """
53 Parameters are set from command-line arguments of the form:
54 `Class.trait=value`. Parameters will *never* be prefixed with '-'.
55 This line is evaluated in Python, so simple expressions are allowed, e.g.
56 `C.a='range(3)'` For setting C.a=[0,1,2]
57 """.strip() # trim newlines of front and back
58
59 #-----------------------------------------------------------------------------
36 60 # Application class
37 61 #-----------------------------------------------------------------------------
38 62
39 63
40 64 class Application(SingletonConfigurable):
41 65 """A singleton application with full configuration support."""
42 66
43 67 # The name of the application, will usually match the name of the command
44 68 # line application
45 69 app_name = Unicode(u'application')
46 70
47 71 # The description of the application that is printed at the beginning
48 72 # of the help.
49 73 description = Unicode(u'This is an application.')
74 # default section descriptions
75 macro_description = Unicode(macro_description)
76 shortname_description = Unicode(shortname_description)
77 keyvalue_description = Unicode(keyvalue_description)
78
50 79
51 80 # A sequence of Configurable subclasses whose config=True attributes will
52 81 # be exposed at the command line (shortnames and help).
53 82 classes = List([])
54 83
55 84 # The version string of this application.
56 85 version = Unicode(u'0.0')
57 86
58 87 # The log level for the application
59 88 log_level = Enum((0,10,20,30,40,50), default_value=logging.WARN,
60 89 config=True,
61 90 help="Set the log level (0,10,20,30,40,50).")
62 91
63 92 # the shortname map for configurables
64 93 shortnames = Dict(dict(log_level='Application.log_level'))
65 94
66 95 # macros for loading Configurables or store_const style flags
67 96 # macros are loaded from this dict by '--key' flags
68 97 macros = Dict()
69 98 # macro_help dict keys must match macros
70 99 macro_help = Dict()
71 100
72 101
73 102 def __init__(self, **kwargs):
74 103 SingletonConfigurable.__init__(self, **kwargs)
75 104 # Add my class to self.classes so my attributes appear in command line
76 105 # options.
77 106 self.classes.insert(0, self.__class__)
78 107
79 108 # check that macro_help has the right keys
80 109 # there is probably a better way to do this that doesn't use 2 dicts
81 110 keys = set(self.macros.keys())
82 111 badkeys = keys.difference_update(set(self.macro_help.keys()))
83 112 if badkeys:
84 113 raise KeyError("macro %r has no help in `macro_help`!"%badkeys.pop())
85 114 self.init_logging()
86 115
87 116 def init_logging(self):
88 117 """Start logging for this application.
89 118
90 119 The default is to log to stdout using a StreaHandler. The log level
91 120 starts at loggin.WARN, but this can be adjusted by setting the
92 121 ``log_level`` attribute.
93 122 """
94 123 self.log = logging.getLogger(self.__class__.__name__)
95 124 self.log.setLevel(self.log_level)
96 125 self._log_handler = logging.StreamHandler()
97 126 self._log_formatter = logging.Formatter("[%(name)s] %(message)s")
98 127 self._log_handler.setFormatter(self._log_formatter)
99 128 self.log.addHandler(self._log_handler)
100 129
101 130 def _log_level_changed(self, name, old, new):
102 131 """Adjust the log level when log_level is set."""
103 132 self.log.setLevel(new)
104 133
105 134 def print_shortname_help(self):
106 135 """print the shortname part of the help"""
107 136 if not self.shortnames:
108 137 return
109 138
110 139 print "Aliases"
111 140 print "-------"
141 print self.shortname_description
142 print
143
112 144 classdict = {}
113 145 for c in self.classes:
114 146 classdict[c.__name__] = c
147
115 148 for shortname, longname in self.shortnames.iteritems():
116 149 classname, traitname = longname.split('.',1)
117 150 cls = classdict[classname]
118 151
119 152 trait = cls.class_traits(config=True)[traitname]
120 153 help = trait.get_metadata('help')
121 154 print shortname, "(%s)"%longname, ':', trait.__class__.__name__
122 155 if help:
123 156 print indent(help)
124 157 print
125 158
126 159 def print_macro_help(self):
127 160 """print the the macro part of the help"""
128 161 if not self.macros:
129 162 return
130 163
131 164 print "Flags"
132 165 print "-----"
166 print self.macro_description
167 print
133 168
134 169 for m, cfg in self.macros.iteritems():
135 170 print '--'+m
136 171 print indent(self.macro_help[m])
137 172 print
138 173
139 174 def print_help(self):
140 175 """Print the help for each Configurable class in self.classes."""
141 176 self.print_macro_help()
142 177 self.print_shortname_help()
178 if self.classes:
179 print "Class parameters"
180 print "----------------"
181 print self.keyvalue_description
182 print
183
143 184 for cls in self.classes:
144 185 cls.class_print_help()
145 186 print
146 187
147 188 def print_description(self):
148 189 """Print the application description."""
149 190 print self.description
150 191 print
151 192
152 193 def print_version(self):
153 194 """Print the version string."""
154 195 print self.version
155 196
156 197 def update_config(self, config):
157 198 """Fire the traits events when the config is updated."""
158 199 # Save a copy of the current config.
159 200 newconfig = deepcopy(self.config)
160 201 # Merge the new config into the current one.
161 202 newconfig._merge(config)
162 203 # Save the combined config as self.config, which triggers the traits
163 204 # events.
164 205 self.config = config
165 206
166 207 def parse_command_line(self, argv=None):
167 208 """Parse the command line arguments."""
168 209 argv = sys.argv[1:] if argv is None else argv
169 210
170 211 if '-h' in argv or '--help' in argv:
171 212 self.print_description()
172 213 self.print_help()
173 214 sys.exit(1)
174 215
175 216 if '--version' in argv:
176 217 self.print_version()
177 218 sys.exit(1)
178 219
179 220 loader = KeyValueConfigLoader(argv=argv, shortnames=self.shortnames,
180 221 macros=self.macros)
181 222 config = loader.load_config()
182 223 self.update_config(config)
183 224
184 225 def load_config_file(self, filename, path=None):
185 226 """Load a .py based config file by filename and path."""
186 227 # TODO: this raises IOError if filename does not exist.
187 228 loader = PyFileConfigLoader(filename, path=path)
188 229 config = loader.load_config()
189 230 self.update_config(config)
190 231
General Comments 0
You need to be logged in to leave comments. Login now