##// END OF EJS Templates
polish pass
MinRK -
Show More
@@ -1,603 +1,603 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 * Min RK
8 * Min RK
9 """
9 """
10 from __future__ import print_function
10 from __future__ import print_function
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2008-2011 The IPython Development Team
13 # Copyright (C) 2008-2011 The IPython Development Team
14 #
14 #
15 # Distributed under the terms of the BSD License. The full license is in
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 import logging
23 import logging
24 import os
24 import os
25 import re
25 import re
26 import sys
26 import sys
27 from copy import deepcopy
27 from copy import deepcopy
28 from collections import defaultdict
28 from collections import defaultdict
29
29
30 from IPython.external.decorator import decorator
30 from IPython.external.decorator import decorator
31
31
32 from IPython.config.configurable import SingletonConfigurable
32 from IPython.config.configurable import SingletonConfigurable
33 from IPython.config.loader import (
33 from IPython.config.loader import (
34 KVArgParseConfigLoader, PyFileConfigLoader, Config, ArgumentError, ConfigFileNotFound, JSONFileConfigLoader
34 KVArgParseConfigLoader, PyFileConfigLoader, Config, ArgumentError, ConfigFileNotFound, JSONFileConfigLoader
35 )
35 )
36
36
37 from IPython.utils.traitlets import (
37 from IPython.utils.traitlets import (
38 Unicode, List, Enum, Dict, Instance, TraitError
38 Unicode, List, Enum, Dict, Instance, TraitError
39 )
39 )
40 from IPython.utils.importstring import import_item
40 from IPython.utils.importstring import import_item
41 from IPython.utils.text import indent, wrap_paragraphs, dedent
41 from IPython.utils.text import indent, wrap_paragraphs, dedent
42 from IPython.utils import py3compat
42 from IPython.utils import py3compat
43 from IPython.utils.py3compat import string_types, iteritems
43 from IPython.utils.py3compat import string_types, iteritems
44
44
45 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
46 # function for re-wrapping a helpstring
46 # function for re-wrapping a helpstring
47 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
48
48
49 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
50 # Descriptions for the various sections
50 # Descriptions for the various sections
51 #-----------------------------------------------------------------------------
51 #-----------------------------------------------------------------------------
52
52
53 # merge flags&aliases into options
53 # merge flags&aliases into options
54 option_description = """
54 option_description = """
55 Arguments that take values are actually convenience aliases to full
55 Arguments that take values are actually convenience aliases to full
56 Configurables, whose aliases are listed on the help line. For more information
56 Configurables, whose aliases are listed on the help line. For more information
57 on full configurables, see '--help-all'.
57 on full configurables, see '--help-all'.
58 """.strip() # trim newlines of front and back
58 """.strip() # trim newlines of front and back
59
59
60 keyvalue_description = """
60 keyvalue_description = """
61 Parameters are set from command-line arguments of the form:
61 Parameters are set from command-line arguments of the form:
62 `--Class.trait=value`.
62 `--Class.trait=value`.
63 This line is evaluated in Python, so simple expressions are allowed, e.g.::
63 This line is evaluated in Python, so simple expressions are allowed, e.g.::
64 `--C.a='range(3)'` For setting C.a=[0,1,2].
64 `--C.a='range(3)'` For setting C.a=[0,1,2].
65 """.strip() # trim newlines of front and back
65 """.strip() # trim newlines of front and back
66
66
67 # sys.argv can be missing, for example when python is embedded. See the docs
67 # sys.argv can be missing, for example when python is embedded. See the docs
68 # for details: http://docs.python.org/2/c-api/intro.html#embedding-python
68 # for details: http://docs.python.org/2/c-api/intro.html#embedding-python
69 if not hasattr(sys, "argv"):
69 if not hasattr(sys, "argv"):
70 sys.argv = [""]
70 sys.argv = [""]
71
71
72 subcommand_description = """
72 subcommand_description = """
73 Subcommands are launched as `{app} cmd [args]`. For information on using
73 Subcommands are launched as `{app} cmd [args]`. For information on using
74 subcommand 'cmd', do: `{app} cmd -h`.
74 subcommand 'cmd', do: `{app} cmd -h`.
75 """.strip().format(app=os.path.basename(sys.argv[0]))
75 """.strip().format(app=os.path.basename(sys.argv[0]))
76 # get running program name
76 # get running program name
77
77
78 #-----------------------------------------------------------------------------
78 #-----------------------------------------------------------------------------
79 # Application class
79 # Application class
80 #-----------------------------------------------------------------------------
80 #-----------------------------------------------------------------------------
81
81
82 @decorator
82 @decorator
83 def catch_config_error(method, app, *args, **kwargs):
83 def catch_config_error(method, app, *args, **kwargs):
84 """Method decorator for catching invalid config (Trait/ArgumentErrors) during init.
84 """Method decorator for catching invalid config (Trait/ArgumentErrors) during init.
85
85
86 On a TraitError (generally caused by bad config), this will print the trait's
86 On a TraitError (generally caused by bad config), this will print the trait's
87 message, and exit the app.
87 message, and exit the app.
88
88
89 For use on init methods, to prevent invoking excepthook on invalid input.
89 For use on init methods, to prevent invoking excepthook on invalid input.
90 """
90 """
91 try:
91 try:
92 return method(app, *args, **kwargs)
92 return method(app, *args, **kwargs)
93 except (TraitError, ArgumentError) as e:
93 except (TraitError, ArgumentError) as e:
94 app.print_help()
94 app.print_help()
95 app.log.fatal("Bad config encountered during initialization:")
95 app.log.fatal("Bad config encountered during initialization:")
96 app.log.fatal(str(e))
96 app.log.fatal(str(e))
97 app.log.debug("Config at the time: %s", app.config)
97 app.log.debug("Config at the time: %s", app.config)
98 app.exit(1)
98 app.exit(1)
99
99
100
100
101 class ApplicationError(Exception):
101 class ApplicationError(Exception):
102 pass
102 pass
103
103
104 class LevelFormatter(logging.Formatter):
104 class LevelFormatter(logging.Formatter):
105 """Formatter with additional `highlevel` record
105 """Formatter with additional `highlevel` record
106
106
107 This field is empty if log level is less than highlevel_limit,
107 This field is empty if log level is less than highlevel_limit,
108 otherwise it is formatted with self.highlevel_format.
108 otherwise it is formatted with self.highlevel_format.
109
109
110 Useful for adding 'WARNING' to warning messages,
110 Useful for adding 'WARNING' to warning messages,
111 without adding 'INFO' to info, etc.
111 without adding 'INFO' to info, etc.
112 """
112 """
113 highlevel_limit = logging.WARN
113 highlevel_limit = logging.WARN
114 highlevel_format = " %(levelname)s |"
114 highlevel_format = " %(levelname)s |"
115
115
116 def format(self, record):
116 def format(self, record):
117 if record.levelno >= self.highlevel_limit:
117 if record.levelno >= self.highlevel_limit:
118 record.highlevel = self.highlevel_format % record.__dict__
118 record.highlevel = self.highlevel_format % record.__dict__
119 else:
119 else:
120 record.highlevel = ""
120 record.highlevel = ""
121 return super(LevelFormatter, self).format(record)
121 return super(LevelFormatter, self).format(record)
122
122
123
123
124 class Application(SingletonConfigurable):
124 class Application(SingletonConfigurable):
125 """A singleton application with full configuration support."""
125 """A singleton application with full configuration support."""
126
126
127 # The name of the application, will usually match the name of the command
127 # The name of the application, will usually match the name of the command
128 # line application
128 # line application
129 name = Unicode(u'application')
129 name = Unicode(u'application')
130
130
131 # The description of the application that is printed at the beginning
131 # The description of the application that is printed at the beginning
132 # of the help.
132 # of the help.
133 description = Unicode(u'This is an application.')
133 description = Unicode(u'This is an application.')
134 # default section descriptions
134 # default section descriptions
135 option_description = Unicode(option_description)
135 option_description = Unicode(option_description)
136 keyvalue_description = Unicode(keyvalue_description)
136 keyvalue_description = Unicode(keyvalue_description)
137 subcommand_description = Unicode(subcommand_description)
137 subcommand_description = Unicode(subcommand_description)
138
138
139 # The usage and example string that goes at the end of the help string.
139 # The usage and example string that goes at the end of the help string.
140 examples = Unicode()
140 examples = Unicode()
141
141
142 # A sequence of Configurable subclasses whose config=True attributes will
142 # A sequence of Configurable subclasses whose config=True attributes will
143 # be exposed at the command line.
143 # be exposed at the command line.
144 classes = List([])
144 classes = List([])
145
145
146 # The version string of this application.
146 # The version string of this application.
147 version = Unicode(u'0.0')
147 version = Unicode(u'0.0')
148
148
149 # the argv used to initialize the application
149 # the argv used to initialize the application
150 argv = List()
150 argv = List()
151
151
152 # The log level for the application
152 # The log level for the application
153 log_level = Enum((0,10,20,30,40,50,'DEBUG','INFO','WARN','ERROR','CRITICAL'),
153 log_level = Enum((0,10,20,30,40,50,'DEBUG','INFO','WARN','ERROR','CRITICAL'),
154 default_value=logging.WARN,
154 default_value=logging.WARN,
155 config=True,
155 config=True,
156 help="Set the log level by value or name.")
156 help="Set the log level by value or name.")
157 def _log_level_changed(self, name, old, new):
157 def _log_level_changed(self, name, old, new):
158 """Adjust the log level when log_level is set."""
158 """Adjust the log level when log_level is set."""
159 if isinstance(new, string_types):
159 if isinstance(new, string_types):
160 new = getattr(logging, new)
160 new = getattr(logging, new)
161 self.log_level = new
161 self.log_level = new
162 self.log.setLevel(new)
162 self.log.setLevel(new)
163
163
164 log_datefmt = Unicode("%Y-%m-%d %H:%M:%S", config=True,
164 log_datefmt = Unicode("%Y-%m-%d %H:%M:%S", config=True,
165 help="The date format used by logging formatters for %(asctime)s"
165 help="The date format used by logging formatters for %(asctime)s"
166 )
166 )
167 def _log_datefmt_changed(self, name, old, new):
167 def _log_datefmt_changed(self, name, old, new):
168 self._log_format_changed()
168 self._log_format_changed()
169
169
170 log_format = Unicode("[%(name)s]%(highlevel)s %(message)s", config=True,
170 log_format = Unicode("[%(name)s]%(highlevel)s %(message)s", config=True,
171 help="The Logging format template",
171 help="The Logging format template",
172 )
172 )
173 def _log_format_changed(self, name, old, new):
173 def _log_format_changed(self, name, old, new):
174 """Change the log formatter when log_format is set."""
174 """Change the log formatter when log_format is set."""
175 _log_handler = self.log.handlers[0]
175 _log_handler = self.log.handlers[0]
176 _log_formatter = LevelFormatter(new, datefmt=self.log_datefmt)
176 _log_formatter = LevelFormatter(new, datefmt=self.log_datefmt)
177 _log_handler.setFormatter(_log_formatter)
177 _log_handler.setFormatter(_log_formatter)
178
178
179 log = Instance(logging.Logger)
179 log = Instance(logging.Logger)
180 def _log_default(self):
180 def _log_default(self):
181 """Start logging for this application.
181 """Start logging for this application.
182
182
183 The default is to log to stderr using a StreamHandler, if no default
183 The default is to log to stderr using a StreamHandler, if no default
184 handler already exists. The log level starts at logging.WARN, but this
184 handler already exists. The log level starts at logging.WARN, but this
185 can be adjusted by setting the ``log_level`` attribute.
185 can be adjusted by setting the ``log_level`` attribute.
186 """
186 """
187 log = logging.getLogger(self.__class__.__name__)
187 log = logging.getLogger(self.__class__.__name__)
188 log.setLevel(self.log_level)
188 log.setLevel(self.log_level)
189 log.propagate = False
189 log.propagate = False
190 _log = log # copied from Logger.hasHandlers() (new in Python 3.2)
190 _log = log # copied from Logger.hasHandlers() (new in Python 3.2)
191 while _log:
191 while _log:
192 if _log.handlers:
192 if _log.handlers:
193 return log
193 return log
194 if not _log.propagate:
194 if not _log.propagate:
195 break
195 break
196 else:
196 else:
197 _log = _log.parent
197 _log = _log.parent
198 if sys.executable.endswith('pythonw.exe'):
198 if sys.executable.endswith('pythonw.exe'):
199 # this should really go to a file, but file-logging is only
199 # this should really go to a file, but file-logging is only
200 # hooked up in parallel applications
200 # hooked up in parallel applications
201 _log_handler = logging.StreamHandler(open(os.devnull, 'w'))
201 _log_handler = logging.StreamHandler(open(os.devnull, 'w'))
202 else:
202 else:
203 _log_handler = logging.StreamHandler()
203 _log_handler = logging.StreamHandler()
204 _log_formatter = LevelFormatter(self.log_format, datefmt=self.log_datefmt)
204 _log_formatter = LevelFormatter(self.log_format, datefmt=self.log_datefmt)
205 _log_handler.setFormatter(_log_formatter)
205 _log_handler.setFormatter(_log_formatter)
206 log.addHandler(_log_handler)
206 log.addHandler(_log_handler)
207 return log
207 return log
208
208
209 # the alias map for configurables
209 # the alias map for configurables
210 aliases = Dict({'log-level' : 'Application.log_level'})
210 aliases = Dict({'log-level' : 'Application.log_level'})
211
211
212 # flags for loading Configurables or store_const style flags
212 # flags for loading Configurables or store_const style flags
213 # flags are loaded from this dict by '--key' flags
213 # flags are loaded from this dict by '--key' flags
214 # this must be a dict of two-tuples, the first element being the Config/dict
214 # this must be a dict of two-tuples, the first element being the Config/dict
215 # and the second being the help string for the flag
215 # and the second being the help string for the flag
216 flags = Dict()
216 flags = Dict()
217 def _flags_changed(self, name, old, new):
217 def _flags_changed(self, name, old, new):
218 """ensure flags dict is valid"""
218 """ensure flags dict is valid"""
219 for key,value in iteritems(new):
219 for key,value in iteritems(new):
220 assert len(value) == 2, "Bad flag: %r:%s"%(key,value)
220 assert len(value) == 2, "Bad flag: %r:%s"%(key,value)
221 assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s"%(key,value)
221 assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s"%(key,value)
222 assert isinstance(value[1], string_types), "Bad flag: %r:%s"%(key,value)
222 assert isinstance(value[1], string_types), "Bad flag: %r:%s"%(key,value)
223
223
224
224
225 # subcommands for launching other applications
225 # subcommands for launching other applications
226 # if this is not empty, this will be a parent Application
226 # if this is not empty, this will be a parent Application
227 # this must be a dict of two-tuples,
227 # this must be a dict of two-tuples,
228 # the first element being the application class/import string
228 # the first element being the application class/import string
229 # and the second being the help string for the subcommand
229 # and the second being the help string for the subcommand
230 subcommands = Dict()
230 subcommands = Dict()
231 # parse_command_line will initialize a subapp, if requested
231 # parse_command_line will initialize a subapp, if requested
232 subapp = Instance('IPython.config.application.Application', allow_none=True)
232 subapp = Instance('IPython.config.application.Application', allow_none=True)
233
233
234 # extra command-line arguments that don't set config values
234 # extra command-line arguments that don't set config values
235 extra_args = List(Unicode)
235 extra_args = List(Unicode)
236
236
237
237
238 def __init__(self, **kwargs):
238 def __init__(self, **kwargs):
239 SingletonConfigurable.__init__(self, **kwargs)
239 SingletonConfigurable.__init__(self, **kwargs)
240 # Ensure my class is in self.classes, so my attributes appear in command line
240 # Ensure my class is in self.classes, so my attributes appear in command line
241 # options and config files.
241 # options and config files.
242 if self.__class__ not in self.classes:
242 if self.__class__ not in self.classes:
243 self.classes.insert(0, self.__class__)
243 self.classes.insert(0, self.__class__)
244
244
245 def _config_changed(self, name, old, new):
245 def _config_changed(self, name, old, new):
246 SingletonConfigurable._config_changed(self, name, old, new)
246 SingletonConfigurable._config_changed(self, name, old, new)
247 self.log.debug('Config changed:')
247 self.log.debug('Config changed:')
248 self.log.debug(repr(new))
248 self.log.debug(repr(new))
249
249
250 @catch_config_error
250 @catch_config_error
251 def initialize(self, argv=None):
251 def initialize(self, argv=None):
252 """Do the basic steps to configure me.
252 """Do the basic steps to configure me.
253
253
254 Override in subclasses.
254 Override in subclasses.
255 """
255 """
256 self.parse_command_line(argv)
256 self.parse_command_line(argv)
257
257
258
258
259 def start(self):
259 def start(self):
260 """Start the app mainloop.
260 """Start the app mainloop.
261
261
262 Override in subclasses.
262 Override in subclasses.
263 """
263 """
264 if self.subapp is not None:
264 if self.subapp is not None:
265 return self.subapp.start()
265 return self.subapp.start()
266
266
267 def print_alias_help(self):
267 def print_alias_help(self):
268 """Print the alias part of the help."""
268 """Print the alias part of the help."""
269 if not self.aliases:
269 if not self.aliases:
270 return
270 return
271
271
272 lines = []
272 lines = []
273 classdict = {}
273 classdict = {}
274 for cls in self.classes:
274 for cls in self.classes:
275 # include all parents (up to, but excluding Configurable) in available names
275 # include all parents (up to, but excluding Configurable) in available names
276 for c in cls.mro()[:-3]:
276 for c in cls.mro()[:-3]:
277 classdict[c.__name__] = c
277 classdict[c.__name__] = c
278
278
279 for alias, longname in iteritems(self.aliases):
279 for alias, longname in iteritems(self.aliases):
280 classname, traitname = longname.split('.',1)
280 classname, traitname = longname.split('.',1)
281 cls = classdict[classname]
281 cls = classdict[classname]
282
282
283 trait = cls.class_traits(config=True)[traitname]
283 trait = cls.class_traits(config=True)[traitname]
284 help = cls.class_get_trait_help(trait).splitlines()
284 help = cls.class_get_trait_help(trait).splitlines()
285 # reformat first line
285 # reformat first line
286 help[0] = help[0].replace(longname, alias) + ' (%s)'%longname
286 help[0] = help[0].replace(longname, alias) + ' (%s)'%longname
287 if len(alias) == 1:
287 if len(alias) == 1:
288 help[0] = help[0].replace('--%s='%alias, '-%s '%alias)
288 help[0] = help[0].replace('--%s='%alias, '-%s '%alias)
289 lines.extend(help)
289 lines.extend(help)
290 # lines.append('')
290 # lines.append('')
291 print(os.linesep.join(lines))
291 print(os.linesep.join(lines))
292
292
293 def print_flag_help(self):
293 def print_flag_help(self):
294 """Print the flag part of the help."""
294 """Print the flag part of the help."""
295 if not self.flags:
295 if not self.flags:
296 return
296 return
297
297
298 lines = []
298 lines = []
299 for m, (cfg,help) in iteritems(self.flags):
299 for m, (cfg,help) in iteritems(self.flags):
300 prefix = '--' if len(m) > 1 else '-'
300 prefix = '--' if len(m) > 1 else '-'
301 lines.append(prefix+m)
301 lines.append(prefix+m)
302 lines.append(indent(dedent(help.strip())))
302 lines.append(indent(dedent(help.strip())))
303 # lines.append('')
303 # lines.append('')
304 print(os.linesep.join(lines))
304 print(os.linesep.join(lines))
305
305
306 def print_options(self):
306 def print_options(self):
307 if not self.flags and not self.aliases:
307 if not self.flags and not self.aliases:
308 return
308 return
309 lines = ['Options']
309 lines = ['Options']
310 lines.append('-'*len(lines[0]))
310 lines.append('-'*len(lines[0]))
311 lines.append('')
311 lines.append('')
312 for p in wrap_paragraphs(self.option_description):
312 for p in wrap_paragraphs(self.option_description):
313 lines.append(p)
313 lines.append(p)
314 lines.append('')
314 lines.append('')
315 print(os.linesep.join(lines))
315 print(os.linesep.join(lines))
316 self.print_flag_help()
316 self.print_flag_help()
317 self.print_alias_help()
317 self.print_alias_help()
318 print()
318 print()
319
319
320 def print_subcommands(self):
320 def print_subcommands(self):
321 """Print the subcommand part of the help."""
321 """Print the subcommand part of the help."""
322 if not self.subcommands:
322 if not self.subcommands:
323 return
323 return
324
324
325 lines = ["Subcommands"]
325 lines = ["Subcommands"]
326 lines.append('-'*len(lines[0]))
326 lines.append('-'*len(lines[0]))
327 lines.append('')
327 lines.append('')
328 for p in wrap_paragraphs(self.subcommand_description):
328 for p in wrap_paragraphs(self.subcommand_description):
329 lines.append(p)
329 lines.append(p)
330 lines.append('')
330 lines.append('')
331 for subc, (cls, help) in iteritems(self.subcommands):
331 for subc, (cls, help) in iteritems(self.subcommands):
332 lines.append(subc)
332 lines.append(subc)
333 if help:
333 if help:
334 lines.append(indent(dedent(help.strip())))
334 lines.append(indent(dedent(help.strip())))
335 lines.append('')
335 lines.append('')
336 print(os.linesep.join(lines))
336 print(os.linesep.join(lines))
337
337
338 def print_help(self, classes=False):
338 def print_help(self, classes=False):
339 """Print the help for each Configurable class in self.classes.
339 """Print the help for each Configurable class in self.classes.
340
340
341 If classes=False (the default), only flags and aliases are printed.
341 If classes=False (the default), only flags and aliases are printed.
342 """
342 """
343 self.print_description()
343 self.print_description()
344 self.print_subcommands()
344 self.print_subcommands()
345 self.print_options()
345 self.print_options()
346
346
347 if classes:
347 if classes:
348 if self.classes:
348 if self.classes:
349 print("Class parameters")
349 print("Class parameters")
350 print("----------------")
350 print("----------------")
351 print()
351 print()
352 for p in wrap_paragraphs(self.keyvalue_description):
352 for p in wrap_paragraphs(self.keyvalue_description):
353 print(p)
353 print(p)
354 print()
354 print()
355
355
356 for cls in self.classes:
356 for cls in self.classes:
357 cls.class_print_help()
357 cls.class_print_help()
358 print()
358 print()
359 else:
359 else:
360 print("To see all available configurables, use `--help-all`")
360 print("To see all available configurables, use `--help-all`")
361 print()
361 print()
362
362
363 self.print_examples()
363 self.print_examples()
364
364
365
365
366 def print_description(self):
366 def print_description(self):
367 """Print the application description."""
367 """Print the application description."""
368 for p in wrap_paragraphs(self.description):
368 for p in wrap_paragraphs(self.description):
369 print(p)
369 print(p)
370 print()
370 print()
371
371
372 def print_examples(self):
372 def print_examples(self):
373 """Print usage and examples.
373 """Print usage and examples.
374
374
375 This usage string goes at the end of the command line help string
375 This usage string goes at the end of the command line help string
376 and should contain examples of the application's usage.
376 and should contain examples of the application's usage.
377 """
377 """
378 if self.examples:
378 if self.examples:
379 print("Examples")
379 print("Examples")
380 print("--------")
380 print("--------")
381 print()
381 print()
382 print(indent(dedent(self.examples.strip())))
382 print(indent(dedent(self.examples.strip())))
383 print()
383 print()
384
384
385 def print_version(self):
385 def print_version(self):
386 """Print the version string."""
386 """Print the version string."""
387 print(self.version)
387 print(self.version)
388
388
389 def update_config(self, config):
389 def update_config(self, config):
390 """Fire the traits events when the config is updated."""
390 """Fire the traits events when the config is updated."""
391 # Save a copy of the current config.
391 # Save a copy of the current config.
392 newconfig = deepcopy(self.config)
392 newconfig = deepcopy(self.config)
393 # Merge the new config into the current one.
393 # Merge the new config into the current one.
394 newconfig.merge(config)
394 newconfig.merge(config)
395 # Save the combined config as self.config, which triggers the traits
395 # Save the combined config as self.config, which triggers the traits
396 # events.
396 # events.
397 self.config = newconfig
397 self.config = newconfig
398
398
399 @catch_config_error
399 @catch_config_error
400 def initialize_subcommand(self, subc, argv=None):
400 def initialize_subcommand(self, subc, argv=None):
401 """Initialize a subcommand with argv."""
401 """Initialize a subcommand with argv."""
402 subapp,help = self.subcommands.get(subc)
402 subapp,help = self.subcommands.get(subc)
403
403
404 if isinstance(subapp, string_types):
404 if isinstance(subapp, string_types):
405 subapp = import_item(subapp)
405 subapp = import_item(subapp)
406
406
407 # clear existing instances
407 # clear existing instances
408 self.__class__.clear_instance()
408 self.__class__.clear_instance()
409 # instantiate
409 # instantiate
410 self.subapp = subapp.instance(config=self.config)
410 self.subapp = subapp.instance(config=self.config)
411 # and initialize subapp
411 # and initialize subapp
412 self.subapp.initialize(argv)
412 self.subapp.initialize(argv)
413
413
414 def flatten_flags(self):
414 def flatten_flags(self):
415 """flatten flags and aliases, so cl-args override as expected.
415 """flatten flags and aliases, so cl-args override as expected.
416
416
417 This prevents issues such as an alias pointing to InteractiveShell,
417 This prevents issues such as an alias pointing to InteractiveShell,
418 but a config file setting the same trait in TerminalInteraciveShell
418 but a config file setting the same trait in TerminalInteraciveShell
419 getting inappropriate priority over the command-line arg.
419 getting inappropriate priority over the command-line arg.
420
420
421 Only aliases with exactly one descendent in the class list
421 Only aliases with exactly one descendent in the class list
422 will be promoted.
422 will be promoted.
423
423
424 """
424 """
425 # build a tree of classes in our list that inherit from a particular
425 # build a tree of classes in our list that inherit from a particular
426 # it will be a dict by parent classname of classes in our list
426 # it will be a dict by parent classname of classes in our list
427 # that are descendents
427 # that are descendents
428 mro_tree = defaultdict(list)
428 mro_tree = defaultdict(list)
429 for cls in self.classes:
429 for cls in self.classes:
430 clsname = cls.__name__
430 clsname = cls.__name__
431 for parent in cls.mro()[1:-3]:
431 for parent in cls.mro()[1:-3]:
432 # exclude cls itself and Configurable,HasTraits,object
432 # exclude cls itself and Configurable,HasTraits,object
433 mro_tree[parent.__name__].append(clsname)
433 mro_tree[parent.__name__].append(clsname)
434 # flatten aliases, which have the form:
434 # flatten aliases, which have the form:
435 # { 'alias' : 'Class.trait' }
435 # { 'alias' : 'Class.trait' }
436 aliases = {}
436 aliases = {}
437 for alias, cls_trait in iteritems(self.aliases):
437 for alias, cls_trait in iteritems(self.aliases):
438 cls,trait = cls_trait.split('.',1)
438 cls,trait = cls_trait.split('.',1)
439 children = mro_tree[cls]
439 children = mro_tree[cls]
440 if len(children) == 1:
440 if len(children) == 1:
441 # exactly one descendent, promote alias
441 # exactly one descendent, promote alias
442 cls = children[0]
442 cls = children[0]
443 aliases[alias] = '.'.join([cls,trait])
443 aliases[alias] = '.'.join([cls,trait])
444
444
445 # flatten flags, which are of the form:
445 # flatten flags, which are of the form:
446 # { 'key' : ({'Cls' : {'trait' : value}}, 'help')}
446 # { 'key' : ({'Cls' : {'trait' : value}}, 'help')}
447 flags = {}
447 flags = {}
448 for key, (flagdict, help) in iteritems(self.flags):
448 for key, (flagdict, help) in iteritems(self.flags):
449 newflag = {}
449 newflag = {}
450 for cls, subdict in iteritems(flagdict):
450 for cls, subdict in iteritems(flagdict):
451 children = mro_tree[cls]
451 children = mro_tree[cls]
452 # exactly one descendent, promote flag section
452 # exactly one descendent, promote flag section
453 if len(children) == 1:
453 if len(children) == 1:
454 cls = children[0]
454 cls = children[0]
455 newflag[cls] = subdict
455 newflag[cls] = subdict
456 flags[key] = (newflag, help)
456 flags[key] = (newflag, help)
457 return flags, aliases
457 return flags, aliases
458
458
459 @catch_config_error
459 @catch_config_error
460 def parse_command_line(self, argv=None):
460 def parse_command_line(self, argv=None):
461 """Parse the command line arguments."""
461 """Parse the command line arguments."""
462 argv = sys.argv[1:] if argv is None else argv
462 argv = sys.argv[1:] if argv is None else argv
463 self.argv = [ py3compat.cast_unicode(arg) for arg in argv ]
463 self.argv = [ py3compat.cast_unicode(arg) for arg in argv ]
464
464
465 if argv and argv[0] == 'help':
465 if argv and argv[0] == 'help':
466 # turn `ipython help notebook` into `ipython notebook -h`
466 # turn `ipython help notebook` into `ipython notebook -h`
467 argv = argv[1:] + ['-h']
467 argv = argv[1:] + ['-h']
468
468
469 if self.subcommands and len(argv) > 0:
469 if self.subcommands and len(argv) > 0:
470 # we have subcommands, and one may have been specified
470 # we have subcommands, and one may have been specified
471 subc, subargv = argv[0], argv[1:]
471 subc, subargv = argv[0], argv[1:]
472 if re.match(r'^\w(\-?\w)*$', subc) and subc in self.subcommands:
472 if re.match(r'^\w(\-?\w)*$', subc) and subc in self.subcommands:
473 # it's a subcommand, and *not* a flag or class parameter
473 # it's a subcommand, and *not* a flag or class parameter
474 return self.initialize_subcommand(subc, subargv)
474 return self.initialize_subcommand(subc, subargv)
475
475
476 # Arguments after a '--' argument are for the script IPython may be
476 # Arguments after a '--' argument are for the script IPython may be
477 # about to run, not IPython iteslf. For arguments parsed here (help and
477 # about to run, not IPython iteslf. For arguments parsed here (help and
478 # version), we want to only search the arguments up to the first
478 # version), we want to only search the arguments up to the first
479 # occurrence of '--', which we're calling interpreted_argv.
479 # occurrence of '--', which we're calling interpreted_argv.
480 try:
480 try:
481 interpreted_argv = argv[:argv.index('--')]
481 interpreted_argv = argv[:argv.index('--')]
482 except ValueError:
482 except ValueError:
483 interpreted_argv = argv
483 interpreted_argv = argv
484
484
485 if any(x in interpreted_argv for x in ('-h', '--help-all', '--help')):
485 if any(x in interpreted_argv for x in ('-h', '--help-all', '--help')):
486 self.print_help('--help-all' in interpreted_argv)
486 self.print_help('--help-all' in interpreted_argv)
487 self.exit(0)
487 self.exit(0)
488
488
489 if '--version' in interpreted_argv or '-V' in interpreted_argv:
489 if '--version' in interpreted_argv or '-V' in interpreted_argv:
490 self.print_version()
490 self.print_version()
491 self.exit(0)
491 self.exit(0)
492
492
493 # flatten flags&aliases, so cl-args get appropriate priority:
493 # flatten flags&aliases, so cl-args get appropriate priority:
494 flags,aliases = self.flatten_flags()
494 flags,aliases = self.flatten_flags()
495 loader = KVArgParseConfigLoader(argv=argv, aliases=aliases,
495 loader = KVArgParseConfigLoader(argv=argv, aliases=aliases,
496 flags=flags, log=self.log)
496 flags=flags, log=self.log)
497 config = loader.load_config()
497 config = loader.load_config()
498 self.update_config(config)
498 self.update_config(config)
499 # store unparsed args in extra_args
499 # store unparsed args in extra_args
500 self.extra_args = loader.extra_args
500 self.extra_args = loader.extra_args
501
501
502 @classmethod
502 @classmethod
503 def _load_config_files(cls, basefilename, path=None, log=None):
503 def _load_config_files(cls, basefilename, path=None, log=None):
504 """Load config files (py,json) by filename and path.
504 """Load config files (py,json) by filename and path.
505
505
506 yield each config object in turn.
506 yield each config object in turn.
507 """
507 """
508
508
509 pyloader = PyFileConfigLoader(basefilename+'.py', path=path, log=log)
509 pyloader = PyFileConfigLoader(basefilename+'.py', path=path, log=log)
510 jsonloader = JSONFileConfigLoader(basefilename+'.json', path=path, log=log)
510 jsonloader = JSONFileConfigLoader(basefilename+'.json', path=path, log=log)
511 config_found = False
511 config_found = False
512 config = None
512 config = None
513 for loader in [pyloader, jsonloader]:
513 for loader in [pyloader, jsonloader]:
514 try:
514 try:
515 config = loader.load_config()
515 config = loader.load_config()
516 config_found = True
516 config_found = True
517 except ConfigFileNotFound:
517 except ConfigFileNotFound:
518 pass
518 pass
519 except Exception:
519 except Exception:
520 # try to get the full filename, but it will be empty in the
520 # try to get the full filename, but it will be empty in the
521 # unlikely event that the error raised before filefind finished
521 # unlikely event that the error raised before filefind finished
522 filename = loader.full_filename or filename
522 filename = loader.full_filename or filename
523 # problem while running the file
523 # problem while running the file
524 log.error("Exception while loading config file %s",
524 log.error("Exception while loading config file %s",
525 filename, exc_info=True)
525 filename, exc_info=True)
526 else:
526 else:
527 log.debug("Loaded config file: %s", loader.full_filename)
527 log.debug("Loaded config file: %s", loader.full_filename)
528 if config :
528 if config:
529 yield config
529 yield config
530
530
531 if not config_found :
531 if not config_found:
532 raise ConfigFileNotFound('Neither .json, not .py file found.')
532 raise ConfigFileNotFound('Neither .json, nor .py config file found.')
533 raise StopIteration
533 raise StopIteration
534
534
535
535
536 @catch_config_error
536 @catch_config_error
537 def load_config_file(self, filename, path=None):
537 def load_config_file(self, filename, path=None):
538 """Load config files (json/py) by filename and path."""
538 """Load config files by filename and path."""
539 filename, ext = os.path.splitext(filename)
539 filename, ext = os.path.splitext(filename)
540 for config in self._load_config_files(filename, path=path , log=self.log):
540 for config in self._load_config_files(filename, path=path, log=self.log):
541 self.update_config(config)
541 self.update_config(config)
542
542
543
543
544 def generate_config_file(self):
544 def generate_config_file(self):
545 """generate default config file from Configurables"""
545 """generate default config file from Configurables"""
546 lines = ["# Configuration file for %s."%self.name]
546 lines = ["# Configuration file for %s."%self.name]
547 lines.append('')
547 lines.append('')
548 lines.append('c = get_config()')
548 lines.append('c = get_config()')
549 lines.append('')
549 lines.append('')
550 for cls in self.classes:
550 for cls in self.classes:
551 lines.append(cls.class_config_section())
551 lines.append(cls.class_config_section())
552 return '\n'.join(lines)
552 return '\n'.join(lines)
553
553
554 def exit(self, exit_status=0):
554 def exit(self, exit_status=0):
555 self.log.debug("Exiting application: %s" % self.name)
555 self.log.debug("Exiting application: %s" % self.name)
556 sys.exit(exit_status)
556 sys.exit(exit_status)
557
557
558 @classmethod
558 @classmethod
559 def launch_instance(cls, argv=None, **kwargs):
559 def launch_instance(cls, argv=None, **kwargs):
560 """Launch a global instance of this Application
560 """Launch a global instance of this Application
561
561
562 If a global instance already exists, this reinitializes and starts it
562 If a global instance already exists, this reinitializes and starts it
563 """
563 """
564 app = cls.instance(**kwargs)
564 app = cls.instance(**kwargs)
565 app.initialize(argv)
565 app.initialize(argv)
566 app.start()
566 app.start()
567
567
568 #-----------------------------------------------------------------------------
568 #-----------------------------------------------------------------------------
569 # utility functions, for convenience
569 # utility functions, for convenience
570 #-----------------------------------------------------------------------------
570 #-----------------------------------------------------------------------------
571
571
572 def boolean_flag(name, configurable, set_help='', unset_help=''):
572 def boolean_flag(name, configurable, set_help='', unset_help=''):
573 """Helper for building basic --trait, --no-trait flags.
573 """Helper for building basic --trait, --no-trait flags.
574
574
575 Parameters
575 Parameters
576 ----------
576 ----------
577
577
578 name : str
578 name : str
579 The name of the flag.
579 The name of the flag.
580 configurable : str
580 configurable : str
581 The 'Class.trait' string of the trait to be set/unset with the flag
581 The 'Class.trait' string of the trait to be set/unset with the flag
582 set_help : unicode
582 set_help : unicode
583 help string for --name flag
583 help string for --name flag
584 unset_help : unicode
584 unset_help : unicode
585 help string for --no-name flag
585 help string for --no-name flag
586
586
587 Returns
587 Returns
588 -------
588 -------
589
589
590 cfg : dict
590 cfg : dict
591 A dict with two keys: 'name', and 'no-name', for setting and unsetting
591 A dict with two keys: 'name', and 'no-name', for setting and unsetting
592 the trait, respectively.
592 the trait, respectively.
593 """
593 """
594 # default helpstrings
594 # default helpstrings
595 set_help = set_help or "set %s=True"%configurable
595 set_help = set_help or "set %s=True"%configurable
596 unset_help = unset_help or "set %s=False"%configurable
596 unset_help = unset_help or "set %s=False"%configurable
597
597
598 cls,trait = configurable.split('.')
598 cls,trait = configurable.split('.')
599
599
600 setter = {cls : {trait : True}}
600 setter = {cls : {trait : True}}
601 unsetter = {cls : {trait : False}}
601 unsetter = {cls : {trait : False}}
602 return {name : (setter, set_help), 'no-'+name : (unsetter, unset_help)}
602 return {name : (setter, set_help), 'no-'+name : (unsetter, unset_help)}
603
603
@@ -1,841 +1,840 b''
1 """A simple configuration system.
1 """A simple configuration system.
2
2
3 Inheritance diagram:
3 Inheritance diagram:
4
4
5 .. inheritance-diagram:: IPython.config.loader
5 .. inheritance-diagram:: IPython.config.loader
6 :parts: 3
6 :parts: 3
7
7
8 Authors
8 Authors
9 -------
9 -------
10 * Brian Granger
10 * Brian Granger
11 * Fernando Perez
11 * Fernando Perez
12 * Min RK
12 * Min RK
13 """
13 """
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Copyright (C) 2008-2011 The IPython Development Team
16 # Copyright (C) 2008-2011 The IPython Development Team
17 #
17 #
18 # Distributed under the terms of the BSD License. The full license is in
18 # Distributed under the terms of the BSD License. The full license is in
19 # the file COPYING, distributed as part of this software.
19 # the file COPYING, distributed as part of this software.
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Imports
23 # Imports
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 import argparse
26 import argparse
27 import copy
27 import copy
28 import os
28 import os
29 import re
29 import re
30 import sys
30 import sys
31 import json
31 import json
32
32
33 from IPython.utils.path import filefind, get_ipython_dir
33 from IPython.utils.path import filefind, get_ipython_dir
34 from IPython.utils import py3compat
34 from IPython.utils import py3compat
35 from IPython.utils.encoding import DEFAULT_ENCODING
35 from IPython.utils.encoding import DEFAULT_ENCODING
36 from IPython.utils.py3compat import unicode_type, iteritems
36 from IPython.utils.py3compat import unicode_type, iteritems
37 from IPython.utils.traitlets import HasTraits, List, Any, TraitError
37 from IPython.utils.traitlets import HasTraits, List, Any, TraitError
38
38
39 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
40 # Exceptions
40 # Exceptions
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42
42
43
43
44 class ConfigError(Exception):
44 class ConfigError(Exception):
45 pass
45 pass
46
46
47 class ConfigLoaderError(ConfigError):
47 class ConfigLoaderError(ConfigError):
48 pass
48 pass
49
49
50 class ConfigFileNotFound(ConfigError):
50 class ConfigFileNotFound(ConfigError):
51 pass
51 pass
52
52
53 class ArgumentError(ConfigLoaderError):
53 class ArgumentError(ConfigLoaderError):
54 pass
54 pass
55
55
56 #-----------------------------------------------------------------------------
56 #-----------------------------------------------------------------------------
57 # Argparse fix
57 # Argparse fix
58 #-----------------------------------------------------------------------------
58 #-----------------------------------------------------------------------------
59
59
60 # Unfortunately argparse by default prints help messages to stderr instead of
60 # Unfortunately argparse by default prints help messages to stderr instead of
61 # stdout. This makes it annoying to capture long help screens at the command
61 # stdout. This makes it annoying to capture long help screens at the command
62 # line, since one must know how to pipe stderr, which many users don't know how
62 # line, since one must know how to pipe stderr, which many users don't know how
63 # to do. So we override the print_help method with one that defaults to
63 # to do. So we override the print_help method with one that defaults to
64 # stdout and use our class instead.
64 # stdout and use our class instead.
65
65
66 class ArgumentParser(argparse.ArgumentParser):
66 class ArgumentParser(argparse.ArgumentParser):
67 """Simple argparse subclass that prints help to stdout by default."""
67 """Simple argparse subclass that prints help to stdout by default."""
68
68
69 def print_help(self, file=None):
69 def print_help(self, file=None):
70 if file is None:
70 if file is None:
71 file = sys.stdout
71 file = sys.stdout
72 return super(ArgumentParser, self).print_help(file)
72 return super(ArgumentParser, self).print_help(file)
73
73
74 print_help.__doc__ = argparse.ArgumentParser.print_help.__doc__
74 print_help.__doc__ = argparse.ArgumentParser.print_help.__doc__
75
75
76 #-----------------------------------------------------------------------------
76 #-----------------------------------------------------------------------------
77 # Config class for holding config information
77 # Config class for holding config information
78 #-----------------------------------------------------------------------------
78 #-----------------------------------------------------------------------------
79
79
80 class LazyConfigValue(HasTraits):
80 class LazyConfigValue(HasTraits):
81 """Proxy object for exposing methods on configurable containers
81 """Proxy object for exposing methods on configurable containers
82
82
83 Exposes:
83 Exposes:
84
84
85 - append, extend, insert on lists
85 - append, extend, insert on lists
86 - update on dicts
86 - update on dicts
87 - update, add on sets
87 - update, add on sets
88 """
88 """
89
89
90 _value = None
90 _value = None
91
91
92 # list methods
92 # list methods
93 _extend = List()
93 _extend = List()
94 _prepend = List()
94 _prepend = List()
95
95
96 def append(self, obj):
96 def append(self, obj):
97 self._extend.append(obj)
97 self._extend.append(obj)
98
98
99 def extend(self, other):
99 def extend(self, other):
100 self._extend.extend(other)
100 self._extend.extend(other)
101
101
102 def prepend(self, other):
102 def prepend(self, other):
103 """like list.extend, but for the front"""
103 """like list.extend, but for the front"""
104 self._prepend[:0] = other
104 self._prepend[:0] = other
105
105
106 _inserts = List()
106 _inserts = List()
107 def insert(self, index, other):
107 def insert(self, index, other):
108 if not isinstance(index, int):
108 if not isinstance(index, int):
109 raise TypeError("An integer is required")
109 raise TypeError("An integer is required")
110 self._inserts.append((index, other))
110 self._inserts.append((index, other))
111
111
112 # dict methods
112 # dict methods
113 # update is used for both dict and set
113 # update is used for both dict and set
114 _update = Any()
114 _update = Any()
115 def update(self, other):
115 def update(self, other):
116 if self._update is None:
116 if self._update is None:
117 if isinstance(other, dict):
117 if isinstance(other, dict):
118 self._update = {}
118 self._update = {}
119 else:
119 else:
120 self._update = set()
120 self._update = set()
121 self._update.update(other)
121 self._update.update(other)
122
122
123 # set methods
123 # set methods
124 def add(self, obj):
124 def add(self, obj):
125 self.update({obj})
125 self.update({obj})
126
126
127 def get_value(self, initial):
127 def get_value(self, initial):
128 """construct the value from the initial one
128 """construct the value from the initial one
129
129
130 after applying any insert / extend / update changes
130 after applying any insert / extend / update changes
131 """
131 """
132 if self._value is not None:
132 if self._value is not None:
133 return self._value
133 return self._value
134 value = copy.deepcopy(initial)
134 value = copy.deepcopy(initial)
135 if isinstance(value, list):
135 if isinstance(value, list):
136 for idx, obj in self._inserts:
136 for idx, obj in self._inserts:
137 value.insert(idx, obj)
137 value.insert(idx, obj)
138 value[:0] = self._prepend
138 value[:0] = self._prepend
139 value.extend(self._extend)
139 value.extend(self._extend)
140
140
141 elif isinstance(value, dict):
141 elif isinstance(value, dict):
142 if self._update:
142 if self._update:
143 value.update(self._update)
143 value.update(self._update)
144 elif isinstance(value, set):
144 elif isinstance(value, set):
145 if self._update:
145 if self._update:
146 value.update(self._update)
146 value.update(self._update)
147 self._value = value
147 self._value = value
148 return value
148 return value
149
149
150 def to_dict(self):
150 def to_dict(self):
151 """return JSONable dict form of my data
151 """return JSONable dict form of my data
152
152
153 Currently update as dict or set, extend, prepend as lists, and inserts as list of tuples.
153 Currently update as dict or set, extend, prepend as lists, and inserts as list of tuples.
154 """
154 """
155 d = {}
155 d = {}
156 if self._update:
156 if self._update:
157 d['update'] = self._update
157 d['update'] = self._update
158 if self._extend:
158 if self._extend:
159 d['extend'] = self._extend
159 d['extend'] = self._extend
160 if self._prepend:
160 if self._prepend:
161 d['prepend'] = self._prepend
161 d['prepend'] = self._prepend
162 elif self._inserts:
162 elif self._inserts:
163 d['inserts'] = self._inserts
163 d['inserts'] = self._inserts
164 return d
164 return d
165
165
166
166
167 def _is_section_key(key):
167 def _is_section_key(key):
168 """Is a Config key a section name (does it start with a capital)?"""
168 """Is a Config key a section name (does it start with a capital)?"""
169 if key and key[0].upper()==key[0] and not key.startswith('_'):
169 if key and key[0].upper()==key[0] and not key.startswith('_'):
170 return True
170 return True
171 else:
171 else:
172 return False
172 return False
173
173
174
174
175 class Config(dict):
175 class Config(dict):
176 """An attribute based dict that can do smart merges."""
176 """An attribute based dict that can do smart merges."""
177
177
178 def __init__(self, *args, **kwds):
178 def __init__(self, *args, **kwds):
179 dict.__init__(self, *args, **kwds)
179 dict.__init__(self, *args, **kwds)
180 self._ensure_subconfig()
180 self._ensure_subconfig()
181
181
182 def _ensure_subconfig(self):
182 def _ensure_subconfig(self):
183 """ensure that sub-dicts that should be Config objects are
183 """ensure that sub-dicts that should be Config objects are
184
184
185 casts dicts that are under section keys to Config objects,
185 casts dicts that are under section keys to Config objects,
186 which is necessary for constructing Config objects from dict literals.
186 which is necessary for constructing Config objects from dict literals.
187 """
187 """
188 for key in self:
188 for key in self:
189 obj = self[key]
189 obj = self[key]
190 if _is_section_key(key) \
190 if _is_section_key(key) \
191 and isinstance(obj, dict) \
191 and isinstance(obj, dict) \
192 and not isinstance(obj, Config):
192 and not isinstance(obj, Config):
193 setattr(self, key, Config(obj))
193 setattr(self, key, Config(obj))
194
194
195 def _merge(self, other):
195 def _merge(self, other):
196 """deprecated alias, use Config.merge()"""
196 """deprecated alias, use Config.merge()"""
197 self.merge(other)
197 self.merge(other)
198
198
199 def merge(self, other):
199 def merge(self, other):
200 """merge another config object into this one"""
200 """merge another config object into this one"""
201 to_update = {}
201 to_update = {}
202 for k, v in iteritems(other):
202 for k, v in iteritems(other):
203 if k not in self:
203 if k not in self:
204 to_update[k] = copy.deepcopy(v)
204 to_update[k] = copy.deepcopy(v)
205 else: # I have this key
205 else: # I have this key
206 if isinstance(v, Config) and isinstance(self[k], Config):
206 if isinstance(v, Config) and isinstance(self[k], Config):
207 # Recursively merge common sub Configs
207 # Recursively merge common sub Configs
208 self[k].merge(v)
208 self[k].merge(v)
209 else:
209 else:
210 # Plain updates for non-Configs
210 # Plain updates for non-Configs
211 to_update[k] = copy.deepcopy(v)
211 to_update[k] = copy.deepcopy(v)
212
212
213 self.update(to_update)
213 self.update(to_update)
214
214
215 def __contains__(self, key):
215 def __contains__(self, key):
216 # allow nested contains of the form `"Section.key" in config`
216 # allow nested contains of the form `"Section.key" in config`
217 if '.' in key:
217 if '.' in key:
218 first, remainder = key.split('.', 1)
218 first, remainder = key.split('.', 1)
219 if first not in self:
219 if first not in self:
220 return False
220 return False
221 return remainder in self[first]
221 return remainder in self[first]
222
222
223 return super(Config, self).__contains__(key)
223 return super(Config, self).__contains__(key)
224
224
225 # .has_key is deprecated for dictionaries.
225 # .has_key is deprecated for dictionaries.
226 has_key = __contains__
226 has_key = __contains__
227
227
228 def _has_section(self, key):
228 def _has_section(self, key):
229 return _is_section_key(key) and key in self
229 return _is_section_key(key) and key in self
230
230
231 def copy(self):
231 def copy(self):
232 return type(self)(dict.copy(self))
232 return type(self)(dict.copy(self))
233
233
234 def __copy__(self):
234 def __copy__(self):
235 return self.copy()
235 return self.copy()
236
236
237 def __deepcopy__(self, memo):
237 def __deepcopy__(self, memo):
238 import copy
238 import copy
239 return type(self)(copy.deepcopy(list(self.items())))
239 return type(self)(copy.deepcopy(list(self.items())))
240
240
241 def __getitem__(self, key):
241 def __getitem__(self, key):
242 try:
242 try:
243 return dict.__getitem__(self, key)
243 return dict.__getitem__(self, key)
244 except KeyError:
244 except KeyError:
245 if _is_section_key(key):
245 if _is_section_key(key):
246 c = Config()
246 c = Config()
247 dict.__setitem__(self, key, c)
247 dict.__setitem__(self, key, c)
248 return c
248 return c
249 else:
249 else:
250 # undefined, create lazy value, used for container methods
250 # undefined, create lazy value, used for container methods
251 v = LazyConfigValue()
251 v = LazyConfigValue()
252 dict.__setitem__(self, key, v)
252 dict.__setitem__(self, key, v)
253 return v
253 return v
254
254
255 def __setitem__(self, key, value):
255 def __setitem__(self, key, value):
256 if _is_section_key(key):
256 if _is_section_key(key):
257 if not isinstance(value, Config):
257 if not isinstance(value, Config):
258 raise ValueError('values whose keys begin with an uppercase '
258 raise ValueError('values whose keys begin with an uppercase '
259 'char must be Config instances: %r, %r' % (key, value))
259 'char must be Config instances: %r, %r' % (key, value))
260 dict.__setitem__(self, key, value)
260 dict.__setitem__(self, key, value)
261
261
262 def __getattr__(self, key):
262 def __getattr__(self, key):
263 if key.startswith('__'):
263 if key.startswith('__'):
264 return dict.__getattr__(self, key)
264 return dict.__getattr__(self, key)
265 try:
265 try:
266 return self.__getitem__(key)
266 return self.__getitem__(key)
267 except KeyError as e:
267 except KeyError as e:
268 raise AttributeError(e)
268 raise AttributeError(e)
269
269
270 def __setattr__(self, key, value):
270 def __setattr__(self, key, value):
271 if key.startswith('__'):
271 if key.startswith('__'):
272 return dict.__setattr__(self, key, value)
272 return dict.__setattr__(self, key, value)
273 try:
273 try:
274 self.__setitem__(key, value)
274 self.__setitem__(key, value)
275 except KeyError as e:
275 except KeyError as e:
276 raise AttributeError(e)
276 raise AttributeError(e)
277
277
278 def __delattr__(self, key):
278 def __delattr__(self, key):
279 if key.startswith('__'):
279 if key.startswith('__'):
280 return dict.__delattr__(self, key)
280 return dict.__delattr__(self, key)
281 try:
281 try:
282 dict.__delitem__(self, key)
282 dict.__delitem__(self, key)
283 except KeyError as e:
283 except KeyError as e:
284 raise AttributeError(e)
284 raise AttributeError(e)
285
285
286
286
287 #-----------------------------------------------------------------------------
287 #-----------------------------------------------------------------------------
288 # Config loading classes
288 # Config loading classes
289 #-----------------------------------------------------------------------------
289 #-----------------------------------------------------------------------------
290
290
291
291
292 class ConfigLoader(object):
292 class ConfigLoader(object):
293 """A object for loading configurations from just about anywhere.
293 """A object for loading configurations from just about anywhere.
294
294
295 The resulting configuration is packaged as a :class:`Struct`.
295 The resulting configuration is packaged as a :class:`Config`.
296
296
297 Notes
297 Notes
298 -----
298 -----
299 A :class:`ConfigLoader` does one thing: load a config from a source
299 A :class:`ConfigLoader` does one thing: load a config from a source
300 (file, command line arguments) and returns the data as a :class:`Struct`.
300 (file, command line arguments) and returns the data as a :class:`Config` object.
301 There are lots of things that :class:`ConfigLoader` does not do. It does
301 There are lots of things that :class:`ConfigLoader` does not do. It does
302 not implement complex logic for finding config files. It does not handle
302 not implement complex logic for finding config files. It does not handle
303 default values or merge multiple configs. These things need to be
303 default values or merge multiple configs. These things need to be
304 handled elsewhere.
304 handled elsewhere.
305 """
305 """
306
306
307 def _log_default(self):
307 def _log_default(self):
308 from IPython.config.application import Application
308 from IPython.config.application import Application
309 return Application.instance().log
309 return Application.instance().log
310
310
311 def __init__(self, log=None):
311 def __init__(self, log=None):
312 """A base class for config loaders.
312 """A base class for config loaders.
313
313
314 log : instance of :class:`logging.Logger` to use.
314 log : instance of :class:`logging.Logger` to use.
315 By default loger of :meth:`IPython.config.application.Application.instance()`
315 By default loger of :meth:`IPython.config.application.Application.instance()`
316 will be used
316 will be used
317
317
318 Examples
318 Examples
319 --------
319 --------
320
320
321 >>> cl = ConfigLoader()
321 >>> cl = ConfigLoader()
322 >>> config = cl.load_config()
322 >>> config = cl.load_config()
323 >>> config
323 >>> config
324 {}
324 {}
325 """
325 """
326 self.clear()
326 self.clear()
327 if log is None :
327 if log is None:
328 self.log = self._log_default()
328 self.log = self._log_default()
329 self.log.debug('Using default logger')
329 self.log.debug('Using default logger')
330 else :
330 else:
331 self.log = log
331 self.log = log
332
332
333 def clear(self):
333 def clear(self):
334 self.config = Config()
334 self.config = Config()
335
335
336 def load_config(self):
336 def load_config(self):
337 """Load a config from somewhere, return a :class:`Config` instance.
337 """Load a config from somewhere, return a :class:`Config` instance.
338
338
339 Usually, this will cause self.config to be set and then returned.
339 Usually, this will cause self.config to be set and then returned.
340 However, in most cases, :meth:`ConfigLoader.clear` should be called
340 However, in most cases, :meth:`ConfigLoader.clear` should be called
341 to erase any previous state.
341 to erase any previous state.
342 """
342 """
343 self.clear()
343 self.clear()
344 return self.config
344 return self.config
345
345
346
346
347 class FileConfigLoader(ConfigLoader):
347 class FileConfigLoader(ConfigLoader):
348 """A base class for file based configurations.
348 """A base class for file based configurations.
349
349
350 As we add more file based config loaders, the common logic should go
350 As we add more file based config loaders, the common logic should go
351 here.
351 here.
352 """
352 """
353
353
354 def __init__(self, filename, path=None, **kw):
354 def __init__(self, filename, path=None, **kw):
355 """Build a config loader for a filename and path.
355 """Build a config loader for a filename and path.
356
356
357 Parameters
357 Parameters
358 ----------
358 ----------
359 filename : str
359 filename : str
360 The file name of the config file.
360 The file name of the config file.
361 path : str, list, tuple
361 path : str, list, tuple
362 The path to search for the config file on, or a sequence of
362 The path to search for the config file on, or a sequence of
363 paths to try in order.
363 paths to try in order.
364 """
364 """
365 super(FileConfigLoader, self).__init__(**kw)
365 super(FileConfigLoader, self).__init__(**kw)
366 self.filename = filename
366 self.filename = filename
367 self.path = path
367 self.path = path
368 self.full_filename = ''
368 self.full_filename = ''
369
369
370 def _find_file(self):
370 def _find_file(self):
371 """Try to find the file by searching the paths."""
371 """Try to find the file by searching the paths."""
372 self.full_filename = filefind(self.filename, self.path)
372 self.full_filename = filefind(self.filename, self.path)
373
373
374 class JSONFileConfigLoader(FileConfigLoader):
374 class JSONFileConfigLoader(FileConfigLoader):
375 """A Json file loader for config"""
375 """A Json file loader for config"""
376
376
377 def load_config(self):
377 def load_config(self):
378 """Load the config from a file and return it as a Struct."""
378 """Load the config from a file and return it as a Config object."""
379 self.clear()
379 self.clear()
380 try:
380 try:
381 self._find_file()
381 self._find_file()
382 except IOError as e:
382 except IOError as e:
383 raise ConfigFileNotFound(str(e))
383 raise ConfigFileNotFound(str(e))
384 dct = self._read_file_as_dict()
384 dct = self._read_file_as_dict()
385 self.config = self._convert_to_config(dct)
385 self.config = self._convert_to_config(dct)
386 return self.config
386 return self.config
387
387
388 def _read_file_as_dict(self):
388 def _read_file_as_dict(self):
389 with open(self.full_filename) as f :
389 with open(self.full_filename) as f:
390 return json.load(f)
390 return json.load(f)
391
391
392 def _convert_to_config(self, dictionary):
392 def _convert_to_config(self, dictionary):
393 if 'version' in dictionary:
393 if 'version' in dictionary:
394 version = dictionary.pop('version')
394 version = dictionary.pop('version')
395 else :
395 else:
396 version = 1
396 version = 1
397 self.log.warn("Unrecognized JSON config file version, assuming version : {}".format(version))
397 self.log.warn("Unrecognized JSON config file version, assuming version {}".format(version))
398
398
399 if version == 1:
399 if version == 1:
400 return Config(dictionary)
400 return Config(dictionary)
401 else :
401 else:
402 raise ValueError('Unknown version of JSON config file : version number {version}'.format(version=version))
402 raise ValueError('Unknown version of JSON config file: {version}'.format(version=version))
403
403
404
404
405 class PyFileConfigLoader(FileConfigLoader):
405 class PyFileConfigLoader(FileConfigLoader):
406 """A config loader for pure python files.
406 """A config loader for pure python files.
407
407
408 This is responsible for locating a Python config file by filename and
408 This is responsible for locating a Python config file by filename and
409 profile name, then executing it in a namespace where it could have access
409 path, then executing it to construct a Config object.
410 to subconfigs.
411 """
410 """
412
411
413 def load_config(self):
412 def load_config(self):
414 """Load the config from a file and return it as a Struct."""
413 """Load the config from a file and return it as a Config object."""
415 self.clear()
414 self.clear()
416 try:
415 try:
417 self._find_file()
416 self._find_file()
418 except IOError as e:
417 except IOError as e:
419 raise ConfigFileNotFound(str(e))
418 raise ConfigFileNotFound(str(e))
420 self._read_file_as_dict()
419 self._read_file_as_dict()
421 return self.config
420 return self.config
422
421
423
422
424 def _read_file_as_dict(self):
423 def _read_file_as_dict(self):
425 """Load the config file into self.config, with recursive loading."""
424 """Load the config file into self.config, with recursive loading."""
426 # This closure is made available in the namespace that is used
425 # This closure is made available in the namespace that is used
427 # to exec the config file. It allows users to call
426 # to exec the config file. It allows users to call
428 # load_subconfig('myconfig.py') to load config files recursively.
427 # load_subconfig('myconfig.py') to load config files recursively.
429 # It needs to be a closure because it has references to self.path
428 # It needs to be a closure because it has references to self.path
430 # and self.config. The sub-config is loaded with the same path
429 # and self.config. The sub-config is loaded with the same path
431 # as the parent, but it uses an empty config which is then merged
430 # as the parent, but it uses an empty config which is then merged
432 # with the parents.
431 # with the parents.
433
432
434 # If a profile is specified, the config file will be loaded
433 # If a profile is specified, the config file will be loaded
435 # from that profile
434 # from that profile
436
435
437 def load_subconfig(fname, profile=None):
436 def load_subconfig(fname, profile=None):
438 # import here to prevent circular imports
437 # import here to prevent circular imports
439 from IPython.core.profiledir import ProfileDir, ProfileDirError
438 from IPython.core.profiledir import ProfileDir, ProfileDirError
440 if profile is not None:
439 if profile is not None:
441 try:
440 try:
442 profile_dir = ProfileDir.find_profile_dir_by_name(
441 profile_dir = ProfileDir.find_profile_dir_by_name(
443 get_ipython_dir(),
442 get_ipython_dir(),
444 profile,
443 profile,
445 )
444 )
446 except ProfileDirError:
445 except ProfileDirError:
447 return
446 return
448 path = profile_dir.location
447 path = profile_dir.location
449 else:
448 else:
450 path = self.path
449 path = self.path
451 loader = PyFileConfigLoader(fname, path)
450 loader = PyFileConfigLoader(fname, path)
452 try:
451 try:
453 sub_config = loader.load_config()
452 sub_config = loader.load_config()
454 except ConfigFileNotFound:
453 except ConfigFileNotFound:
455 # Pass silently if the sub config is not there. This happens
454 # Pass silently if the sub config is not there. This happens
456 # when a user s using a profile, but not the default config.
455 # when a user s using a profile, but not the default config.
457 pass
456 pass
458 else:
457 else:
459 self.config.merge(sub_config)
458 self.config.merge(sub_config)
460
459
461 # Again, this needs to be a closure and should be used in config
460 # Again, this needs to be a closure and should be used in config
462 # files to get the config being loaded.
461 # files to get the config being loaded.
463 def get_config():
462 def get_config():
464 return self.config
463 return self.config
465
464
466 namespace = dict(
465 namespace = dict(
467 load_subconfig=load_subconfig,
466 load_subconfig=load_subconfig,
468 get_config=get_config,
467 get_config=get_config,
469 __file__=self.full_filename,
468 __file__=self.full_filename,
470 )
469 )
471 fs_encoding = sys.getfilesystemencoding() or 'ascii'
470 fs_encoding = sys.getfilesystemencoding() or 'ascii'
472 conf_filename = self.full_filename.encode(fs_encoding)
471 conf_filename = self.full_filename.encode(fs_encoding)
473 py3compat.execfile(conf_filename, namespace)
472 py3compat.execfile(conf_filename, namespace)
474
473
475
474
476 class CommandLineConfigLoader(ConfigLoader):
475 class CommandLineConfigLoader(ConfigLoader):
477 """A config loader for command line arguments.
476 """A config loader for command line arguments.
478
477
479 As we add more command line based loaders, the common logic should go
478 As we add more command line based loaders, the common logic should go
480 here.
479 here.
481 """
480 """
482
481
483 def _exec_config_str(self, lhs, rhs):
482 def _exec_config_str(self, lhs, rhs):
484 """execute self.config.<lhs> = <rhs>
483 """execute self.config.<lhs> = <rhs>
485
484
486 * expands ~ with expanduser
485 * expands ~ with expanduser
487 * tries to assign with raw eval, otherwise assigns with just the string,
486 * tries to assign with raw eval, otherwise assigns with just the string,
488 allowing `--C.a=foobar` and `--C.a="foobar"` to be equivalent. *Not*
487 allowing `--C.a=foobar` and `--C.a="foobar"` to be equivalent. *Not*
489 equivalent are `--C.a=4` and `--C.a='4'`.
488 equivalent are `--C.a=4` and `--C.a='4'`.
490 """
489 """
491 rhs = os.path.expanduser(rhs)
490 rhs = os.path.expanduser(rhs)
492 try:
491 try:
493 # Try to see if regular Python syntax will work. This
492 # Try to see if regular Python syntax will work. This
494 # won't handle strings as the quote marks are removed
493 # won't handle strings as the quote marks are removed
495 # by the system shell.
494 # by the system shell.
496 value = eval(rhs)
495 value = eval(rhs)
497 except (NameError, SyntaxError):
496 except (NameError, SyntaxError):
498 # This case happens if the rhs is a string.
497 # This case happens if the rhs is a string.
499 value = rhs
498 value = rhs
500
499
501 exec(u'self.config.%s = value' % lhs)
500 exec(u'self.config.%s = value' % lhs)
502
501
503 def _load_flag(self, cfg):
502 def _load_flag(self, cfg):
504 """update self.config from a flag, which can be a dict or Config"""
503 """update self.config from a flag, which can be a dict or Config"""
505 if isinstance(cfg, (dict, Config)):
504 if isinstance(cfg, (dict, Config)):
506 # don't clobber whole config sections, update
505 # don't clobber whole config sections, update
507 # each section from config:
506 # each section from config:
508 for sec,c in iteritems(cfg):
507 for sec,c in iteritems(cfg):
509 self.config[sec].update(c)
508 self.config[sec].update(c)
510 else:
509 else:
511 raise TypeError("Invalid flag: %r" % cfg)
510 raise TypeError("Invalid flag: %r" % cfg)
512
511
513 # raw --identifier=value pattern
512 # raw --identifier=value pattern
514 # but *also* accept '-' as wordsep, for aliases
513 # but *also* accept '-' as wordsep, for aliases
515 # accepts: --foo=a
514 # accepts: --foo=a
516 # --Class.trait=value
515 # --Class.trait=value
517 # --alias-name=value
516 # --alias-name=value
518 # rejects: -foo=value
517 # rejects: -foo=value
519 # --foo
518 # --foo
520 # --Class.trait
519 # --Class.trait
521 kv_pattern = re.compile(r'\-\-[A-Za-z][\w\-]*(\.[\w\-]+)*\=.*')
520 kv_pattern = re.compile(r'\-\-[A-Za-z][\w\-]*(\.[\w\-]+)*\=.*')
522
521
523 # just flags, no assignments, with two *or one* leading '-'
522 # just flags, no assignments, with two *or one* leading '-'
524 # accepts: --foo
523 # accepts: --foo
525 # -foo-bar-again
524 # -foo-bar-again
526 # rejects: --anything=anything
525 # rejects: --anything=anything
527 # --two.word
526 # --two.word
528
527
529 flag_pattern = re.compile(r'\-\-?\w+[\-\w]*$')
528 flag_pattern = re.compile(r'\-\-?\w+[\-\w]*$')
530
529
531 class KeyValueConfigLoader(CommandLineConfigLoader):
530 class KeyValueConfigLoader(CommandLineConfigLoader):
532 """A config loader that loads key value pairs from the command line.
531 """A config loader that loads key value pairs from the command line.
533
532
534 This allows command line options to be gives in the following form::
533 This allows command line options to be gives in the following form::
535
534
536 ipython --profile="foo" --InteractiveShell.autocall=False
535 ipython --profile="foo" --InteractiveShell.autocall=False
537 """
536 """
538
537
539 def __init__(self, argv=None, aliases=None, flags=None, **kw):
538 def __init__(self, argv=None, aliases=None, flags=None, **kw):
540 """Create a key value pair config loader.
539 """Create a key value pair config loader.
541
540
542 Parameters
541 Parameters
543 ----------
542 ----------
544 argv : list
543 argv : list
545 A list that has the form of sys.argv[1:] which has unicode
544 A list that has the form of sys.argv[1:] which has unicode
546 elements of the form u"key=value". If this is None (default),
545 elements of the form u"key=value". If this is None (default),
547 then sys.argv[1:] will be used.
546 then sys.argv[1:] will be used.
548 aliases : dict
547 aliases : dict
549 A dict of aliases for configurable traits.
548 A dict of aliases for configurable traits.
550 Keys are the short aliases, Values are the resolved trait.
549 Keys are the short aliases, Values are the resolved trait.
551 Of the form: `{'alias' : 'Configurable.trait'}`
550 Of the form: `{'alias' : 'Configurable.trait'}`
552 flags : dict
551 flags : dict
553 A dict of flags, keyed by str name. Vaues can be Config objects,
552 A dict of flags, keyed by str name. Vaues can be Config objects,
554 dicts, or "key=value" strings. If Config or dict, when the flag
553 dicts, or "key=value" strings. If Config or dict, when the flag
555 is triggered, The flag is loaded as `self.config.update(m)`.
554 is triggered, The flag is loaded as `self.config.update(m)`.
556
555
557 Returns
556 Returns
558 -------
557 -------
559 config : Config
558 config : Config
560 The resulting Config object.
559 The resulting Config object.
561
560
562 Examples
561 Examples
563 --------
562 --------
564
563
565 >>> from IPython.config.loader import KeyValueConfigLoader
564 >>> from IPython.config.loader import KeyValueConfigLoader
566 >>> cl = KeyValueConfigLoader()
565 >>> cl = KeyValueConfigLoader()
567 >>> d = cl.load_config(["--A.name='brian'","--B.number=0"])
566 >>> d = cl.load_config(["--A.name='brian'","--B.number=0"])
568 >>> sorted(d.items())
567 >>> sorted(d.items())
569 [('A', {'name': 'brian'}), ('B', {'number': 0})]
568 [('A', {'name': 'brian'}), ('B', {'number': 0})]
570 """
569 """
571 super(KeyValueConfigLoader, self).__init__(**kw)
570 super(KeyValueConfigLoader, self).__init__(**kw)
572 if argv is None:
571 if argv is None:
573 argv = sys.argv[1:]
572 argv = sys.argv[1:]
574 self.argv = argv
573 self.argv = argv
575 self.aliases = aliases or {}
574 self.aliases = aliases or {}
576 self.flags = flags or {}
575 self.flags = flags or {}
577
576
578
577
579 def clear(self):
578 def clear(self):
580 super(KeyValueConfigLoader, self).clear()
579 super(KeyValueConfigLoader, self).clear()
581 self.extra_args = []
580 self.extra_args = []
582
581
583
582
584 def _decode_argv(self, argv, enc=None):
583 def _decode_argv(self, argv, enc=None):
585 """decode argv if bytes, using stin.encoding, falling back on default enc"""
584 """decode argv if bytes, using stin.encoding, falling back on default enc"""
586 uargv = []
585 uargv = []
587 if enc is None:
586 if enc is None:
588 enc = DEFAULT_ENCODING
587 enc = DEFAULT_ENCODING
589 for arg in argv:
588 for arg in argv:
590 if not isinstance(arg, unicode_type):
589 if not isinstance(arg, unicode_type):
591 # only decode if not already decoded
590 # only decode if not already decoded
592 arg = arg.decode(enc)
591 arg = arg.decode(enc)
593 uargv.append(arg)
592 uargv.append(arg)
594 return uargv
593 return uargv
595
594
596
595
597 def load_config(self, argv=None, aliases=None, flags=None):
596 def load_config(self, argv=None, aliases=None, flags=None):
598 """Parse the configuration and generate the Config object.
597 """Parse the configuration and generate the Config object.
599
598
600 After loading, any arguments that are not key-value or
599 After loading, any arguments that are not key-value or
601 flags will be stored in self.extra_args - a list of
600 flags will be stored in self.extra_args - a list of
602 unparsed command-line arguments. This is used for
601 unparsed command-line arguments. This is used for
603 arguments such as input files or subcommands.
602 arguments such as input files or subcommands.
604
603
605 Parameters
604 Parameters
606 ----------
605 ----------
607 argv : list, optional
606 argv : list, optional
608 A list that has the form of sys.argv[1:] which has unicode
607 A list that has the form of sys.argv[1:] which has unicode
609 elements of the form u"key=value". If this is None (default),
608 elements of the form u"key=value". If this is None (default),
610 then self.argv will be used.
609 then self.argv will be used.
611 aliases : dict
610 aliases : dict
612 A dict of aliases for configurable traits.
611 A dict of aliases for configurable traits.
613 Keys are the short aliases, Values are the resolved trait.
612 Keys are the short aliases, Values are the resolved trait.
614 Of the form: `{'alias' : 'Configurable.trait'}`
613 Of the form: `{'alias' : 'Configurable.trait'}`
615 flags : dict
614 flags : dict
616 A dict of flags, keyed by str name. Values can be Config objects
615 A dict of flags, keyed by str name. Values can be Config objects
617 or dicts. When the flag is triggered, The config is loaded as
616 or dicts. When the flag is triggered, The config is loaded as
618 `self.config.update(cfg)`.
617 `self.config.update(cfg)`.
619 """
618 """
620 self.clear()
619 self.clear()
621 if argv is None:
620 if argv is None:
622 argv = self.argv
621 argv = self.argv
623 if aliases is None:
622 if aliases is None:
624 aliases = self.aliases
623 aliases = self.aliases
625 if flags is None:
624 if flags is None:
626 flags = self.flags
625 flags = self.flags
627
626
628 # ensure argv is a list of unicode strings:
627 # ensure argv is a list of unicode strings:
629 uargv = self._decode_argv(argv)
628 uargv = self._decode_argv(argv)
630 for idx,raw in enumerate(uargv):
629 for idx,raw in enumerate(uargv):
631 # strip leading '-'
630 # strip leading '-'
632 item = raw.lstrip('-')
631 item = raw.lstrip('-')
633
632
634 if raw == '--':
633 if raw == '--':
635 # don't parse arguments after '--'
634 # don't parse arguments after '--'
636 # this is useful for relaying arguments to scripts, e.g.
635 # this is useful for relaying arguments to scripts, e.g.
637 # ipython -i foo.py --matplotlib=qt -- args after '--' go-to-foo.py
636 # ipython -i foo.py --matplotlib=qt -- args after '--' go-to-foo.py
638 self.extra_args.extend(uargv[idx+1:])
637 self.extra_args.extend(uargv[idx+1:])
639 break
638 break
640
639
641 if kv_pattern.match(raw):
640 if kv_pattern.match(raw):
642 lhs,rhs = item.split('=',1)
641 lhs,rhs = item.split('=',1)
643 # Substitute longnames for aliases.
642 # Substitute longnames for aliases.
644 if lhs in aliases:
643 if lhs in aliases:
645 lhs = aliases[lhs]
644 lhs = aliases[lhs]
646 if '.' not in lhs:
645 if '.' not in lhs:
647 # probably a mistyped alias, but not technically illegal
646 # probably a mistyped alias, but not technically illegal
648 self.log.warn("Unrecognized alias: '%s', it will probably have no effect. %s,-- %s"%(lhs,raw, aliases))
647 self.log.warn("Unrecognized alias: '%s', it will probably have no effect.", raw)
649 try:
648 try:
650 self._exec_config_str(lhs, rhs)
649 self._exec_config_str(lhs, rhs)
651 except Exception:
650 except Exception:
652 raise ArgumentError("Invalid argument: '%s'" % raw)
651 raise ArgumentError("Invalid argument: '%s'" % raw)
653
652
654 elif flag_pattern.match(raw):
653 elif flag_pattern.match(raw):
655 if item in flags:
654 if item in flags:
656 cfg,help = flags[item]
655 cfg,help = flags[item]
657 self._load_flag(cfg)
656 self._load_flag(cfg)
658 else:
657 else:
659 raise ArgumentError("Unrecognized flag: '%s'"%raw)
658 raise ArgumentError("Unrecognized flag: '%s'"%raw)
660 elif raw.startswith('-'):
659 elif raw.startswith('-'):
661 kv = '--'+item
660 kv = '--'+item
662 if kv_pattern.match(kv):
661 if kv_pattern.match(kv):
663 raise ArgumentError("Invalid argument: '%s', did you mean '%s'?"%(raw, kv))
662 raise ArgumentError("Invalid argument: '%s', did you mean '%s'?"%(raw, kv))
664 else:
663 else:
665 raise ArgumentError("Invalid argument: '%s'"%raw)
664 raise ArgumentError("Invalid argument: '%s'"%raw)
666 else:
665 else:
667 # keep all args that aren't valid in a list,
666 # keep all args that aren't valid in a list,
668 # in case our parent knows what to do with them.
667 # in case our parent knows what to do with them.
669 self.extra_args.append(item)
668 self.extra_args.append(item)
670 return self.config
669 return self.config
671
670
672 class ArgParseConfigLoader(CommandLineConfigLoader):
671 class ArgParseConfigLoader(CommandLineConfigLoader):
673 """A loader that uses the argparse module to load from the command line."""
672 """A loader that uses the argparse module to load from the command line."""
674
673
675 def __init__(self, argv=None, aliases=None, flags=None, log=None, *parser_args, **parser_kw):
674 def __init__(self, argv=None, aliases=None, flags=None, log=None, *parser_args, **parser_kw):
676 """Create a config loader for use with argparse.
675 """Create a config loader for use with argparse.
677
676
678 Parameters
677 Parameters
679 ----------
678 ----------
680
679
681 argv : optional, list
680 argv : optional, list
682 If given, used to read command-line arguments from, otherwise
681 If given, used to read command-line arguments from, otherwise
683 sys.argv[1:] is used.
682 sys.argv[1:] is used.
684
683
685 parser_args : tuple
684 parser_args : tuple
686 A tuple of positional arguments that will be passed to the
685 A tuple of positional arguments that will be passed to the
687 constructor of :class:`argparse.ArgumentParser`.
686 constructor of :class:`argparse.ArgumentParser`.
688
687
689 parser_kw : dict
688 parser_kw : dict
690 A tuple of keyword arguments that will be passed to the
689 A tuple of keyword arguments that will be passed to the
691 constructor of :class:`argparse.ArgumentParser`.
690 constructor of :class:`argparse.ArgumentParser`.
692
691
693 Returns
692 Returns
694 -------
693 -------
695 config : Config
694 config : Config
696 The resulting Config object.
695 The resulting Config object.
697 """
696 """
698 super(CommandLineConfigLoader, self).__init__(log=log)
697 super(CommandLineConfigLoader, self).__init__(log=log)
699 self.clear()
698 self.clear()
700 if argv is None:
699 if argv is None:
701 argv = sys.argv[1:]
700 argv = sys.argv[1:]
702 self.argv = argv
701 self.argv = argv
703 self.aliases = aliases or {}
702 self.aliases = aliases or {}
704 self.flags = flags or {}
703 self.flags = flags or {}
705
704
706 self.parser_args = parser_args
705 self.parser_args = parser_args
707 self.version = parser_kw.pop("version", None)
706 self.version = parser_kw.pop("version", None)
708 kwargs = dict(argument_default=argparse.SUPPRESS)
707 kwargs = dict(argument_default=argparse.SUPPRESS)
709 kwargs.update(parser_kw)
708 kwargs.update(parser_kw)
710 self.parser_kw = kwargs
709 self.parser_kw = kwargs
711
710
712 def load_config(self, argv=None, aliases=None, flags=None):
711 def load_config(self, argv=None, aliases=None, flags=None):
713 """Parse command line arguments and return as a Config object.
712 """Parse command line arguments and return as a Config object.
714
713
715 Parameters
714 Parameters
716 ----------
715 ----------
717
716
718 args : optional, list
717 args : optional, list
719 If given, a list with the structure of sys.argv[1:] to parse
718 If given, a list with the structure of sys.argv[1:] to parse
720 arguments from. If not given, the instance's self.argv attribute
719 arguments from. If not given, the instance's self.argv attribute
721 (given at construction time) is used."""
720 (given at construction time) is used."""
722 self.clear()
721 self.clear()
723 if argv is None:
722 if argv is None:
724 argv = self.argv
723 argv = self.argv
725 if aliases is None:
724 if aliases is None:
726 aliases = self.aliases
725 aliases = self.aliases
727 if flags is None:
726 if flags is None:
728 flags = self.flags
727 flags = self.flags
729 self._create_parser(aliases, flags)
728 self._create_parser(aliases, flags)
730 self._parse_args(argv)
729 self._parse_args(argv)
731 self._convert_to_config()
730 self._convert_to_config()
732 return self.config
731 return self.config
733
732
734 def get_extra_args(self):
733 def get_extra_args(self):
735 if hasattr(self, 'extra_args'):
734 if hasattr(self, 'extra_args'):
736 return self.extra_args
735 return self.extra_args
737 else:
736 else:
738 return []
737 return []
739
738
740 def _create_parser(self, aliases=None, flags=None):
739 def _create_parser(self, aliases=None, flags=None):
741 self.parser = ArgumentParser(*self.parser_args, **self.parser_kw)
740 self.parser = ArgumentParser(*self.parser_args, **self.parser_kw)
742 self._add_arguments(aliases, flags)
741 self._add_arguments(aliases, flags)
743
742
744 def _add_arguments(self, aliases=None, flags=None):
743 def _add_arguments(self, aliases=None, flags=None):
745 raise NotImplementedError("subclasses must implement _add_arguments")
744 raise NotImplementedError("subclasses must implement _add_arguments")
746
745
747 def _parse_args(self, args):
746 def _parse_args(self, args):
748 """self.parser->self.parsed_data"""
747 """self.parser->self.parsed_data"""
749 # decode sys.argv to support unicode command-line options
748 # decode sys.argv to support unicode command-line options
750 enc = DEFAULT_ENCODING
749 enc = DEFAULT_ENCODING
751 uargs = [py3compat.cast_unicode(a, enc) for a in args]
750 uargs = [py3compat.cast_unicode(a, enc) for a in args]
752 self.parsed_data, self.extra_args = self.parser.parse_known_args(uargs)
751 self.parsed_data, self.extra_args = self.parser.parse_known_args(uargs)
753
752
754 def _convert_to_config(self):
753 def _convert_to_config(self):
755 """self.parsed_data->self.config"""
754 """self.parsed_data->self.config"""
756 for k, v in iteritems(vars(self.parsed_data)):
755 for k, v in iteritems(vars(self.parsed_data)):
757 exec("self.config.%s = v"%k, locals(), globals())
756 exec("self.config.%s = v"%k, locals(), globals())
758
757
759 class KVArgParseConfigLoader(ArgParseConfigLoader):
758 class KVArgParseConfigLoader(ArgParseConfigLoader):
760 """A config loader that loads aliases and flags with argparse,
759 """A config loader that loads aliases and flags with argparse,
761 but will use KVLoader for the rest. This allows better parsing
760 but will use KVLoader for the rest. This allows better parsing
762 of common args, such as `ipython -c 'print 5'`, but still gets
761 of common args, such as `ipython -c 'print 5'`, but still gets
763 arbitrary config with `ipython --InteractiveShell.use_readline=False`"""
762 arbitrary config with `ipython --InteractiveShell.use_readline=False`"""
764
763
765 def _add_arguments(self, aliases=None, flags=None):
764 def _add_arguments(self, aliases=None, flags=None):
766 self.alias_flags = {}
765 self.alias_flags = {}
767 # print aliases, flags
766 # print aliases, flags
768 if aliases is None:
767 if aliases is None:
769 aliases = self.aliases
768 aliases = self.aliases
770 if flags is None:
769 if flags is None:
771 flags = self.flags
770 flags = self.flags
772 paa = self.parser.add_argument
771 paa = self.parser.add_argument
773 for key,value in iteritems(aliases):
772 for key,value in iteritems(aliases):
774 if key in flags:
773 if key in flags:
775 # flags
774 # flags
776 nargs = '?'
775 nargs = '?'
777 else:
776 else:
778 nargs = None
777 nargs = None
779 if len(key) is 1:
778 if len(key) is 1:
780 paa('-'+key, '--'+key, type=unicode_type, dest=value, nargs=nargs)
779 paa('-'+key, '--'+key, type=unicode_type, dest=value, nargs=nargs)
781 else:
780 else:
782 paa('--'+key, type=unicode_type, dest=value, nargs=nargs)
781 paa('--'+key, type=unicode_type, dest=value, nargs=nargs)
783 for key, (value, help) in iteritems(flags):
782 for key, (value, help) in iteritems(flags):
784 if key in self.aliases:
783 if key in self.aliases:
785 #
784 #
786 self.alias_flags[self.aliases[key]] = value
785 self.alias_flags[self.aliases[key]] = value
787 continue
786 continue
788 if len(key) is 1:
787 if len(key) is 1:
789 paa('-'+key, '--'+key, action='append_const', dest='_flags', const=value)
788 paa('-'+key, '--'+key, action='append_const', dest='_flags', const=value)
790 else:
789 else:
791 paa('--'+key, action='append_const', dest='_flags', const=value)
790 paa('--'+key, action='append_const', dest='_flags', const=value)
792
791
793 def _convert_to_config(self):
792 def _convert_to_config(self):
794 """self.parsed_data->self.config, parse unrecognized extra args via KVLoader."""
793 """self.parsed_data->self.config, parse unrecognized extra args via KVLoader."""
795 # remove subconfigs list from namespace before transforming the Namespace
794 # remove subconfigs list from namespace before transforming the Namespace
796 if '_flags' in self.parsed_data:
795 if '_flags' in self.parsed_data:
797 subcs = self.parsed_data._flags
796 subcs = self.parsed_data._flags
798 del self.parsed_data._flags
797 del self.parsed_data._flags
799 else:
798 else:
800 subcs = []
799 subcs = []
801
800
802 for k, v in iteritems(vars(self.parsed_data)):
801 for k, v in iteritems(vars(self.parsed_data)):
803 if v is None:
802 if v is None:
804 # it was a flag that shares the name of an alias
803 # it was a flag that shares the name of an alias
805 subcs.append(self.alias_flags[k])
804 subcs.append(self.alias_flags[k])
806 else:
805 else:
807 # eval the KV assignment
806 # eval the KV assignment
808 self._exec_config_str(k, v)
807 self._exec_config_str(k, v)
809
808
810 for subc in subcs:
809 for subc in subcs:
811 self._load_flag(subc)
810 self._load_flag(subc)
812
811
813 if self.extra_args:
812 if self.extra_args:
814 sub_parser = KeyValueConfigLoader(log=self.log)
813 sub_parser = KeyValueConfigLoader(log=self.log)
815 sub_parser.load_config(self.extra_args)
814 sub_parser.load_config(self.extra_args)
816 self.config.merge(sub_parser.config)
815 self.config.merge(sub_parser.config)
817 self.extra_args = sub_parser.extra_args
816 self.extra_args = sub_parser.extra_args
818
817
819
818
820 def load_pyconfig_files(config_files, path):
819 def load_pyconfig_files(config_files, path):
821 """Load multiple Python config files, merging each of them in turn.
820 """Load multiple Python config files, merging each of them in turn.
822
821
823 Parameters
822 Parameters
824 ==========
823 ==========
825 config_files : list of str
824 config_files : list of str
826 List of config files names to load and merge into the config.
825 List of config files names to load and merge into the config.
827 path : unicode
826 path : unicode
828 The full path to the location of the config files.
827 The full path to the location of the config files.
829 """
828 """
830 config = Config()
829 config = Config()
831 for cf in config_files:
830 for cf in config_files:
832 loader = PyFileConfigLoader(cf, path=path)
831 loader = PyFileConfigLoader(cf, path=path)
833 try:
832 try:
834 next_config = loader.load_config()
833 next_config = loader.load_config()
835 except ConfigFileNotFound:
834 except ConfigFileNotFound:
836 pass
835 pass
837 except:
836 except:
838 raise
837 raise
839 else:
838 else:
840 config.merge(next_config)
839 config.merge(next_config)
841 return config
840 return config
@@ -1,566 +1,566 b''
1 .. _config_overview:
1 .. _config_overview:
2
2
3 ============================================
3 ============================================
4 Overview of the IPython configuration system
4 Overview of the IPython configuration system
5 ============================================
5 ============================================
6
6
7 This section describes the IPython configuration system.
7 This section describes the IPython configuration system.
8
8
9 The main concepts
9 The main concepts
10 =================
10 =================
11
11
12 There are a number of abstractions that the IPython configuration system uses.
12 There are a number of abstractions that the IPython configuration system uses.
13 Each of these abstractions is represented by a Python class.
13 Each of these abstractions is represented by a Python class.
14
14
15 Configuration object: :class:`~IPython.config.loader.Config`
15 Configuration object: :class:`~IPython.config.loader.Config`
16 A configuration object is a simple dictionary-like class that holds
16 A configuration object is a simple dictionary-like class that holds
17 configuration attributes and sub-configuration objects. These classes
17 configuration attributes and sub-configuration objects. These classes
18 support dotted attribute style access (``cfg.Foo.bar``) in addition to the
18 support dotted attribute style access (``cfg.Foo.bar``) in addition to the
19 regular dictionary style access (``cfg['Foo']['bar']``).
19 regular dictionary style access (``cfg['Foo']['bar']``).
20 The Config object is a wrapper around a simple dictionary with some convenience methods,
20 The Config object is a wrapper around a simple dictionary with some convenience methods,
21 such as merging and automatic section creation.
21 such as merging and automatic section creation.
22
22
23 Application: :class:`~IPython.config.application.Application`
23 Application: :class:`~IPython.config.application.Application`
24 An application is a process that does a specific job. The most obvious
24 An application is a process that does a specific job. The most obvious
25 application is the :command:`ipython` command line program. Each
25 application is the :command:`ipython` command line program. Each
26 application reads *one or more* configuration files and a single set of
26 application reads *one or more* configuration files and a single set of
27 command line options
27 command line options
28 and then produces a master configuration object for the application. This
28 and then produces a master configuration object for the application. This
29 configuration object is then passed to the configurable objects that the
29 configuration object is then passed to the configurable objects that the
30 application creates. These configurable objects implement the actual logic
30 application creates. These configurable objects implement the actual logic
31 of the application and know how to configure themselves given the
31 of the application and know how to configure themselves given the
32 configuration object.
32 configuration object.
33
33
34 Applications always have a `log` attribute that is a configured Logger.
34 Applications always have a `log` attribute that is a configured Logger.
35 This allows centralized logging configuration per-application.
35 This allows centralized logging configuration per-application.
36
36
37 Configurable: :class:`~IPython.config.configurable.Configurable`
37 Configurable: :class:`~IPython.config.configurable.Configurable`
38 A configurable is a regular Python class that serves as a base class for
38 A configurable is a regular Python class that serves as a base class for
39 all main classes in an application. The
39 all main classes in an application. The
40 :class:`~IPython.config.configurable.Configurable` base class is
40 :class:`~IPython.config.configurable.Configurable` base class is
41 lightweight and only does one things.
41 lightweight and only does one things.
42
42
43 This :class:`~IPython.config.configurable.Configurable` is a subclass
43 This :class:`~IPython.config.configurable.Configurable` is a subclass
44 of :class:`~IPython.utils.traitlets.HasTraits` that knows how to configure
44 of :class:`~IPython.utils.traitlets.HasTraits` that knows how to configure
45 itself. Class level traits with the metadata ``config=True`` become
45 itself. Class level traits with the metadata ``config=True`` become
46 values that can be configured from the command line and configuration
46 values that can be configured from the command line and configuration
47 files.
47 files.
48
48
49 Developers create :class:`~IPython.config.configurable.Configurable`
49 Developers create :class:`~IPython.config.configurable.Configurable`
50 subclasses that implement all of the logic in the application. Each of
50 subclasses that implement all of the logic in the application. Each of
51 these subclasses has its own configuration information that controls how
51 these subclasses has its own configuration information that controls how
52 instances are created.
52 instances are created.
53
53
54 Singletons: :class:`~IPython.config.configurable.SingletonConfigurable`
54 Singletons: :class:`~IPython.config.configurable.SingletonConfigurable`
55 Any object for which there is a single canonical instance. These are
55 Any object for which there is a single canonical instance. These are
56 just like Configurables, except they have a class method
56 just like Configurables, except they have a class method
57 :meth:`~IPython.config.configurable.SingletonConfigurable.instance`,
57 :meth:`~IPython.config.configurable.SingletonConfigurable.instance`,
58 that returns the current active instance (or creates one if it
58 that returns the current active instance (or creates one if it
59 does not exist). Examples of singletons include
59 does not exist). Examples of singletons include
60 :class:`~IPython.config.application.Application`s and
60 :class:`~IPython.config.application.Application`s and
61 :class:`~IPython.core.interactiveshell.InteractiveShell`. This lets
61 :class:`~IPython.core.interactiveshell.InteractiveShell`. This lets
62 objects easily connect to the current running Application without passing
62 objects easily connect to the current running Application without passing
63 objects around everywhere. For instance, to get the current running
63 objects around everywhere. For instance, to get the current running
64 Application instance, simply do: ``app = Application.instance()``.
64 Application instance, simply do: ``app = Application.instance()``.
65
65
66
66
67 .. note::
67 .. note::
68
68
69 Singletons are not strictly enforced - you can have many instances
69 Singletons are not strictly enforced - you can have many instances
70 of a given singleton class, but the :meth:`instance` method will always
70 of a given singleton class, but the :meth:`instance` method will always
71 return the same one.
71 return the same one.
72
72
73 Having described these main concepts, we can now state the main idea in our
73 Having described these main concepts, we can now state the main idea in our
74 configuration system: *"configuration" allows the default values of class
74 configuration system: *"configuration" allows the default values of class
75 attributes to be controlled on a class by class basis*. Thus all instances of
75 attributes to be controlled on a class by class basis*. Thus all instances of
76 a given class are configured in the same way. Furthermore, if two instances
76 a given class are configured in the same way. Furthermore, if two instances
77 need to be configured differently, they need to be instances of two different
77 need to be configured differently, they need to be instances of two different
78 classes. While this model may seem a bit restrictive, we have found that it
78 classes. While this model may seem a bit restrictive, we have found that it
79 expresses most things that need to be configured extremely well. However, it
79 expresses most things that need to be configured extremely well. However, it
80 is possible to create two instances of the same class that have different
80 is possible to create two instances of the same class that have different
81 trait values. This is done by overriding the configuration.
81 trait values. This is done by overriding the configuration.
82
82
83 Now, we show what our configuration objects and files look like.
83 Now, we show what our configuration objects and files look like.
84
84
85 Configuration objects and files
85 Configuration objects and files
86 ===============================
86 ===============================
87
87
88 A configuration object is little more than a wrapper around a dictionary.
88 A configuration object is little more than a wrapper around a dictionary.
89 A configuration *file* is simply a mechanism for producing that object.
89 A configuration *file* is simply a mechanism for producing that object.
90 The main IPython configuration file is a plain Python script,
90 The main IPython configuration file is a plain Python script,
91 which can perform extensive logic to populate the config object.
91 which can perform extensive logic to populate the config object.
92 IPython 2.0 introduces a JSON configuration file,
92 IPython 2.0 introduces a JSON configuration file,
93 which is just a direct JSON serialization of the config dictionary.
93 which is just a direct JSON serialization of the config dictionary,
94 The JSON format is easily processed by external software.
94 which is easily processed by external software.
95
95
96 When both Python and JSON configuration file are present, both will be loaded,
96 When both Python and JSON configuration file are present, both will be loaded,
97 with JSON configuration having higher priority.
97 with JSON configuration having higher priority.
98
98
99 Python configuration Files
99 Python configuration Files
100 ~~~~~~~~~~~~~~~~~~~~~~~~~~
100 ~~~~~~~~~~~~~~~~~~~~~~~~~~
101
101
102 A Python configuration file is a pure Python file that populates a configuration object.
102 A Python configuration file is a pure Python file that populates a configuration object.
103 This configuration object is a :class:`~IPython.config.loader.Config` instance.
103 This configuration object is a :class:`~IPython.config.loader.Config` instance.
104 While in a configuration file, to get a reference to this object, simply call the :func:`get_config`
104 While in a configuration file, to get a reference to this object, simply call the :func:`get_config`
105 function, which is available in the global namespace of the script.
105 function, which is available in the global namespace of the script.
106
106
107 Here is an example of a super simple configuration file that does nothing::
107 Here is an example of a super simple configuration file that does nothing::
108
108
109 c = get_config()
109 c = get_config()
110
110
111 Once you get a reference to the configuration object, you simply set
111 Once you get a reference to the configuration object, you simply set
112 attributes on it. All you have to know is:
112 attributes on it. All you have to know is:
113
113
114 * The name of the class to configure.
114 * The name of the class to configure.
115 * The name of the attribute.
115 * The name of the attribute.
116 * The type of each attribute.
116 * The type of each attribute.
117
117
118 The answers to these questions are provided by the various
118 The answers to these questions are provided by the various
119 :class:`~IPython.config.configurable.Configurable` subclasses that an
119 :class:`~IPython.config.configurable.Configurable` subclasses that an
120 application uses. Let's look at how this would work for a simple configurable
120 application uses. Let's look at how this would work for a simple configurable
121 subclass::
121 subclass::
122
122
123 # Sample configurable:
123 # Sample configurable:
124 from IPython.config.configurable import Configurable
124 from IPython.config.configurable import Configurable
125 from IPython.utils.traitlets import Int, Float, Unicode, Bool
125 from IPython.utils.traitlets import Int, Float, Unicode, Bool
126
126
127 class MyClass(Configurable):
127 class MyClass(Configurable):
128 name = Unicode(u'defaultname', config=True)
128 name = Unicode(u'defaultname', config=True)
129 ranking = Int(0, config=True)
129 ranking = Int(0, config=True)
130 value = Float(99.0)
130 value = Float(99.0)
131 # The rest of the class implementation would go here..
131 # The rest of the class implementation would go here..
132
132
133 In this example, we see that :class:`MyClass` has three attributes, two
133 In this example, we see that :class:`MyClass` has three attributes, two
134 of (``name``, ``ranking``) can be configured. All of the attributes
134 of which (``name``, ``ranking``) can be configured. All of the attributes
135 are given types and default values. If a :class:`MyClass` is instantiated,
135 are given types and default values. If a :class:`MyClass` is instantiated,
136 but not configured, these default values will be used. But let's see how
136 but not configured, these default values will be used. But let's see how
137 to configure this class in a configuration file::
137 to configure this class in a configuration file::
138
138
139 # Sample config file
139 # Sample config file
140 c = get_config()
140 c = get_config()
141
141
142 c.MyClass.name = 'coolname'
142 c.MyClass.name = 'coolname'
143 c.MyClass.ranking = 10
143 c.MyClass.ranking = 10
144
144
145 After this configuration file is loaded, the values set in it will override
145 After this configuration file is loaded, the values set in it will override
146 the class defaults anytime a :class:`MyClass` is created. Furthermore,
146 the class defaults anytime a :class:`MyClass` is created. Furthermore,
147 these attributes will be type checked and validated anytime they are set.
147 these attributes will be type checked and validated anytime they are set.
148 This type checking is handled by the :mod:`IPython.utils.traitlets` module,
148 This type checking is handled by the :mod:`IPython.utils.traitlets` module,
149 which provides the :class:`Unicode`, :class:`Int` and :class:`Float` types.
149 which provides the :class:`Unicode`, :class:`Int` and :class:`Float` types.
150 In addition to these traitlets, the :mod:`IPython.utils.traitlets` provides
150 In addition to these traitlets, the :mod:`IPython.utils.traitlets` provides
151 traitlets for a number of other types.
151 traitlets for a number of other types.
152
152
153 .. note::
153 .. note::
154
154
155 Underneath the hood, the :class:`Configurable` base class is a subclass of
155 Underneath the hood, the :class:`Configurable` base class is a subclass of
156 :class:`IPython.utils.traitlets.HasTraits`. The
156 :class:`IPython.utils.traitlets.HasTraits`. The
157 :mod:`IPython.utils.traitlets` module is a lightweight version of
157 :mod:`IPython.utils.traitlets` module is a lightweight version of
158 :mod:`enthought.traits`. Our implementation is a pure Python subset
158 :mod:`enthought.traits`. Our implementation is a pure Python subset
159 (mostly API compatible) of :mod:`enthought.traits` that does not have any
159 (mostly API compatible) of :mod:`enthought.traits` that does not have any
160 of the automatic GUI generation capabilities. Our plan is to achieve 100%
160 of the automatic GUI generation capabilities. Our plan is to achieve 100%
161 API compatibility to enable the actual :mod:`enthought.traits` to
161 API compatibility to enable the actual :mod:`enthought.traits` to
162 eventually be used instead. Currently, we cannot use
162 eventually be used instead. Currently, we cannot use
163 :mod:`enthought.traits` as we are committed to the core of IPython being
163 :mod:`enthought.traits` as we are committed to the core of IPython being
164 pure Python.
164 pure Python.
165
165
166 It should be very clear at this point what the naming convention is for
166 It should be very clear at this point what the naming convention is for
167 configuration attributes::
167 configuration attributes::
168
168
169 c.ClassName.attribute_name = attribute_value
169 c.ClassName.attribute_name = attribute_value
170
170
171 Here, ``ClassName`` is the name of the class whose configuration attribute you
171 Here, ``ClassName`` is the name of the class whose configuration attribute you
172 want to set, ``attribute_name`` is the name of the attribute you want to set
172 want to set, ``attribute_name`` is the name of the attribute you want to set
173 and ``attribute_value`` the the value you want it to have. The ``ClassName``
173 and ``attribute_value`` the the value you want it to have. The ``ClassName``
174 attribute of ``c`` is not the actual class, but instead is another
174 attribute of ``c`` is not the actual class, but instead is another
175 :class:`~IPython.config.loader.Config` instance.
175 :class:`~IPython.config.loader.Config` instance.
176
176
177 .. note::
177 .. note::
178
178
179 The careful reader may wonder how the ``ClassName`` (``MyClass`` in
179 The careful reader may wonder how the ``ClassName`` (``MyClass`` in
180 the above example) attribute of the configuration object ``c`` gets
180 the above example) attribute of the configuration object ``c`` gets
181 created. These attributes are created on the fly by the
181 created. These attributes are created on the fly by the
182 :class:`~IPython.config.loader.Config` instance, using a simple naming
182 :class:`~IPython.config.loader.Config` instance, using a simple naming
183 convention. Any attribute of a :class:`~IPython.config.loader.Config`
183 convention. Any attribute of a :class:`~IPython.config.loader.Config`
184 instance whose name begins with an uppercase character is assumed to be a
184 instance whose name begins with an uppercase character is assumed to be a
185 sub-configuration and a new empty :class:`~IPython.config.loader.Config`
185 sub-configuration and a new empty :class:`~IPython.config.loader.Config`
186 instance is dynamically created for that attribute. This allows deeply
186 instance is dynamically created for that attribute. This allows deeply
187 hierarchical information created easily (``c.Foo.Bar.value``) on the fly.
187 hierarchical information created easily (``c.Foo.Bar.value``) on the fly.
188
188
189 JSON configuration Files
189 JSON configuration Files
190 ~~~~~~~~~~~~~~~~~~~~~~~~
190 ~~~~~~~~~~~~~~~~~~~~~~~~
191
191
192 A JSON configuration file is simply a file that contain a
192 A JSON configuration file is simply a file that contains a
193 :class:`~IPython.config.loader.Config` dictionary serialized to JSON.
193 :class:`~IPython.config.loader.Config` dictionary serialized to JSON.
194 A JSON configuration file has the same base name as a Python configuration file,
194 A JSON configuration file has the same base name as a Python configuration file,
195 just with a .json extension.
195 but with a .json extension.
196
196
197 Configuration described in previous section could be written as follow in a
197 Configuration described in previous section could be written as follows in a
198 JSON configuration file:
198 JSON configuration file:
199
199
200 .. sourcecode:: json
200 .. sourcecode:: json
201
201
202 {
202 {
203 "version": "1.0",
203 "version": "1.0",
204 "MyClass": {
204 "MyClass": {
205 "name": "coolname",
205 "name": "coolname",
206 "ranking": 10
206 "ranking": 10
207 }
207 }
208 }
208 }
209
209
210 JSON configuration files can be more easily generated or processed by programs
210 JSON configuration files can be more easily generated or processed by programs
211 or other languages.
211 or other languages.
212
212
213
213
214 Configuration files inheritance
214 Configuration files inheritance
215 ===============================
215 ===============================
216
216
217 .. note::
217 .. note::
218
218
219 This section only apply to Python configuration files.
219 This section only apply to Python configuration files.
220
220
221 Let's say you want to have different configuration files for various purposes.
221 Let's say you want to have different configuration files for various purposes.
222 Our configuration system makes it easy for one configuration file to inherit
222 Our configuration system makes it easy for one configuration file to inherit
223 the information in another configuration file. The :func:`load_subconfig`
223 the information in another configuration file. The :func:`load_subconfig`
224 command can be used in a configuration file for this purpose. Here is a simple
224 command can be used in a configuration file for this purpose. Here is a simple
225 example that loads all of the values from the file :file:`base_config.py`::
225 example that loads all of the values from the file :file:`base_config.py`::
226
226
227 # base_config.py
227 # base_config.py
228 c = get_config()
228 c = get_config()
229 c.MyClass.name = 'coolname'
229 c.MyClass.name = 'coolname'
230 c.MyClass.ranking = 100
230 c.MyClass.ranking = 100
231
231
232 into the configuration file :file:`main_config.py`::
232 into the configuration file :file:`main_config.py`::
233
233
234 # main_config.py
234 # main_config.py
235 c = get_config()
235 c = get_config()
236
236
237 # Load everything from base_config.py
237 # Load everything from base_config.py
238 load_subconfig('base_config.py')
238 load_subconfig('base_config.py')
239
239
240 # Now override one of the values
240 # Now override one of the values
241 c.MyClass.name = 'bettername'
241 c.MyClass.name = 'bettername'
242
242
243 In a situation like this the :func:`load_subconfig` makes sure that the
243 In a situation like this the :func:`load_subconfig` makes sure that the
244 search path for sub-configuration files is inherited from that of the parent.
244 search path for sub-configuration files is inherited from that of the parent.
245 Thus, you can typically put the two in the same directory and everything will
245 Thus, you can typically put the two in the same directory and everything will
246 just work.
246 just work.
247
247
248 You can also load configuration files by profile, for instance:
248 You can also load configuration files by profile, for instance:
249
249
250 .. sourcecode:: python
250 .. sourcecode:: python
251
251
252 load_subconfig('ipython_config.py', profile='default')
252 load_subconfig('ipython_config.py', profile='default')
253
253
254 to inherit your default configuration as a starting point.
254 to inherit your default configuration as a starting point.
255
255
256
256
257 Class based configuration inheritance
257 Class based configuration inheritance
258 =====================================
258 =====================================
259
259
260 There is another aspect of configuration where inheritance comes into play.
260 There is another aspect of configuration where inheritance comes into play.
261 Sometimes, your classes will have an inheritance hierarchy that you want
261 Sometimes, your classes will have an inheritance hierarchy that you want
262 to be reflected in the configuration system. Here is a simple example::
262 to be reflected in the configuration system. Here is a simple example::
263
263
264 from IPython.config.configurable import Configurable
264 from IPython.config.configurable import Configurable
265 from IPython.utils.traitlets import Int, Float, Unicode, Bool
265 from IPython.utils.traitlets import Int, Float, Unicode, Bool
266
266
267 class Foo(Configurable):
267 class Foo(Configurable):
268 name = Unicode(u'fooname', config=True)
268 name = Unicode(u'fooname', config=True)
269 value = Float(100.0, config=True)
269 value = Float(100.0, config=True)
270
270
271 class Bar(Foo):
271 class Bar(Foo):
272 name = Unicode(u'barname', config=True)
272 name = Unicode(u'barname', config=True)
273 othervalue = Int(0, config=True)
273 othervalue = Int(0, config=True)
274
274
275 Now, we can create a configuration file to configure instances of :class:`Foo`
275 Now, we can create a configuration file to configure instances of :class:`Foo`
276 and :class:`Bar`::
276 and :class:`Bar`::
277
277
278 # config file
278 # config file
279 c = get_config()
279 c = get_config()
280
280
281 c.Foo.name = u'bestname'
281 c.Foo.name = u'bestname'
282 c.Bar.othervalue = 10
282 c.Bar.othervalue = 10
283
283
284 This class hierarchy and configuration file accomplishes the following:
284 This class hierarchy and configuration file accomplishes the following:
285
285
286 * The default value for :attr:`Foo.name` and :attr:`Bar.name` will be
286 * The default value for :attr:`Foo.name` and :attr:`Bar.name` will be
287 'bestname'. Because :class:`Bar` is a :class:`Foo` subclass it also
287 'bestname'. Because :class:`Bar` is a :class:`Foo` subclass it also
288 picks up the configuration information for :class:`Foo`.
288 picks up the configuration information for :class:`Foo`.
289 * The default value for :attr:`Foo.value` and :attr:`Bar.value` will be
289 * The default value for :attr:`Foo.value` and :attr:`Bar.value` will be
290 ``100.0``, which is the value specified as the class default.
290 ``100.0``, which is the value specified as the class default.
291 * The default value for :attr:`Bar.othervalue` will be 10 as set in the
291 * The default value for :attr:`Bar.othervalue` will be 10 as set in the
292 configuration file. Because :class:`Foo` is the parent of :class:`Bar`
292 configuration file. Because :class:`Foo` is the parent of :class:`Bar`
293 it doesn't know anything about the :attr:`othervalue` attribute.
293 it doesn't know anything about the :attr:`othervalue` attribute.
294
294
295
295
296 .. _ipython_dir:
296 .. _ipython_dir:
297
297
298 Configuration file location
298 Configuration file location
299 ===========================
299 ===========================
300
300
301 So where should you put your configuration files? IPython uses "profiles" for
301 So where should you put your configuration files? IPython uses "profiles" for
302 configuration, and by default, all profiles will be stored in the so called
302 configuration, and by default, all profiles will be stored in the so called
303 "IPython directory". The location of this directory is determined by the
303 "IPython directory". The location of this directory is determined by the
304 following algorithm:
304 following algorithm:
305
305
306 * If the ``ipython-dir`` command line flag is given, its value is used.
306 * If the ``ipython-dir`` command line flag is given, its value is used.
307
307
308 * If not, the value returned by :func:`IPython.utils.path.get_ipython_dir`
308 * If not, the value returned by :func:`IPython.utils.path.get_ipython_dir`
309 is used. This function will first look at the :envvar:`IPYTHONDIR`
309 is used. This function will first look at the :envvar:`IPYTHONDIR`
310 environment variable and then default to :file:`~/.ipython`.
310 environment variable and then default to :file:`~/.ipython`.
311 Historical support for the :envvar:`IPYTHON_DIR` environment variable will
311 Historical support for the :envvar:`IPYTHON_DIR` environment variable will
312 be removed in a future release.
312 be removed in a future release.
313
313
314 For most users, the configuration directory will be :file:`~/.ipython`.
314 For most users, the configuration directory will be :file:`~/.ipython`.
315
315
316 Previous versions of IPython on Linux would use the XDG config directory,
316 Previous versions of IPython on Linux would use the XDG config directory,
317 creating :file:`~/.config/ipython` by default. We have decided to go
317 creating :file:`~/.config/ipython` by default. We have decided to go
318 back to :file:`~/.ipython` for consistency among systems. IPython will
318 back to :file:`~/.ipython` for consistency among systems. IPython will
319 issue a warning if it finds the XDG location, and will move it to the new
319 issue a warning if it finds the XDG location, and will move it to the new
320 location if there isn't already a directory there.
320 location if there isn't already a directory there.
321
321
322 Once the location of the IPython directory has been determined, you need to know
322 Once the location of the IPython directory has been determined, you need to know
323 which profile you are using. For users with a single configuration, this will
323 which profile you are using. For users with a single configuration, this will
324 simply be 'default', and will be located in
324 simply be 'default', and will be located in
325 :file:`<IPYTHONDIR>/profile_default`.
325 :file:`<IPYTHONDIR>/profile_default`.
326
326
327 The next thing you need to know is what to call your configuration file. The
327 The next thing you need to know is what to call your configuration file. The
328 basic idea is that each application has its own default configuration filename.
328 basic idea is that each application has its own default configuration filename.
329 The default named used by the :command:`ipython` command line program is
329 The default named used by the :command:`ipython` command line program is
330 :file:`ipython_config.py`, and *all* IPython applications will use this file.
330 :file:`ipython_config.py`, and *all* IPython applications will use this file.
331 Other applications, such as the parallel :command:`ipcluster` scripts or the
331 Other applications, such as the parallel :command:`ipcluster` scripts or the
332 QtConsole will load their own config files *after* :file:`ipython_config.py`. To
332 QtConsole will load their own config files *after* :file:`ipython_config.py`. To
333 load a particular configuration file instead of the default, the name can be
333 load a particular configuration file instead of the default, the name can be
334 overridden by the ``config_file`` command line flag.
334 overridden by the ``config_file`` command line flag.
335
335
336 To generate the default configuration files, do::
336 To generate the default configuration files, do::
337
337
338 $ ipython profile create
338 $ ipython profile create
339
339
340 and you will have a default :file:`ipython_config.py` in your IPython directory
340 and you will have a default :file:`ipython_config.py` in your IPython directory
341 under :file:`profile_default`. If you want the default config files for the
341 under :file:`profile_default`. If you want the default config files for the
342 :mod:`IPython.parallel` applications, add ``--parallel`` to the end of the
342 :mod:`IPython.parallel` applications, add ``--parallel`` to the end of the
343 command-line args.
343 command-line args.
344
344
345
345
346 Locating these files
346 Locating these files
347 --------------------
347 --------------------
348
348
349 From the command-line, you can quickly locate the IPYTHONDIR or a specific
349 From the command-line, you can quickly locate the IPYTHONDIR or a specific
350 profile with:
350 profile with:
351
351
352 .. sourcecode:: bash
352 .. sourcecode:: bash
353
353
354 $ ipython locate
354 $ ipython locate
355 /home/you/.ipython
355 /home/you/.ipython
356
356
357 $ ipython locate profile foo
357 $ ipython locate profile foo
358 /home/you/.ipython/profile_foo
358 /home/you/.ipython/profile_foo
359
359
360 These map to the utility functions: :func:`IPython.utils.path.get_ipython_dir`
360 These map to the utility functions: :func:`IPython.utils.path.get_ipython_dir`
361 and :func:`IPython.utils.path.locate_profile` respectively.
361 and :func:`IPython.utils.path.locate_profile` respectively.
362
362
363
363
364 .. _profiles_dev:
364 .. _profiles_dev:
365
365
366 Profiles
366 Profiles
367 ========
367 ========
368
368
369 A profile is a directory containing configuration and runtime files, such as
369 A profile is a directory containing configuration and runtime files, such as
370 logs, connection info for the parallel apps, and your IPython command history.
370 logs, connection info for the parallel apps, and your IPython command history.
371
371
372 The idea is that users often want to maintain a set of configuration files for
372 The idea is that users often want to maintain a set of configuration files for
373 different purposes: one for doing numerical computing with NumPy and SciPy and
373 different purposes: one for doing numerical computing with NumPy and SciPy and
374 another for doing symbolic computing with SymPy. Profiles make it easy to keep a
374 another for doing symbolic computing with SymPy. Profiles make it easy to keep a
375 separate configuration files, logs, and histories for each of these purposes.
375 separate configuration files, logs, and histories for each of these purposes.
376
376
377 Let's start by showing how a profile is used:
377 Let's start by showing how a profile is used:
378
378
379 .. code-block:: bash
379 .. code-block:: bash
380
380
381 $ ipython --profile=sympy
381 $ ipython --profile=sympy
382
382
383 This tells the :command:`ipython` command line program to get its configuration
383 This tells the :command:`ipython` command line program to get its configuration
384 from the "sympy" profile. The file names for various profiles do not change. The
384 from the "sympy" profile. The file names for various profiles do not change. The
385 only difference is that profiles are named in a special way. In the case above,
385 only difference is that profiles are named in a special way. In the case above,
386 the "sympy" profile means looking for :file:`ipython_config.py` in :file:`<IPYTHONDIR>/profile_sympy`.
386 the "sympy" profile means looking for :file:`ipython_config.py` in :file:`<IPYTHONDIR>/profile_sympy`.
387
387
388 The general pattern is this: simply create a new profile with:
388 The general pattern is this: simply create a new profile with:
389
389
390 .. code-block:: bash
390 .. code-block:: bash
391
391
392 $ ipython profile create <name>
392 $ ipython profile create <name>
393
393
394 which adds a directory called ``profile_<name>`` to your IPython directory. Then
394 which adds a directory called ``profile_<name>`` to your IPython directory. Then
395 you can load this profile by adding ``--profile=<name>`` to your command line
395 you can load this profile by adding ``--profile=<name>`` to your command line
396 options. Profiles are supported by all IPython applications.
396 options. Profiles are supported by all IPython applications.
397
397
398 IPython ships with some sample profiles in :file:`IPython/config/profile`. If
398 IPython ships with some sample profiles in :file:`IPython/config/profile`. If
399 you create profiles with the name of one of our shipped profiles, these config
399 you create profiles with the name of one of our shipped profiles, these config
400 files will be copied over instead of starting with the automatically generated
400 files will be copied over instead of starting with the automatically generated
401 config files.
401 config files.
402
402
403 Security Files
403 Security Files
404 --------------
404 --------------
405
405
406 If you are using the notebook, qtconsole, or parallel code, IPython stores
406 If you are using the notebook, qtconsole, or parallel code, IPython stores
407 connection information in small JSON files in the active profile's security
407 connection information in small JSON files in the active profile's security
408 directory. This directory is made private, so only you can see the files inside. If
408 directory. This directory is made private, so only you can see the files inside. If
409 you need to move connection files around to other computers, this is where they will
409 you need to move connection files around to other computers, this is where they will
410 be. If you want your code to be able to open security files by name, we have a
410 be. If you want your code to be able to open security files by name, we have a
411 convenience function :func:`IPython.utils.path.get_security_file`, which will return
411 convenience function :func:`IPython.utils.path.get_security_file`, which will return
412 the absolute path to a security file from its filename and [optionally] profile
412 the absolute path to a security file from its filename and [optionally] profile
413 name.
413 name.
414
414
415 .. _startup_files:
415 .. _startup_files:
416
416
417 Startup Files
417 Startup Files
418 -------------
418 -------------
419
419
420 If you want some code to be run at the beginning of every IPython session with
420 If you want some code to be run at the beginning of every IPython session with
421 a particular profile, the easiest way is to add Python (``.py``) or
421 a particular profile, the easiest way is to add Python (``.py``) or
422 IPython (``.ipy``) scripts to your :file:`<profile>/startup` directory. Files
422 IPython (``.ipy``) scripts to your :file:`<profile>/startup` directory. Files
423 in this directory will always be executed as soon as the IPython shell is
423 in this directory will always be executed as soon as the IPython shell is
424 constructed, and before any other code or scripts you have specified. If you
424 constructed, and before any other code or scripts you have specified. If you
425 have multiple files in the startup directory, they will be run in
425 have multiple files in the startup directory, they will be run in
426 lexicographical order, so you can control the ordering by adding a '00-'
426 lexicographical order, so you can control the ordering by adding a '00-'
427 prefix.
427 prefix.
428
428
429
429
430 .. _commandline:
430 .. _commandline:
431
431
432 Command-line arguments
432 Command-line arguments
433 ======================
433 ======================
434
434
435 IPython exposes *all* configurable options on the command-line. The command-line
435 IPython exposes *all* configurable options on the command-line. The command-line
436 arguments are generated from the Configurable traits of the classes associated
436 arguments are generated from the Configurable traits of the classes associated
437 with a given Application. Configuring IPython from the command-line may look
437 with a given Application. Configuring IPython from the command-line may look
438 very similar to an IPython config file
438 very similar to an IPython config file
439
439
440 IPython applications use a parser called
440 IPython applications use a parser called
441 :class:`~IPython.config.loader.KeyValueLoader` to load values into a Config
441 :class:`~IPython.config.loader.KeyValueLoader` to load values into a Config
442 object. Values are assigned in much the same way as in a config file:
442 object. Values are assigned in much the same way as in a config file:
443
443
444 .. code-block:: bash
444 .. code-block:: bash
445
445
446 $ ipython --InteractiveShell.use_readline=False --BaseIPythonApplication.profile='myprofile'
446 $ ipython --InteractiveShell.use_readline=False --BaseIPythonApplication.profile='myprofile'
447
447
448 Is the same as adding:
448 Is the same as adding:
449
449
450 .. sourcecode:: python
450 .. sourcecode:: python
451
451
452 c.InteractiveShell.use_readline=False
452 c.InteractiveShell.use_readline=False
453 c.BaseIPythonApplication.profile='myprofile'
453 c.BaseIPythonApplication.profile='myprofile'
454
454
455 to your config file. Key/Value arguments *always* take a value, separated by '='
455 to your config file. Key/Value arguments *always* take a value, separated by '='
456 and no spaces.
456 and no spaces.
457
457
458 Common Arguments
458 Common Arguments
459 ----------------
459 ----------------
460
460
461 Since the strictness and verbosity of the KVLoader above are not ideal for everyday
461 Since the strictness and verbosity of the KVLoader above are not ideal for everyday
462 use, common arguments can be specified as flags_ or aliases_.
462 use, common arguments can be specified as flags_ or aliases_.
463
463
464 Flags and Aliases are handled by :mod:`argparse` instead, allowing for more flexible
464 Flags and Aliases are handled by :mod:`argparse` instead, allowing for more flexible
465 parsing. In general, flags and aliases are prefixed by ``--``, except for those
465 parsing. In general, flags and aliases are prefixed by ``--``, except for those
466 that are single characters, in which case they can be specified with a single ``-``, e.g.:
466 that are single characters, in which case they can be specified with a single ``-``, e.g.:
467
467
468 .. code-block:: bash
468 .. code-block:: bash
469
469
470 $ ipython -i -c "import numpy; x=numpy.linspace(0,1)" --profile testing --colors=lightbg
470 $ ipython -i -c "import numpy; x=numpy.linspace(0,1)" --profile testing --colors=lightbg
471
471
472 Aliases
472 Aliases
473 *******
473 *******
474
474
475 For convenience, applications have a mapping of commonly used traits, so you don't have
475 For convenience, applications have a mapping of commonly used traits, so you don't have
476 to specify the whole class name:
476 to specify the whole class name:
477
477
478 .. code-block:: bash
478 .. code-block:: bash
479
479
480 $ ipython --profile myprofile
480 $ ipython --profile myprofile
481 # and
481 # and
482 $ ipython --profile='myprofile'
482 $ ipython --profile='myprofile'
483 # are equivalent to
483 # are equivalent to
484 $ ipython --BaseIPythonApplication.profile='myprofile'
484 $ ipython --BaseIPythonApplication.profile='myprofile'
485
485
486 Flags
486 Flags
487 *****
487 *****
488
488
489 Applications can also be passed **flags**. Flags are options that take no
489 Applications can also be passed **flags**. Flags are options that take no
490 arguments. They are simply wrappers for
490 arguments. They are simply wrappers for
491 setting one or more configurables with predefined values, often True/False.
491 setting one or more configurables with predefined values, often True/False.
492
492
493 For instance:
493 For instance:
494
494
495 .. code-block:: bash
495 .. code-block:: bash
496
496
497 $ ipcontroller --debug
497 $ ipcontroller --debug
498 # is equivalent to
498 # is equivalent to
499 $ ipcontroller --Application.log_level=DEBUG
499 $ ipcontroller --Application.log_level=DEBUG
500 # and
500 # and
501 $ ipython --matploitlib
501 $ ipython --matploitlib
502 # is equivalent to
502 # is equivalent to
503 $ ipython --matplotlib auto
503 $ ipython --matplotlib auto
504 # or
504 # or
505 $ ipython --no-banner
505 $ ipython --no-banner
506 # is equivalent to
506 # is equivalent to
507 $ ipython --TerminalIPythonApp.display_banner=False
507 $ ipython --TerminalIPythonApp.display_banner=False
508
508
509 Subcommands
509 Subcommands
510 -----------
510 -----------
511
511
512
512
513 Some IPython applications have **subcommands**. Subcommands are modeled after
513 Some IPython applications have **subcommands**. Subcommands are modeled after
514 :command:`git`, and are called with the form :command:`command subcommand
514 :command:`git`, and are called with the form :command:`command subcommand
515 [...args]`. Currently, the QtConsole is a subcommand of terminal IPython:
515 [...args]`. Currently, the QtConsole is a subcommand of terminal IPython:
516
516
517 .. code-block:: bash
517 .. code-block:: bash
518
518
519 $ ipython qtconsole --profile myprofile
519 $ ipython qtconsole --profile myprofile
520
520
521 and :command:`ipcluster` is simply a wrapper for its various subcommands (start,
521 and :command:`ipcluster` is simply a wrapper for its various subcommands (start,
522 stop, engines).
522 stop, engines).
523
523
524 .. code-block:: bash
524 .. code-block:: bash
525
525
526 $ ipcluster start --profile=myprofile -n 4
526 $ ipcluster start --profile=myprofile -n 4
527
527
528
528
529 To see a list of the available aliases, flags, and subcommands for an IPython application, simply pass ``-h`` or ``--help``. And to see the full list of configurable options (*very* long), pass ``--help-all``.
529 To see a list of the available aliases, flags, and subcommands for an IPython application, simply pass ``-h`` or ``--help``. And to see the full list of configurable options (*very* long), pass ``--help-all``.
530
530
531
531
532 Design requirements
532 Design requirements
533 ===================
533 ===================
534
534
535 Here are the main requirements we wanted our configuration system to have:
535 Here are the main requirements we wanted our configuration system to have:
536
536
537 * Support for hierarchical configuration information.
537 * Support for hierarchical configuration information.
538
538
539 * Full integration with command line option parsers. Often, you want to read
539 * Full integration with command line option parsers. Often, you want to read
540 a configuration file, but then override some of the values with command line
540 a configuration file, but then override some of the values with command line
541 options. Our configuration system automates this process and allows each
541 options. Our configuration system automates this process and allows each
542 command line option to be linked to a particular attribute in the
542 command line option to be linked to a particular attribute in the
543 configuration hierarchy that it will override.
543 configuration hierarchy that it will override.
544
544
545 * Configuration files that are themselves valid Python code. This accomplishes
545 * Configuration files that are themselves valid Python code. This accomplishes
546 many things. First, it becomes possible to put logic in your configuration
546 many things. First, it becomes possible to put logic in your configuration
547 files that sets attributes based on your operating system, network setup,
547 files that sets attributes based on your operating system, network setup,
548 Python version, etc. Second, Python has a super simple syntax for accessing
548 Python version, etc. Second, Python has a super simple syntax for accessing
549 hierarchical data structures, namely regular attribute access
549 hierarchical data structures, namely regular attribute access
550 (``Foo.Bar.Bam.name``). Third, using Python makes it easy for users to
550 (``Foo.Bar.Bam.name``). Third, using Python makes it easy for users to
551 import configuration attributes from one configuration file to another.
551 import configuration attributes from one configuration file to another.
552 Fourth, even though Python is dynamically typed, it does have types that can
552 Fourth, even though Python is dynamically typed, it does have types that can
553 be checked at runtime. Thus, a ``1`` in a config file is the integer '1',
553 be checked at runtime. Thus, a ``1`` in a config file is the integer '1',
554 while a ``'1'`` is a string.
554 while a ``'1'`` is a string.
555
555
556 * A fully automated method for getting the configuration information to the
556 * A fully automated method for getting the configuration information to the
557 classes that need it at runtime. Writing code that walks a configuration
557 classes that need it at runtime. Writing code that walks a configuration
558 hierarchy to extract a particular attribute is painful. When you have
558 hierarchy to extract a particular attribute is painful. When you have
559 complex configuration information with hundreds of attributes, this makes
559 complex configuration information with hundreds of attributes, this makes
560 you want to cry.
560 you want to cry.
561
561
562 * Type checking and validation that doesn't require the entire configuration
562 * Type checking and validation that doesn't require the entire configuration
563 hierarchy to be specified statically before runtime. Python is a very
563 hierarchy to be specified statically before runtime. Python is a very
564 dynamic language and you don't always know everything that needs to be
564 dynamic language and you don't always know everything that needs to be
565 configured when a program starts.
565 configured when a program starts.
566
566
General Comments 0
You need to be logged in to leave comments. Login now