Show More
@@ -24,7 +24,7 import sys | |||
|
24 | 24 | |
|
25 | 25 | from IPython.config.configurable import SingletonConfigurable |
|
26 | 26 | from IPython.config.loader import ( |
|
27 | KeyValueConfigLoader, PyFileConfigLoader | |
|
27 | KeyValueConfigLoader, PyFileConfigLoader, Config | |
|
28 | 28 | ) |
|
29 | 29 | |
|
30 | 30 | from IPython.utils.traitlets import ( |
@@ -36,14 +36,14 from IPython.utils.text import indent | |||
|
36 | 36 | # Descriptions for |
|
37 | 37 | #----------------------------------------------------------------------------- |
|
38 | 38 | |
|
39 |
|
|
|
39 | flag_description = """ | |
|
40 | 40 | Flags are command-line arguments passed as '--<flag>'. |
|
41 | 41 | These take no parameters, unlike regular key-value arguments. |
|
42 | 42 | They are typically used for setting boolean flags, or enabling |
|
43 | 43 | modes that involve setting multiple options together. |
|
44 | 44 | """.strip() # trim newlines of front and back |
|
45 | 45 | |
|
46 |
|
|
|
46 | alias_description = """ | |
|
47 | 47 | These are commonly set parameters, given abbreviated aliases for convenience. |
|
48 | 48 | They are set in the same `name=value` way as class parameters, where |
|
49 | 49 | <name> is replaced by the real parameter for which it is an alias. |
@@ -72,13 +72,13 class Application(SingletonConfigurable): | |||
|
72 | 72 | # of the help. |
|
73 | 73 | description = Unicode(u'This is an application.') |
|
74 | 74 | # default section descriptions |
|
75 |
|
|
|
76 |
|
|
|
75 | flag_description = Unicode(flag_description) | |
|
76 | alias_description = Unicode(alias_description) | |
|
77 | 77 | keyvalue_description = Unicode(keyvalue_description) |
|
78 | 78 | |
|
79 | 79 | |
|
80 | 80 | # A sequence of Configurable subclasses whose config=True attributes will |
|
81 |
# be exposed at the command line |
|
|
81 | # be exposed at the command line. | |
|
82 | 82 | classes = List([]) |
|
83 | 83 | |
|
84 | 84 | # The version string of this application. |
@@ -89,14 +89,14 class Application(SingletonConfigurable): | |||
|
89 | 89 | config=True, |
|
90 | 90 | help="Set the log level (0,10,20,30,40,50).") |
|
91 | 91 | |
|
92 |
# the |
|
|
93 |
s |
|
|
92 | # the alias map for configurables | |
|
93 | aliases = Dict(dict(log_level='Application.log_level')) | |
|
94 | 94 | |
|
95 |
# |
|
|
96 |
# |
|
|
97 | macros = Dict() | |
|
98 | # macro_help dict keys must match macros | |
|
99 |
|
|
|
95 | # flags for loading Configurables or store_const style flags | |
|
96 | # flags are loaded from this dict by '--key' flags | |
|
97 | # this must be a dict of two-tuples, the first element being the Config/dict | |
|
98 | # and the second being the help string for the flag | |
|
99 | flags = Dict() | |
|
100 | 100 | |
|
101 | 101 | |
|
102 | 102 | def __init__(self, **kwargs): |
@@ -105,12 +105,11 class Application(SingletonConfigurable): | |||
|
105 | 105 | # options. |
|
106 | 106 | self.classes.insert(0, self.__class__) |
|
107 | 107 | |
|
108 | # check that macro_help has the right keys | |
|
109 | # there is probably a better way to do this that doesn't use 2 dicts | |
|
110 | keys = set(self.macros.keys()) | |
|
111 | badkeys = keys.difference_update(set(self.macro_help.keys())) | |
|
112 | if badkeys: | |
|
113 | raise KeyError("macro %r has no help in `macro_help`!"%badkeys.pop()) | |
|
108 | # ensure self.flags dict is valid | |
|
109 | for key,value in self.flags.iteritems(): | |
|
110 | assert len(value) == 2, "Bad flag: %r:%s"%(key,value) | |
|
111 | assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s"%(key,value) | |
|
112 | assert isinstance(value[1], basestring), "Bad flag: %r:%s"%(key,value) | |
|
114 | 113 | self.init_logging() |
|
115 | 114 | |
|
116 | 115 | def init_logging(self): |
@@ -131,50 +130,50 class Application(SingletonConfigurable): | |||
|
131 | 130 | """Adjust the log level when log_level is set.""" |
|
132 | 131 | self.log.setLevel(new) |
|
133 | 132 | |
|
134 |
def print_ |
|
|
135 |
"""print the |
|
|
136 |
if not self.s |
|
|
133 | def print_alias_help(self): | |
|
134 | """print the alias part of the help""" | |
|
135 | if not self.aliases: | |
|
137 | 136 | return |
|
138 | 137 | |
|
139 | 138 | print "Aliases" |
|
140 | 139 | print "-------" |
|
141 |
print self. |
|
|
140 | print self.alias_description | |
|
142 | 141 | |
|
143 | 142 | |
|
144 | 143 | classdict = {} |
|
145 | 144 | for c in self.classes: |
|
146 | 145 | classdict[c.__name__] = c |
|
147 | 146 | |
|
148 |
for |
|
|
147 | for alias, longname in self.aliases.iteritems(): | |
|
149 | 148 | classname, traitname = longname.split('.',1) |
|
150 | 149 | cls = classdict[classname] |
|
151 | 150 | |
|
152 | 151 | trait = cls.class_traits(config=True)[traitname] |
|
153 | 152 | help = trait.get_metadata('help') |
|
154 |
print |
|
|
153 | print alias, "(%s)"%longname, ':', trait.__class__.__name__ | |
|
155 | 154 | if help: |
|
156 | 155 | print indent(help) |
|
157 | 156 | |
|
158 | 157 | |
|
159 |
def print_ |
|
|
160 |
"""print the |
|
|
161 |
if not self. |
|
|
158 | def print_flag_help(self): | |
|
159 | """print the flag part of the help""" | |
|
160 | if not self.flags: | |
|
162 | 161 | return |
|
163 | 162 | |
|
164 | 163 | print "Flags" |
|
165 | 164 | print "-----" |
|
166 |
print self. |
|
|
165 | print self.flag_description | |
|
167 | 166 | |
|
168 | 167 | |
|
169 |
for m, cfg in self. |
|
|
168 | for m, (cfg,help) in self.flags.iteritems(): | |
|
170 | 169 | print '--'+m |
|
171 |
print indent( |
|
|
170 | print indent(help) | |
|
172 | 171 | |
|
173 | 172 | |
|
174 | 173 | def print_help(self): |
|
175 | 174 | """Print the help for each Configurable class in self.classes.""" |
|
176 |
self.print_ |
|
|
177 |
self.print_ |
|
|
175 | self.print_flag_help() | |
|
176 | self.print_alias_help() | |
|
178 | 177 | if self.classes: |
|
179 | 178 | print "Class parameters" |
|
180 | 179 | print "----------------" |
@@ -216,9 +215,9 class Application(SingletonConfigurable): | |||
|
216 | 215 | if '--version' in argv: |
|
217 | 216 | self.print_version() |
|
218 | 217 | sys.exit(1) |
|
219 | ||
|
220 |
loader = KeyValueConfigLoader(argv=argv, s |
|
|
221 |
|
|
|
218 | ||
|
219 | loader = KeyValueConfigLoader(argv=argv, aliases=self.aliases, | |
|
220 | flags=self.flags) | |
|
222 | 221 | config = loader.load_config() |
|
223 | 222 | self.update_config(config) |
|
224 | 223 |
@@ -305,7 +305,7 class CommandLineConfigLoader(ConfigLoader): | |||
|
305 | 305 | """ |
|
306 | 306 | |
|
307 | 307 | kv_pattern = re.compile(r'[A-Za-z]\w*(\.\w+)*\=.+') |
|
308 |
|
|
|
308 | flag_pattern = re.compile(r'\-\-\w+(\-\w)*') | |
|
309 | 309 | |
|
310 | 310 | class KeyValueConfigLoader(CommandLineConfigLoader): |
|
311 | 311 | """A config loader that loads key value pairs from the command line. |
@@ -315,7 +315,7 class KeyValueConfigLoader(CommandLineConfigLoader): | |||
|
315 | 315 | ipython Global.profile="foo" InteractiveShell.autocall=False |
|
316 | 316 | """ |
|
317 | 317 | |
|
318 |
def __init__(self, argv=None, s |
|
|
318 | def __init__(self, argv=None, aliases=None, flags=None): | |
|
319 | 319 | """Create a key value pair config loader. |
|
320 | 320 | |
|
321 | 321 | Parameters |
@@ -324,14 +324,14 class KeyValueConfigLoader(CommandLineConfigLoader): | |||
|
324 | 324 | A list that has the form of sys.argv[1:] which has unicode |
|
325 | 325 | elements of the form u"key=value". If this is None (default), |
|
326 | 326 | then sys.argv[1:] will be used. |
|
327 |
s |
|
|
327 | aliases : dict | |
|
328 | 328 | A dict of aliases for configurable traits. |
|
329 | 329 | Keys are the short aliases, Values are the resolved trait. |
|
330 |
Of the form: `{' |
|
|
331 |
|
|
|
332 |
A dict of |
|
|
333 |
dicts, or "key=value" strings. If Config or dict, when the |
|
|
334 |
is triggered, The |
|
|
330 | Of the form: `{'alias' : 'Configurable.trait'}` | |
|
331 | flags : dict | |
|
332 | A dict of flags, keyed by str name. Vaues can be Config objects, | |
|
333 | dicts, or "key=value" strings. If Config or dict, when the flag | |
|
334 | is triggered, The flag is loaded as `self.config.update(m)`. | |
|
335 | 335 | |
|
336 | 336 | Returns |
|
337 | 337 | ------- |
@@ -349,10 +349,10 class KeyValueConfigLoader(CommandLineConfigLoader): | |||
|
349 | 349 | if argv is None: |
|
350 | 350 | argv = sys.argv[1:] |
|
351 | 351 | self.argv = argv |
|
352 |
self.s |
|
|
353 |
self. |
|
|
352 | self.aliases = aliases or {} | |
|
353 | self.flags = flags or {} | |
|
354 | 354 | |
|
355 |
def load_config(self, argv=None, s |
|
|
355 | def load_config(self, argv=None, aliases=None, flags=None): | |
|
356 | 356 | """Parse the configuration and generate the Config object. |
|
357 | 357 | |
|
358 | 358 | Parameters |
@@ -361,31 +361,31 class KeyValueConfigLoader(CommandLineConfigLoader): | |||
|
361 | 361 | A list that has the form of sys.argv[1:] which has unicode |
|
362 | 362 | elements of the form u"key=value". If this is None (default), |
|
363 | 363 | then self.argv will be used. |
|
364 |
s |
|
|
364 | aliases : dict | |
|
365 | 365 | A dict of aliases for configurable traits. |
|
366 | 366 | Keys are the short aliases, Values are the resolved trait. |
|
367 |
Of the form: `{' |
|
|
368 |
|
|
|
369 |
A dict of |
|
|
370 | dicts, or "key=value" strings. If Config or dict, when the macro | |
|
371 |
|
|
|
367 | Of the form: `{'alias' : 'Configurable.trait'}` | |
|
368 | flags : dict | |
|
369 | A dict of flags, keyed by str name. Values can be Config objects | |
|
370 | or dicts. When the flag is triggered, The config is loaded as | |
|
371 | `self.config.update(cfg)`. | |
|
372 | 372 | """ |
|
373 | 373 | from IPython.config.configurable import Configurable |
|
374 | 374 | |
|
375 | 375 | self.clear() |
|
376 | 376 | if argv is None: |
|
377 | 377 | argv = self.argv |
|
378 |
if s |
|
|
379 |
s |
|
|
380 |
if |
|
|
381 |
|
|
|
378 | if aliases is None: | |
|
379 | aliases = self.aliases | |
|
380 | if flags is None: | |
|
381 | flags = self.flags | |
|
382 | 382 | |
|
383 | 383 | for item in argv: |
|
384 | 384 | if kv_pattern.match(item): |
|
385 | 385 | lhs,rhs = item.split('=',1) |
|
386 |
# Substitute longnames for s |
|
|
387 |
if lhs in s |
|
|
388 |
lhs = s |
|
|
386 | # Substitute longnames for aliases. | |
|
387 | if lhs in aliases: | |
|
388 | lhs = aliases[lhs] | |
|
389 | 389 | exec_str = 'self.config.' + lhs + '=' + rhs |
|
390 | 390 | try: |
|
391 | 391 | # Try to see if regular Python syntax will work. This |
@@ -398,18 +398,17 class KeyValueConfigLoader(CommandLineConfigLoader): | |||
|
398 | 398 | # it succeeds. If it still fails, we let it raise. |
|
399 | 399 | exec_str = 'self.config.' + lhs + '="' + rhs + '"' |
|
400 | 400 | exec exec_str in locals(), globals() |
|
401 |
elif |
|
|
401 | elif flag_pattern.match(item): | |
|
402 | 402 | # trim leading '--' |
|
403 | 403 | m = item[2:] |
|
404 |
|
|
|
405 |
if |
|
|
406 |
raise ValueError("Unrecognized a |
|
|
407 | macro = macros[m] | |
|
408 | if isinstance(macro, (dict, Configurable)): | |
|
404 | cfg,_ = flags.get(m, (None,None)) | |
|
405 | if cfg is None: | |
|
406 | raise ValueError("Unrecognized flag: %r"%item) | |
|
407 | elif isinstance(cfg, (dict, Config)): | |
|
409 | 408 | # update self.config with Config: |
|
410 |
self.config.update( |
|
|
409 | self.config.update(cfg) | |
|
411 | 410 | else: |
|
412 |
raise ValueError("Invalid |
|
|
411 | raise ValueError("Invalid flag: %r"%flag) | |
|
413 | 412 | else: |
|
414 | 413 | raise ValueError("Invalid argument: %r"%item) |
|
415 | 414 | return self.config |
@@ -26,7 +26,7 from IPython.config.application import ( | |||
|
26 | 26 | ) |
|
27 | 27 | |
|
28 | 28 | from IPython.utils.traitlets import ( |
|
29 | Bool, Unicode, Int, Float, List | |
|
29 | Bool, Unicode, Int, Float, List, Dict | |
|
30 | 30 | ) |
|
31 | 31 | |
|
32 | 32 | #----------------------------------------------------------------------------- |
@@ -48,21 +48,18 class Bar(Configurable): | |||
|
48 | 48 | class MyApp(Application): |
|
49 | 49 | |
|
50 | 50 | app_name = Unicode(u'myapp') |
|
51 |
running = Bool(False, config=True, |
|
|
51 | running = Bool(False, config=True, | |
|
52 | 52 | help="Is the app running?") |
|
53 | 53 | classes = List([Bar, Foo]) |
|
54 |
config_file = Unicode(u'', config=True, |
|
|
54 | config_file = Unicode(u'', config=True, | |
|
55 | 55 | help="Load this config file") |
|
56 | 56 | |
|
57 |
s |
|
|
58 | enabled='Bar.enabled', log_level='MyApp.log_level') | |
|
57 | aliases = Dict(dict(i='Foo.i',j='Foo.j',name='Foo.name', | |
|
58 | enabled='Bar.enabled', log_level='MyApp.log_level')) | |
|
59 | ||
|
60 | flags = Dict(dict(enable=({'Bar': {'enabled' : True}}, "Set Bar.enabled to True"), | |
|
61 | disable=({'Bar': {'enabled' : False}}, "Set Bar.enabled to False"))) | |
|
59 | 62 | |
|
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 | ) | |
|
66 | 63 | def init_foo(self): |
|
67 | 64 | self.foo = Foo(config=self.config) |
|
68 | 65 | |
@@ -97,7 +94,7 class TestApplication(TestCase): | |||
|
97 | 94 | self.assertEquals(app.foo.j, 10) |
|
98 | 95 | self.assertEquals(app.bar.enabled, False) |
|
99 | 96 | |
|
100 |
def test_ |
|
|
97 | def test_alias(self): | |
|
101 | 98 | app = MyApp() |
|
102 | 99 | app.parse_command_line(["--disable"]) |
|
103 | 100 | app.init_bar() |
@@ -35,7 +35,7 import sys | |||
|
35 | 35 | from IPython.config.configurable import Configurable |
|
36 | 36 | from IPython.config.application import Application |
|
37 | 37 | from IPython.utils.traitlets import ( |
|
38 | Bool, Unicode, Int, Float, List | |
|
38 | Bool, Unicode, Int, Float, List, Dict | |
|
39 | 39 | ) |
|
40 | 40 | |
|
41 | 41 | |
@@ -63,15 +63,14 class MyApp(Application): | |||
|
63 | 63 | config_file = Unicode(u'', config=True, |
|
64 | 64 | help="Load this config file") |
|
65 | 65 | |
|
66 |
s |
|
|
67 | enabled='Bar.enabled') | |
|
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')) | |
|
68 | ||
|
69 | flags = Dict(dict(enable=({'Bar': {'enabled' : True}}, "Enable Bar"), | |
|
70 | disable=({'Bar': {'enabled' : False}}, "Disable Bar"), | |
|
71 | debug=({'MyApp':{'log_level':10}}, "Set loglevel to DEBUG") | |
|
72 | )) | |
|
68 | 73 | |
|
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 | ) | |
|
74 | ||
|
75 | 74 | def init_foo(self): |
|
76 | 75 | # Pass config to other classes for them to inherit the config. |
|
77 | 76 | self.foo = Foo(config=self.config) |
@@ -91,7 +90,6 def main(): | |||
|
91 | 90 | app.init_bar() |
|
92 | 91 | print "app.config:" |
|
93 | 92 | print app.config |
|
94 | print app.bar.enabled | |
|
95 | 93 | |
|
96 | 94 | |
|
97 | 95 | if __name__ == "__main__": |
General Comments 0
You need to be logged in to leave comments.
Login now