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