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