Show More
@@ -23,13 +23,15 b' 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.utils.traitlets import ( |
|
|||
27 | Unicode, List, Int, Enum |
|
|||
28 | ) |
|
|||
29 | from IPython.config.loader import ( |
|
26 | from IPython.config.loader import ( | |
30 | KeyValueConfigLoader, PyFileConfigLoader |
|
27 | KeyValueConfigLoader, PyFileConfigLoader | |
31 | ) |
|
28 | ) | |
32 |
|
29 | |||
|
30 | from IPython.utils.traitlets import ( | |||
|
31 | Unicode, List, Int, Enum, Dict | |||
|
32 | ) | |||
|
33 | from IPython.utils.text import indent | |||
|
34 | ||||
33 | #----------------------------------------------------------------------------- |
|
35 | #----------------------------------------------------------------------------- | |
34 | # Application class |
|
36 | # Application class | |
35 | #----------------------------------------------------------------------------- |
|
37 | #----------------------------------------------------------------------------- | |
@@ -55,16 +57,33 b' class Application(SingletonConfigurable):' | |||||
55 |
|
57 | |||
56 | # The log level for the application |
|
58 | # The log level for the application | |
57 | log_level = Enum((0,10,20,30,40,50), default_value=logging.WARN, |
|
59 | log_level = Enum((0,10,20,30,40,50), default_value=logging.WARN, | |
58 |
config=True, |
|
60 | config=True, | |
59 | help="Set the log level (0,10,20,30,40,50).") |
|
61 | help="Set the log level (0,10,20,30,40,50).") | |
|
62 | ||||
|
63 | # the shortname map for configurables | |||
|
64 | shortnames = Dict(dict(log_level='Application.log_level')) | |||
|
65 | ||||
|
66 | # macros for loading Configurables or store_const style flags | |||
|
67 | # macros are loaded from this dict by '--key' flags | |||
|
68 | macros = Dict() | |||
|
69 | # macro_help dict keys must match macros | |||
|
70 | macro_help = Dict() | |||
|
71 | ||||
60 |
|
72 | |||
61 | def __init__(self, **kwargs): |
|
73 | def __init__(self, **kwargs): | |
62 | SingletonConfigurable.__init__(self, **kwargs) |
|
74 | SingletonConfigurable.__init__(self, **kwargs) | |
63 | # Add my class to self.classes so my attributes appear in command line |
|
75 | # Add my class to self.classes so my attributes appear in command line | |
64 | # options. |
|
76 | # options. | |
65 | self.classes.insert(0, self.__class__) |
|
77 | self.classes.insert(0, self.__class__) | |
|
78 | ||||
|
79 | # check that macro_help has the right keys | |||
|
80 | # there is probably a better way to do this that doesn't use 2 dicts | |||
|
81 | keys = set(self.macros.keys()) | |||
|
82 | badkeys = keys.difference_update(set(self.macro_help.keys())) | |||
|
83 | if badkeys: | |||
|
84 | raise KeyError("macro %r has no help in `macro_help`!"%badkeys.pop()) | |||
66 | self.init_logging() |
|
85 | self.init_logging() | |
67 |
|
86 | |||
68 | def init_logging(self): |
|
87 | def init_logging(self): | |
69 | """Start logging for this application. |
|
88 | """Start logging for this application. | |
70 |
|
89 | |||
@@ -82,9 +101,45 b' class Application(SingletonConfigurable):' | |||||
82 | def _log_level_changed(self, name, old, new): |
|
101 | def _log_level_changed(self, name, old, new): | |
83 | """Adjust the log level when log_level is set.""" |
|
102 | """Adjust the log level when log_level is set.""" | |
84 | self.log.setLevel(new) |
|
103 | self.log.setLevel(new) | |
85 |
|
104 | |||
|
105 | def print_shortname_help(self): | |||
|
106 | """print the shortname part of the help""" | |||
|
107 | if not self.shortnames: | |||
|
108 | return | |||
|
109 | ||||
|
110 | print "Aliases" | |||
|
111 | print "-------" | |||
|
112 | classdict = {} | |||
|
113 | for c in self.classes: | |||
|
114 | classdict[c.__name__] = c | |||
|
115 | for shortname, longname in self.shortnames.iteritems(): | |||
|
116 | classname, traitname = longname.split('.',1) | |||
|
117 | cls = classdict[classname] | |||
|
118 | ||||
|
119 | trait = cls.class_traits(config=True)[traitname] | |||
|
120 | help = trait.get_metadata('help') | |||
|
121 | print shortname, "(%s)"%longname, ':', trait.__class__.__name__ | |||
|
122 | if help: | |||
|
123 | print indent(help) | |||
|
124 | ||||
|
125 | ||||
|
126 | def print_macro_help(self): | |||
|
127 | """print the the macro part of the help""" | |||
|
128 | if not self.macros: | |||
|
129 | return | |||
|
130 | ||||
|
131 | print "Flags" | |||
|
132 | print "-----" | |||
|
133 | ||||
|
134 | for m, cfg in self.macros.iteritems(): | |||
|
135 | print '--'+m | |||
|
136 | print indent(self.macro_help[m]) | |||
|
137 | ||||
|
138 | ||||
86 | def print_help(self): |
|
139 | def print_help(self): | |
87 | """Print the help for each Configurable class in self.classes.""" |
|
140 | """Print the help for each Configurable class in self.classes.""" | |
|
141 | self.print_macro_help() | |||
|
142 | self.print_shortname_help() | |||
88 | for cls in self.classes: |
|
143 | for cls in self.classes: | |
89 | cls.class_print_help() |
|
144 | cls.class_print_help() | |
90 |
|
145 | |||
@@ -112,7 +167,7 b' class Application(SingletonConfigurable):' | |||||
112 | """Parse the command line arguments.""" |
|
167 | """Parse the command line arguments.""" | |
113 | argv = sys.argv[1:] if argv is None else argv |
|
168 | argv = sys.argv[1:] if argv is None else argv | |
114 |
|
169 | |||
115 | if '-h' in argv or '--h' in argv: |
|
170 | if '-h' in argv or '--help' in argv: | |
116 | self.print_description() |
|
171 | self.print_description() | |
117 | self.print_help() |
|
172 | self.print_help() | |
118 | sys.exit(1) |
|
173 | sys.exit(1) | |
@@ -121,7 +176,8 b' class Application(SingletonConfigurable):' | |||||
121 | self.print_version() |
|
176 | self.print_version() | |
122 | sys.exit(1) |
|
177 | sys.exit(1) | |
123 |
|
178 | |||
124 |
loader = KeyValueConfigLoader(argv=argv, |
|
179 | loader = KeyValueConfigLoader(argv=argv, shortnames=self.shortnames, | |
|
180 | macros=self.macros) | |||
125 | config = loader.load_config() |
|
181 | config = loader.load_config() | |
126 | self.update_config(config) |
|
182 | self.update_config(config) | |
127 |
|
183 |
@@ -140,18 +140,6 b' class Configurable(HasTraits):' | |||||
140 | setattr(self, k, deepcopy(config_value)) |
|
140 | setattr(self, k, deepcopy(config_value)) | |
141 |
|
141 | |||
142 | @classmethod |
|
142 | @classmethod | |
143 | def class_get_shortnames(cls): |
|
|||
144 | """Return the shortname to fullname dict for config=True traits.""" |
|
|||
145 | cls_traits = cls.class_traits(config=True) |
|
|||
146 | shortnames = {} |
|
|||
147 | for k, v in cls_traits.items(): |
|
|||
148 | shortname = v.get_metadata('shortname') |
|
|||
149 | if shortname is not None: |
|
|||
150 | longname = cls.__name__ + '.' + k |
|
|||
151 | shortnames[shortname] = longname |
|
|||
152 | return shortnames |
|
|||
153 |
|
||||
154 | @classmethod |
|
|||
155 | def class_get_help(cls): |
|
143 | def class_get_help(cls): | |
156 | """Get the help string for this class in ReST format.""" |
|
144 | """Get the help string for this class in ReST format.""" | |
157 | cls_traits = cls.class_traits(config=True) |
|
145 | cls_traits = cls.class_traits(config=True) | |
@@ -160,10 +148,7 b' class Configurable(HasTraits):' | |||||
160 | final_help.append(len(final_help[0])*u'-') |
|
148 | final_help.append(len(final_help[0])*u'-') | |
161 | for k, v in cls_traits.items(): |
|
149 | for k, v in cls_traits.items(): | |
162 | help = v.get_metadata('help') |
|
150 | help = v.get_metadata('help') | |
163 | shortname = v.get_metadata('shortname') |
|
|||
164 | header = "%s.%s : %s" % (cls.__name__, k, v.__class__.__name__) |
|
151 | header = "%s.%s : %s" % (cls.__name__, k, v.__class__.__name__) | |
165 | if shortname is not None: |
|
|||
166 | header += " (shortname=" + shortname + ")" |
|
|||
167 | final_help.append(header) |
|
152 | final_help.append(header) | |
168 | if help is not None: |
|
153 | if help is not None: | |
169 | final_help.append(indent(help)) |
|
154 | final_help.append(indent(help)) |
@@ -18,6 +18,7 b' Authors' | |||||
18 | #----------------------------------------------------------------------------- |
|
18 | #----------------------------------------------------------------------------- | |
19 |
|
19 | |||
20 | import __builtin__ |
|
20 | import __builtin__ | |
|
21 | import re | |||
21 | import sys |
|
22 | import sys | |
22 |
|
23 | |||
23 | from IPython.external import argparse |
|
24 | from IPython.external import argparse | |
@@ -303,6 +304,8 b' class CommandLineConfigLoader(ConfigLoader):' | |||||
303 | here. |
|
304 | here. | |
304 | """ |
|
305 | """ | |
305 |
|
306 | |||
|
307 | kv_pattern = re.compile(r'[A-Za-z]\w*(\.\w+)*\=.+') | |||
|
308 | macro_pattern = re.compile(r'\-\-\w+(\-\w)*') | |||
306 |
|
309 | |||
307 | class KeyValueConfigLoader(CommandLineConfigLoader): |
|
310 | class KeyValueConfigLoader(CommandLineConfigLoader): | |
308 | """A config loader that loads key value pairs from the command line. |
|
311 | """A config loader that loads key value pairs from the command line. | |
@@ -312,7 +315,7 b' class KeyValueConfigLoader(CommandLineConfigLoader):' | |||||
312 | ipython Global.profile="foo" InteractiveShell.autocall=False |
|
315 | ipython Global.profile="foo" InteractiveShell.autocall=False | |
313 | """ |
|
316 | """ | |
314 |
|
317 | |||
315 |
def __init__(self, argv=None, |
|
318 | def __init__(self, argv=None, shortnames=None, macros=None): | |
316 | """Create a key value pair config loader. |
|
319 | """Create a key value pair config loader. | |
317 |
|
320 | |||
318 | Parameters |
|
321 | Parameters | |
@@ -321,9 +324,14 b' class KeyValueConfigLoader(CommandLineConfigLoader):' | |||||
321 | A list that has the form of sys.argv[1:] which has unicode |
|
324 | A list that has the form of sys.argv[1:] which has unicode | |
322 | elements of the form u"key=value". If this is None (default), |
|
325 | elements of the form u"key=value". If this is None (default), | |
323 | then sys.argv[1:] will be used. |
|
326 | then sys.argv[1:] will be used. | |
324 | classes : (list, tuple) of Configurables |
|
327 | shortnames : dict | |
325 | A sequence of Configurable classes that will be used to map |
|
328 | A dict of aliases for configurable traits. | |
326 | shortnames to longnames. |
|
329 | Keys are the short aliases, Values are the resolved trait. | |
|
330 | Of the form: `{'shortname' : 'Configurable.trait'}` | |||
|
331 | macros : dict | |||
|
332 | A dict of macros, keyed by str name. Vaues can be Config objects, | |||
|
333 | dicts, or "key=value" strings. If Config or dict, when the macro | |||
|
334 | is triggered, The macro is loaded as `self.config.update(m)`. | |||
327 |
|
335 | |||
328 | Returns |
|
336 | Returns | |
329 | ------- |
|
337 | ------- | |
@@ -340,12 +348,11 b' class KeyValueConfigLoader(CommandLineConfigLoader):' | |||||
340 | """ |
|
348 | """ | |
341 | if argv is None: |
|
349 | if argv is None: | |
342 | argv = sys.argv[1:] |
|
350 | argv = sys.argv[1:] | |
343 | if classes is None: |
|
|||
344 | classes = () |
|
|||
345 | self.argv = argv |
|
351 | self.argv = argv | |
346 |
self. |
|
352 | self.shortnames = shortnames or {} | |
|
353 | self.macros = macros or {} | |||
347 |
|
354 | |||
348 |
def load_config(self, argv=None, |
|
355 | def load_config(self, argv=None, shortnames=None, macros=None): | |
349 | """Parse the configuration and generate the Config object. |
|
356 | """Parse the configuration and generate the Config object. | |
350 |
|
357 | |||
351 | Parameters |
|
358 | Parameters | |
@@ -354,37 +361,28 b' class KeyValueConfigLoader(CommandLineConfigLoader):' | |||||
354 | A list that has the form of sys.argv[1:] which has unicode |
|
361 | A list that has the form of sys.argv[1:] which has unicode | |
355 | elements of the form u"key=value". If this is None (default), |
|
362 | elements of the form u"key=value". If this is None (default), | |
356 | then self.argv will be used. |
|
363 | then self.argv will be used. | |
357 | classes : (list, tuple) of Configurables |
|
364 | shortnames : dict | |
358 | A sequence of Configurable classes that will be used to map |
|
365 | A dict of aliases for configurable traits. | |
359 | shortnames to longnames. |
|
366 | Keys are the short aliases, Values are the resolved trait. | |
|
367 | Of the form: `{'shortname' : 'Configurable.trait'}` | |||
|
368 | macros : dict | |||
|
369 | A dict of macros, keyed by str name. Vaues can be Config objects, | |||
|
370 | dicts, or "key=value" strings. If Config or dict, when the macro | |||
|
371 | is triggered, The macro is loaded as `self.config.update(m)`. | |||
360 | """ |
|
372 | """ | |
361 | from IPython.config.configurable import Configurable |
|
373 | from IPython.config.configurable import Configurable | |
362 |
|
374 | |||
363 | self.clear() |
|
375 | self.clear() | |
364 | if argv is None: |
|
376 | if argv is None: | |
365 | argv = self.argv |
|
377 | argv = self.argv | |
366 |
if |
|
378 | if shortnames is None: | |
367 |
|
|
379 | shortnames = self.shortnames | |
368 |
|
380 | if macros is None: | ||
369 | # Create the mapping between shortnames and longnames. |
|
381 | macros = self.macros | |
370 | shortnames = {} |
|
|||
371 | for cls in classes: |
|
|||
372 | if issubclass(cls, Configurable): |
|
|||
373 | sn = cls.class_get_shortnames() |
|
|||
374 | # Check for duplicate shortnames and raise if found. |
|
|||
375 | for k, v in sn.items(): |
|
|||
376 | if k in shortnames: |
|
|||
377 | raise KeyError( |
|
|||
378 | 'Duplicate shortname: both %s and %s use the shortname: "%s"' %\ |
|
|||
379 | (v, shortnames[k], k) |
|
|||
380 | ) |
|
|||
381 | shortnames.update(sn) |
|
|||
382 |
|
382 | |||
383 | for item in argv: |
|
383 | for item in argv: | |
384 | pair = tuple(item.split("=")) |
|
384 | if kv_pattern.match(item): | |
385 | if len(pair) == 2: |
|
385 | lhs,rhs = item.split('=',1) | |
386 | lhs = pair[0] |
|
|||
387 | rhs = pair[1] |
|
|||
388 | # Substitute longnames for shortnames. |
|
386 | # Substitute longnames for shortnames. | |
389 | if lhs in shortnames: |
|
387 | if lhs in shortnames: | |
390 | lhs = shortnames[lhs] |
|
388 | lhs = shortnames[lhs] | |
@@ -400,9 +398,26 b' class KeyValueConfigLoader(CommandLineConfigLoader):' | |||||
400 | # it succeeds. If it still fails, we let it raise. |
|
398 | # it succeeds. If it still fails, we let it raise. | |
401 | exec_str = 'self.config.' + lhs + '="' + rhs + '"' |
|
399 | exec_str = 'self.config.' + lhs + '="' + rhs + '"' | |
402 | exec exec_str in locals(), globals() |
|
400 | exec exec_str in locals(), globals() | |
|
401 | elif macro_pattern.match(item): | |||
|
402 | # trim leading '--' | |||
|
403 | m = item[2:] | |||
|
404 | macro = macros.get(m, None) | |||
|
405 | if macro is None: | |||
|
406 | raise ValueError("Unrecognized argument: %r"%item) | |||
|
407 | macro = macros[m] | |||
|
408 | if isinstance(macro, basestring): | |||
|
409 | # macro is simply a 'Class.trait=value' string | |||
|
410 | exec_str = 'self.config.' + macro | |||
|
411 | exec exec_str in locals(), globals() | |||
|
412 | elif isinstance(macro, (dict, Configurable)): | |||
|
413 | # update self.config with Config: | |||
|
414 | self.config.update(macros[m]) | |||
|
415 | else: | |||
|
416 | raise ValueError("Invalid macro: %r"%macro) | |||
|
417 | else: | |||
|
418 | raise ValueError("Invalid argument: %r"%item) | |||
403 | return self.config |
|
419 | return self.config | |
404 |
|
420 | |||
405 |
|
||||
406 | class ArgParseConfigLoader(CommandLineConfigLoader): |
|
421 | class ArgParseConfigLoader(CommandLineConfigLoader): | |
407 | """A loader that uses the argparse module to load from the command line.""" |
|
422 | """A loader that uses the argparse module to load from the command line.""" | |
408 |
|
423 |
@@ -35,14 +35,14 b' from IPython.utils.traitlets import (' | |||||
35 |
|
35 | |||
36 | class Foo(Configurable): |
|
36 | class Foo(Configurable): | |
37 |
|
37 | |||
38 |
i = Int(0, config=True, |
|
38 | i = Int(0, config=True, help="The integer i.") | |
39 |
j = Int(1, config=True, |
|
39 | j = Int(1, config=True, help="The integer j.") | |
40 |
name = Unicode(u'Brian', config=True, |
|
40 | name = Unicode(u'Brian', config=True, help="First name.") | |
41 |
|
41 | |||
42 |
|
42 | |||
43 | class Bar(Configurable): |
|
43 | class Bar(Configurable): | |
44 |
|
44 | |||
45 |
enabled = Bool(True, config=True, |
|
45 | enabled = Bool(True, config=True, help="Enable bar.") | |
46 |
|
46 | |||
47 |
|
47 | |||
48 | class MyApp(Application): |
|
48 | class MyApp(Application): | |
@@ -54,6 +54,15 b' class MyApp(Application):' | |||||
54 | config_file = Unicode(u'', config=True, shortname="config_file", |
|
54 | config_file = Unicode(u'', config=True, shortname="config_file", | |
55 | help="Load this config file") |
|
55 | help="Load this config file") | |
56 |
|
56 | |||
|
57 | shortnames = dict(i='Foo.i',j='Foo.j',name='Foo.name', | |||
|
58 | enabled='Bar.enabled', log_level='MyApp.log_level') | |||
|
59 | ||||
|
60 | macros = dict(enable='Bar.enabled=True', disable='Bar.enabled=False') | |||
|
61 | ||||
|
62 | macro_help = dict( | |||
|
63 | enable="""Enable bar""", | |||
|
64 | disable="""Disable bar""" | |||
|
65 | ) | |||
57 | def init_foo(self): |
|
66 | def init_foo(self): | |
58 | self.foo = Foo(config=self.config) |
|
67 | self.foo = Foo(config=self.config) | |
59 |
|
68 | |||
@@ -88,3 +97,12 b' class TestApplication(TestCase):' | |||||
88 | self.assertEquals(app.foo.j, 10) |
|
97 | self.assertEquals(app.foo.j, 10) | |
89 | self.assertEquals(app.bar.enabled, False) |
|
98 | self.assertEquals(app.bar.enabled, False) | |
90 |
|
99 | |||
|
100 | def test_macro(self): | |||
|
101 | app = MyApp() | |||
|
102 | app.parse_command_line(["--disable"]) | |||
|
103 | app.init_bar() | |||
|
104 | self.assertEquals(app.bar.enabled, False) | |||
|
105 | app.parse_command_line(["--enable"]) | |||
|
106 | app.init_bar() | |||
|
107 | self.assertEquals(app.bar.enabled, True) | |||
|
108 |
@@ -40,26 +40,26 b' from IPython.config.loader import Config' | |||||
40 |
|
40 | |||
41 |
|
41 | |||
42 | class MyConfigurable(Configurable): |
|
42 | class MyConfigurable(Configurable): | |
43 |
a = Int(1, config=True, |
|
43 | a = Int(1, config=True, help="The integer a.") | |
44 |
b = Float(1.0, config=True, |
|
44 | b = Float(1.0, config=True, help="The integer b.") | |
45 | c = Str('no config') |
|
45 | c = Str('no config') | |
46 |
|
46 | |||
47 |
|
47 | |||
48 | mc_help=u"""MyConfigurable options |
|
48 | mc_help=u"""MyConfigurable options | |
49 | ---------------------- |
|
49 | ---------------------- | |
50 |
MyConfigurable.a : Int |
|
50 | MyConfigurable.a : Int | |
51 | The integer a. |
|
51 | The integer a. | |
52 |
MyConfigurable.b : Float |
|
52 | MyConfigurable.b : Float | |
53 | The integer b.""" |
|
53 | The integer b.""" | |
54 |
|
54 | |||
55 | class Foo(Configurable): |
|
55 | class Foo(Configurable): | |
56 |
a = Int(0, config=True, |
|
56 | a = Int(0, config=True, help="The integer a.") | |
57 | b = Str('nope', config=True) |
|
57 | b = Str('nope', config=True) | |
58 |
|
58 | |||
59 |
|
59 | |||
60 | class Bar(Foo): |
|
60 | class Bar(Foo): | |
61 |
b = Str('gotit', config=False, |
|
61 | b = Str('gotit', config=False, help="The string b.") | |
62 |
c = Float(config=True, |
|
62 | c = Float(config=True, help="The string c.") | |
63 |
|
63 | |||
64 |
|
64 | |||
65 | class TestConfigurable(TestCase): |
|
65 | class TestConfigurable(TestCase): | |
@@ -135,14 +135,6 b' class TestConfigurable(TestCase):' | |||||
135 | self.assertEquals(c.b, 'and') |
|
135 | self.assertEquals(c.b, 'and') | |
136 | self.assertEquals(c.c, 20.0) |
|
136 | self.assertEquals(c.c, 20.0) | |
137 |
|
137 | |||
138 | def test_shortnames(self): |
|
|||
139 | sn = MyConfigurable.class_get_shortnames() |
|
|||
140 | self.assertEquals(sn, {'a': 'MyConfigurable.a', 'b': 'MyConfigurable.b'}) |
|
|||
141 | sn = Foo.class_get_shortnames() |
|
|||
142 | self.assertEquals(sn, {'a': 'Foo.a'}) |
|
|||
143 | sn = Bar.class_get_shortnames() |
|
|||
144 | self.assertEquals(sn, {'a': 'Bar.a', 'c': 'Bar.c'}) |
|
|||
145 |
|
||||
146 | def test_help(self): |
|
138 | def test_help(self): | |
147 | self.assertEquals(MyConfigurable.class_get_help(), mc_help) |
|
139 | self.assertEquals(MyConfigurable.class_get_help(), mc_help) | |
148 |
|
140 |
@@ -124,23 +124,6 b' class TestKeyValueCL(TestCase):' | |||||
124 | self.assertEquals(config.Foo.Bam.value, range(10)) |
|
124 | self.assertEquals(config.Foo.Bam.value, range(10)) | |
125 | self.assertEquals(config.D.C.value, 'hi there') |
|
125 | self.assertEquals(config.D.C.value, 'hi there') | |
126 |
|
126 | |||
127 | def test_shortname(self): |
|
|||
128 | class Foo(Configurable): |
|
|||
129 | i = Int(0, config=True, shortname="i") |
|
|||
130 | s = Unicode('hi', config=True, shortname="s") |
|
|||
131 | cl = KeyValueConfigLoader() |
|
|||
132 | config = cl.load_config(["i=20", "s=there"], classes=[Foo]) |
|
|||
133 | self.assertEquals(config.Foo.i, 20) |
|
|||
134 | self.assertEquals(config.Foo.s, "there") |
|
|||
135 |
|
||||
136 | def test_duplicate(self): |
|
|||
137 | class Foo(Configurable): |
|
|||
138 | i = Int(0, config=True, shortname="i") |
|
|||
139 | class Bar(Configurable): |
|
|||
140 | i = Int(0, config=True, shortname="i") |
|
|||
141 | cl = KeyValueConfigLoader() |
|
|||
142 | self.assertRaises(KeyError, cl.load_config, ["i=20", "s=there"], classes=[Foo, Bar]) |
|
|||
143 |
|
||||
144 |
|
127 | |||
145 | class TestConfig(TestCase): |
|
128 | class TestConfig(TestCase): | |
146 |
|
129 |
@@ -62,6 +62,15 b' class MyApp(Application):' | |||||
62 | classes = List([Bar, Foo]) |
|
62 | classes = List([Bar, Foo]) | |
63 | config_file = Unicode(u'', config=True, shortname="config_file", |
|
63 | config_file = Unicode(u'', config=True, shortname="config_file", | |
64 | help="Load this config file") |
|
64 | help="Load this config file") | |
|
65 | ||||
|
66 | shortnames = dict(i='Foo.i',j='Foo.j',name='Foo.name', | |||
|
67 | enabled='Bar.enabled') | |||
|
68 | ||||
|
69 | macros = dict(enable='Bar.enabled=True', disable='Bar.enabled=False') | |||
|
70 | macro_help = dict( | |||
|
71 | enable="""Set Bar.enabled to True""", | |||
|
72 | disable="""Set Bar.enabled to False""" | |||
|
73 | ) | |||
65 |
|
74 | |||
66 | def init_foo(self): |
|
75 | def init_foo(self): | |
67 | # Pass config to other classes for them to inherit the config. |
|
76 | # Pass config to other classes for them to inherit the config. |
General Comments 0
You need to be logged in to leave comments.
Login now