##// END OF EJS Templates
add subcommand support
MinRK -
Show More
@@ -1,293 +1,360 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, Config
27 KeyValueConfigLoader, PyFileConfigLoader, Config
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, Instance
32 )
32 )
33 from IPython.utils.importstring import import_item
33 from IPython.utils.text import indent
34 from IPython.utils.text import indent
34
35
35 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
36 # Descriptions for the various sections
37 # Descriptions for the various sections
37 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
38
39
39 flag_description = """
40 flag_description = """
40 Flags are command-line arguments passed as '--<flag>'.
41 Flags are command-line arguments passed as '--<flag>'.
41 These take no parameters, unlike regular key-value arguments.
42 These take no parameters, unlike regular key-value arguments.
42 They are typically used for setting boolean flags, or enabling
43 They are typically used for setting boolean flags, or enabling
43 modes that involve setting multiple options together.
44 modes that involve setting multiple options together.
44 """.strip() # trim newlines of front and back
45 """.strip() # trim newlines of front and back
45
46
46 alias_description = """
47 alias_description = """
47 These are commonly set parameters, given abbreviated aliases for convenience.
48 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 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 <name> is replaced by the real parameter for which it is an alias.
50 """.strip() # trim newlines of front and back
51 """.strip() # trim newlines of front and back
51
52
52 keyvalue_description = """
53 keyvalue_description = """
53 Parameters are set from command-line arguments of the form:
54 Parameters are set from command-line arguments of the form:
54 `Class.trait=value`. Parameters will *never* be prefixed with '-'.
55 `Class.trait=value`. Parameters will *never* be prefixed with '-'.
55 This line is evaluated in Python, so simple expressions are allowed, e.g.
56 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 `C.a='range(3)'` For setting C.a=[0,1,2]
57 """.strip() # trim newlines of front and back
58 """.strip() # trim newlines of front and back
58
59
59 #-----------------------------------------------------------------------------
60 #-----------------------------------------------------------------------------
60 # Application class
61 # Application class
61 #-----------------------------------------------------------------------------
62 #-----------------------------------------------------------------------------
62
63
63
64
64 class ApplicationError(Exception):
65 class ApplicationError(Exception):
65 pass
66 pass
66
67
67
68
68 class Application(SingletonConfigurable):
69 class Application(SingletonConfigurable):
69 """A singleton application with full configuration support."""
70 """A singleton application with full configuration support."""
70
71
71 # The name of the application, will usually match the name of the command
72 # The name of the application, will usually match the name of the command
72 # line application
73 # line application
73 name = Unicode(u'application')
74 name = Unicode(u'application')
74
75
75 # The description of the application that is printed at the beginning
76 # The description of the application that is printed at the beginning
76 # of the help.
77 # of the help.
77 description = Unicode(u'This is an application.')
78 description = Unicode(u'This is an application.')
78 # default section descriptions
79 # default section descriptions
79 flag_description = Unicode(flag_description)
80 flag_description = Unicode(flag_description)
80 alias_description = Unicode(alias_description)
81 alias_description = Unicode(alias_description)
81 keyvalue_description = Unicode(keyvalue_description)
82 keyvalue_description = Unicode(keyvalue_description)
82
83
83
84
84 # A sequence of Configurable subclasses whose config=True attributes will
85 # A sequence of Configurable subclasses whose config=True attributes will
85 # be exposed at the command line.
86 # be exposed at the command line.
86 classes = List([])
87 classes = List([])
87
88
88 # The version string of this application.
89 # The version string of this application.
89 version = Unicode(u'0.0')
90 version = Unicode(u'0.0')
90
91
91 # The log level for the application
92 # The log level for the application
92 log_level = Enum((0,10,20,30,40,50), default_value=logging.WARN,
93 log_level = Enum((0,10,20,30,40,50), default_value=logging.WARN,
93 config=True,
94 config=True,
94 help="Set the log level.")
95 help="Set the log level.")
95
96
96 # the alias map for configurables
97 # the alias map for configurables
97 aliases = Dict(dict(log_level='Application.log_level'))
98 aliases = Dict(dict(log_level='Application.log_level'))
98
99
99 # flags for loading Configurables or store_const style flags
100 # flags for loading Configurables or store_const style flags
100 # flags are loaded from this dict by '--key' flags
101 # flags are loaded from this dict by '--key' flags
101 # this must be a dict of two-tuples, the first element being the Config/dict
102 # this must be a dict of two-tuples, the first element being the Config/dict
102 # and the second being the help string for the flag
103 # and the second being the help string for the flag
103 flags = Dict()
104 flags = Dict()
104
105
106 # subcommands for launching other applications
107 # if this is not empty, this will be a parent Application
108 # this must be a dict of two-tuples, the first element being the application class/import string
109 # and the second being the help string for the subcommand
110 subcommands = Dict()
111 # parse_command_line will initialize a subapp, if requested
112 subapp = Instance('IPython.config.application.Application', allow_none=True)
113
105
114
106 def __init__(self, **kwargs):
115 def __init__(self, **kwargs):
107 SingletonConfigurable.__init__(self, **kwargs)
116 SingletonConfigurable.__init__(self, **kwargs)
108 # Add my class to self.classes so my attributes appear in command line
117 # Add my class to self.classes so my attributes appear in command line
109 # options.
118 # options.
110 self.classes.insert(0, self.__class__)
119 self.classes.insert(0, self.__class__)
111
120
112 # ensure self.flags dict is valid
121 # ensure self.flags dict is valid
113 for key,value in self.flags.iteritems():
122 for key,value in self.flags.iteritems():
114 assert len(value) == 2, "Bad flag: %r:%s"%(key,value)
123 assert len(value) == 2, "Bad flag: %r:%s"%(key,value)
115 assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s"%(key,value)
124 assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s"%(key,value)
116 assert isinstance(value[1], basestring), "Bad flag: %r:%s"%(key,value)
125 assert isinstance(value[1], basestring), "Bad flag: %r:%s"%(key,value)
117 self.init_logging()
126 self.init_logging()
118
127
119 def _config_changed(self, name, old, new):
128 def _config_changed(self, name, old, new):
120 SingletonConfigurable._config_changed(self, name, old, new)
129 SingletonConfigurable._config_changed(self, name, old, new)
121 self.log.debug('Config changed:')
130 self.log.debug('Config changed:')
122 self.log.debug(repr(new))
131 self.log.debug(repr(new))
123
132
124 def init_logging(self):
133 def init_logging(self):
125 """Start logging for this application.
134 """Start logging for this application.
126
135
127 The default is to log to stdout using a StreaHandler. The log level
136 The default is to log to stdout using a StreaHandler. The log level
128 starts at loggin.WARN, but this can be adjusted by setting the
137 starts at loggin.WARN, but this can be adjusted by setting the
129 ``log_level`` attribute.
138 ``log_level`` attribute.
130 """
139 """
131 self.log = logging.getLogger(self.__class__.__name__)
140 self.log = logging.getLogger(self.__class__.__name__)
132 self.log.setLevel(self.log_level)
141 self.log.setLevel(self.log_level)
133 self._log_handler = logging.StreamHandler()
142 self._log_handler = logging.StreamHandler()
134 self._log_formatter = logging.Formatter("[%(name)s] %(message)s")
143 self._log_formatter = logging.Formatter("[%(name)s] %(message)s")
135 self._log_handler.setFormatter(self._log_formatter)
144 self._log_handler.setFormatter(self._log_formatter)
136 self.log.addHandler(self._log_handler)
145 self.log.addHandler(self._log_handler)
137
146
147 def initialize(self, argv=None):
148 """Do the basic steps to configure me.
149
150 Override in subclasses.
151 """
152 self.parse_command_line(argv)
153
154
155 def start(self):
156 """Start the app mainloop.
157
158 Override in subclasses.
159 """
160 if self.subapp is not None:
161 return self.subapp.start()
162
138 def _log_level_changed(self, name, old, new):
163 def _log_level_changed(self, name, old, new):
139 """Adjust the log level when log_level is set."""
164 """Adjust the log level when log_level is set."""
140 self.log.setLevel(new)
165 self.log.setLevel(new)
141
166
142 def print_alias_help(self):
167 def print_alias_help(self):
143 """print the alias part of the help"""
168 """print the alias part of the help"""
144 if not self.aliases:
169 if not self.aliases:
145 return
170 return
146
171
147 lines = ['Aliases']
172 lines = ['Aliases']
148 lines.append('_'*len(lines[0]))
173 lines.append('-'*len(lines[0]))
149 lines.append(self.alias_description)
174 lines.append(self.alias_description)
150 lines.append('')
175 lines.append('')
151
176
152 classdict = {}
177 classdict = {}
153 for c in self.classes:
178 for c in self.classes:
154 classdict[c.__name__] = c
179 classdict[c.__name__] = c
155
180
156 for alias, longname in self.aliases.iteritems():
181 for alias, longname in self.aliases.iteritems():
157 classname, traitname = longname.split('.',1)
182 classname, traitname = longname.split('.',1)
158 cls = classdict[classname]
183 cls = classdict[classname]
159
184
160 trait = cls.class_traits(config=True)[traitname]
185 trait = cls.class_traits(config=True)[traitname]
161 help = cls.class_get_trait_help(trait)
186 help = cls.class_get_trait_help(trait)
162 help = help.replace(longname, "%s (%s)"%(alias, longname), 1)
187 help = help.replace(longname, "%s (%s)"%(alias, longname), 1)
163 lines.append(help)
188 lines.append(help)
164 # header = "%s (%s) : %s"%(alias, longname, trait.__class__.__name__)
165 # lines.append(header)
166 # help = cls.class_get_trait_help(trait)
167 # if help:
168 # lines.append(indent(help, flatten=True))
169 lines.append('')
189 lines.append('')
170 print '\n'.join(lines)
190 print '\n'.join(lines)
171
191
172 def print_flag_help(self):
192 def print_flag_help(self):
173 """print the flag part of the help"""
193 """print the flag part of the help"""
174 if not self.flags:
194 if not self.flags:
175 return
195 return
176
196
177 lines = ['Flags']
197 lines = ['Flags']
178 lines.append('_'*len(lines[0]))
198 lines.append('-'*len(lines[0]))
179 lines.append(self.flag_description)
199 lines.append(self.flag_description)
180 lines.append('')
200 lines.append('')
181
201
182 for m, (cfg,help) in self.flags.iteritems():
202 for m, (cfg,help) in self.flags.iteritems():
183 lines.append('--'+m)
203 lines.append('--'+m)
184 lines.append(indent(help, flatten=True))
204 lines.append(indent(help, flatten=True))
185 lines.append('')
205 lines.append('')
186 print '\n'.join(lines)
206 print '\n'.join(lines)
187
207
208 def print_subcommands(self):
209 """print the subcommand part of the help"""
210 if not self.subcommands:
211 return
212
213 lines = ["Subcommands"]
214 lines.append('-'*len(lines[0]))
215 for subc, cls,help in self.subcommands:
216 lines.append("%s : %s"%(subc, cls))
217 if help:
218 lines.append(indent(help, flatten=True))
219 lines.append('')
220 print '\n'.join(lines)
221
188 def print_help(self, classes=False):
222 def print_help(self, classes=False):
189 """Print the help for each Configurable class in self.classes.
223 """Print the help for each Configurable class in self.classes.
190
224
191 If classes=False (the default), only flags and aliases are printed
225 If classes=False (the default), only flags and aliases are printed
192 """
226 """
193 self.print_flag_help()
227 self.print_flag_help()
194 self.print_alias_help()
228 self.print_alias_help()
195
229
196 if classes:
230 if classes:
197 if self.classes:
231 if self.classes:
198 print "Class parameters"
232 print "Class parameters"
199 print "----------------"
233 print "----------------"
200 print self.keyvalue_description
234 print self.keyvalue_description
201 print
235 print
202
236
203 for cls in self.classes:
237 for cls in self.classes:
204 cls.class_print_help()
238 cls.class_print_help()
205 print
239 print
206 else:
240 else:
207 print "To see all available configurables, use `--help-all`"
241 print "To see all available configurables, use `--help-all`"
208 print
242 print
209
243
210 def print_description(self):
244 def print_description(self):
211 """Print the application description."""
245 """Print the application description."""
212 print self.description
246 print self.description
213 print
247 print
214
248
215 def print_version(self):
249 def print_version(self):
216 """Print the version string."""
250 """Print the version string."""
217 print self.version
251 print self.version
218
252
219 def update_config(self, config):
253 def update_config(self, config):
220 """Fire the traits events when the config is updated."""
254 """Fire the traits events when the config is updated."""
221 # Save a copy of the current config.
255 # Save a copy of the current config.
222 newconfig = deepcopy(self.config)
256 newconfig = deepcopy(self.config)
223 # Merge the new config into the current one.
257 # Merge the new config into the current one.
224 newconfig._merge(config)
258 newconfig._merge(config)
225 # Save the combined config as self.config, which triggers the traits
259 # Save the combined config as self.config, which triggers the traits
226 # events.
260 # events.
227 self.config = newconfig
261 self.config = newconfig
228
262
263 def initialize_subcommand(self, subc, argv=None):
264 """Initialize a subcommand with argv"""
265 if '-h' in subc:
266 # requested help
267 self.print_description()
268 self.print_subcommands()
269 self.exit(0)
270 subapp = self.subcommands.get(subc, None)
271 if subapp is None:
272 self.print_description()
273 print "No such subcommand: %r"%subc
274 print
275 self.print_subcommands()
276 self.exit(1)
277
278 if isinstance(subapp, basestring):
279 subapp = import_item(subapp)
280
281 # instantiate
282 self.subapp = subapp()
283 # and initialize subapp
284 self.subapp.initialize(argv)
285
229 def parse_command_line(self, argv=None):
286 def parse_command_line(self, argv=None):
230 """Parse the command line arguments."""
287 """Parse the command line arguments."""
231 argv = sys.argv[1:] if argv is None else argv
288 argv = sys.argv[1:] if argv is None else argv
232
289
290 if self.subcommands:
291 # we have subcommands
292 if len(argv) == 0:
293 # none specified
294 self.print_description()
295 self.print_subcommands()
296 self.exit(1)
297
298 return self.initialize_subcommand(argv[0], argv[1:])
299
233 if '-h' in argv or '--help' in argv or '--help-all' in argv:
300 if '-h' in argv or '--help' in argv or '--help-all' in argv:
234 self.print_description()
301 self.print_description()
235 self.print_help('--help-all' in argv)
302 self.print_help('--help-all' in argv)
236 self.exit(0)
303 self.exit(0)
237
304
238 if '--version' in argv:
305 if '--version' in argv:
239 self.print_version()
306 self.print_version()
240 self.exit(0)
307 self.exit(0)
241
308
242 loader = KeyValueConfigLoader(argv=argv, aliases=self.aliases,
309 loader = KeyValueConfigLoader(argv=argv, aliases=self.aliases,
243 flags=self.flags)
310 flags=self.flags)
244 config = loader.load_config()
311 config = loader.load_config()
245 self.update_config(config)
312 self.update_config(config)
246
313
247 def load_config_file(self, filename, path=None):
314 def load_config_file(self, filename, path=None):
248 """Load a .py based config file by filename and path."""
315 """Load a .py based config file by filename and path."""
249 loader = PyFileConfigLoader(filename, path=path)
316 loader = PyFileConfigLoader(filename, path=path)
250 config = loader.load_config()
317 config = loader.load_config()
251 self.update_config(config)
318 self.update_config(config)
252
319
253 def exit(self, exit_status=0):
320 def exit(self, exit_status=0):
254 self.log.debug("Exiting application: %s" % self.name)
321 self.log.debug("Exiting application: %s" % self.name)
255 sys.exit(exit_status)
322 sys.exit(exit_status)
256
323
257 #-----------------------------------------------------------------------------
324 #-----------------------------------------------------------------------------
258 # utility functions, for convenience
325 # utility functions, for convenience
259 #-----------------------------------------------------------------------------
326 #-----------------------------------------------------------------------------
260
327
261 def boolean_flag(name, configurable, set_help='', unset_help=''):
328 def boolean_flag(name, configurable, set_help='', unset_help=''):
262 """helper for building basic --trait, --no-trait flags
329 """helper for building basic --trait, --no-trait flags
263
330
264 Parameters
331 Parameters
265 ----------
332 ----------
266
333
267 name : str
334 name : str
268 The name of the flag.
335 The name of the flag.
269 configurable : str
336 configurable : str
270 The 'Class.trait' string of the trait to be set/unset with the flag
337 The 'Class.trait' string of the trait to be set/unset with the flag
271 set_help : unicode
338 set_help : unicode
272 help string for --name flag
339 help string for --name flag
273 unset_help : unicode
340 unset_help : unicode
274 help string for --no-name flag
341 help string for --no-name flag
275
342
276 Returns
343 Returns
277 -------
344 -------
278
345
279 cfg : dict
346 cfg : dict
280 A dict with two keys: 'name', and 'no-name', for setting and unsetting
347 A dict with two keys: 'name', and 'no-name', for setting and unsetting
281 the trait, respectively.
348 the trait, respectively.
282 """
349 """
283 # default helpstrings
350 # default helpstrings
284 set_help = set_help or "set %s=True"%configurable
351 set_help = set_help or "set %s=True"%configurable
285 unset_help = unset_help or "set %s=False"%configurable
352 unset_help = unset_help or "set %s=False"%configurable
286
353
287 cls,trait = configurable.split('.')
354 cls,trait = configurable.split('.')
288
355
289 setter = Config()
356 setter = Config()
290 setter[cls][trait] = True
357 setter[cls][trait] = True
291 unsetter = Config()
358 unsetter = Config()
292 unsetter[cls][trait] = False
359 unsetter[cls][trait] = False
293 return {name : (setter, set_help), 'no-'+name : (unsetter, unset_help)}
360 return {name : (setter, set_help), 'no-'+name : (unsetter, unset_help)}
@@ -1,96 +1,101 b''
1 """A simple example of how to use IPython.config.application.Application.
1 """A simple example of how to use IPython.config.application.Application.
2
2
3 This should serve as a simple example that shows how the IPython config
3 This should serve as a simple example that shows how the IPython config
4 system works. The main classes are:
4 system works. The main classes are:
5
5
6 * IPython.config.configurable.Configurable
6 * IPython.config.configurable.Configurable
7 * IPython.config.configurable.SingletonConfigurable
7 * IPython.config.configurable.SingletonConfigurable
8 * IPython.config.loader.Config
8 * IPython.config.loader.Config
9 * IPython.config.application.Application
9 * IPython.config.application.Application
10
10
11 To see the command line option help, run this program from the command line::
11 To see the command line option help, run this program from the command line::
12
12
13 $ python appconfig.py -h
13 $ python appconfig.py -h
14
14
15 To make one of your classes configurable (from the command line and config
15 To make one of your classes configurable (from the command line and config
16 files) inherit from Configurable and declare class attributes as traits (see
16 files) inherit from Configurable and declare class attributes as traits (see
17 classes Foo and Bar below). To make the traits configurable, you will need
17 classes Foo and Bar below). To make the traits configurable, you will need
18 to set the following options:
18 to set the following options:
19
19
20 * ``config``: set to ``True`` to make the attribute configurable.
20 * ``config``: set to ``True`` to make the attribute configurable.
21 * ``shortname``: by default, configurable attributes are set using the syntax
21 * ``shortname``: by default, configurable attributes are set using the syntax
22 "Classname.attributename". At the command line, this is a bit verbose, so
22 "Classname.attributename". At the command line, this is a bit verbose, so
23 we allow "shortnames" to be declared. Setting a shortname is optional, but
23 we allow "shortnames" to be declared. Setting a shortname is optional, but
24 when you do this, you can set the option at the command line using the
24 when you do this, you can set the option at the command line using the
25 syntax: "shortname=value".
25 syntax: "shortname=value".
26 * ``help``: set the help string to display a help message when the ``-h``
26 * ``help``: set the help string to display a help message when the ``-h``
27 option is given at the command line. The help string should be valid ReST.
27 option is given at the command line. The help string should be valid ReST.
28
28
29 When the config attribute of an Application is updated, it will fire all of
29 When the config attribute of an Application is updated, it will fire all of
30 the trait's events for all of the config=True attributes.
30 the trait's events for all of the config=True attributes.
31 """
31 """
32
32
33 import sys
33 import sys
34
34
35 from IPython.config.configurable import Configurable
35 from IPython.config.configurable import Configurable
36 from IPython.config.application import Application
36 from IPython.config.application import Application
37 from IPython.utils.traitlets import (
37 from IPython.utils.traitlets import (
38 Bool, Unicode, Int, Float, List, Dict
38 Bool, Unicode, Int, Float, List, Dict
39 )
39 )
40
40
41
41
42 class Foo(Configurable):
42 class Foo(Configurable):
43 """A class that has configurable, typed attributes.
43 """A class that has configurable, typed attributes.
44
44
45 """
45 """
46
46
47 i = Int(0, config=True, help="The integer i.")
47 i = Int(0, config=True, help="The integer i.")
48 j = Int(1, config=True, help="The integer j.")
48 j = Int(1, config=True, help="The integer j.")
49 name = Unicode(u'Brian', config=True, help="First name.")
49 name = Unicode(u'Brian', config=True, help="First name.")
50
50
51
51
52 class Bar(Configurable):
52 class Bar(Configurable):
53
53
54 enabled = Bool(True, config=True, help="Enable bar.")
54 enabled = Bool(True, config=True, help="Enable bar.")
55
55
56
56
57 class MyApp(Application):
57 class MyApp(Application):
58
58
59 name = Unicode(u'myapp')
59 name = Unicode(u'myapp')
60 running = Bool(False, config=True,
60 running = Bool(False, config=True,
61 help="Is the app running?")
61 help="Is the app running?")
62 classes = List([Bar, Foo])
62 classes = List([Bar, Foo])
63 config_file = Unicode(u'', config=True,
63 config_file = Unicode(u'', config=True,
64 help="Load this config file")
64 help="Load this config file")
65
65
66 aliases = Dict(dict(i='Foo.i',j='Foo.j',name='Foo.name', running='MyApp.running',
66 aliases = Dict(dict(i='Foo.i',j='Foo.j',name='Foo.name', running='MyApp.running',
67 enabled='Bar.enabled', log_level='MyApp.log_level'))
67 enabled='Bar.enabled', log_level='MyApp.log_level'))
68
68
69 flags = Dict(dict(enable=({'Bar': {'enabled' : True}}, "Enable Bar"),
69 flags = Dict(dict(enable=({'Bar': {'enabled' : True}}, "Enable Bar"),
70 disable=({'Bar': {'enabled' : False}}, "Disable Bar"),
70 disable=({'Bar': {'enabled' : False}}, "Disable Bar"),
71 debug=({'MyApp':{'log_level':10}}, "Set loglevel to DEBUG")
71 debug=({'MyApp':{'log_level':10}}, "Set loglevel to DEBUG")
72 ))
72 ))
73
73
74 def init_foo(self):
74 def init_foo(self):
75 # Pass config to other classes for them to inherit the config.
75 # Pass config to other classes for them to inherit the config.
76 self.foo = Foo(config=self.config)
76 self.foo = Foo(config=self.config)
77
77
78 def init_bar(self):
78 def init_bar(self):
79 # Pass config to other classes for them to inherit the config.
79 # Pass config to other classes for them to inherit the config.
80 self.bar = Bar(config=self.config)
80 self.bar = Bar(config=self.config)
81
81
82 def initialize(self, argv=None):
83 self.parse_command_line(argv)
84 if self.config_file:
85 self.load_config_file(self.config_file)
86 self.init_foo()
87 self.init_bar()
88
89 def start(self):
90 print "app.config:"
91 print self.config
82
92
83
93
84 def main():
94 def main():
85 app = MyApp()
95 app = MyApp()
86 app.parse_command_line()
96 app.initialize()
87 if app.config_file:
97 app.start()
88 app.load_config_file(app.config_file)
89 app.init_foo()
90 app.init_bar()
91 print "app.config:"
92 print app.config
93
98
94
99
95 if __name__ == "__main__":
100 if __name__ == "__main__":
96 main()
101 main()
General Comments 0
You need to be logged in to leave comments. Login now