##// END OF EJS Templates
Simplify options handling code by using argparse argument_default....
Fernando Perez -
Show More
@@ -1,373 +1,376 b''
1 # coding: utf-8
1 # coding: utf-8
2 """A simple configuration system.
2 """A simple configuration system.
3
3
4 Authors
4 Authors
5 -------
5 -------
6 * Brian Granger
6 * Brian Granger
7 * Fernando Perez
7 * Fernando Perez
8 """
8 """
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Copyright (C) 2008-2009 The IPython Development Team
11 # Copyright (C) 2008-2009 The IPython Development Team
12 #
12 #
13 # Distributed under the terms of the BSD License. The full license is in
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
14 # the file COPYING, distributed as part of this software.
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Imports
18 # Imports
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 import __builtin__
21 import __builtin__
22 import os
22 import os
23 import sys
23 import sys
24
24
25 from IPython.external import argparse
25 from IPython.external import argparse
26 from IPython.utils.genutils import filefind
26 from IPython.utils.genutils import filefind
27
27
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29 # Exceptions
29 # Exceptions
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31
31
32
32
33 class ConfigError(Exception):
33 class ConfigError(Exception):
34 pass
34 pass
35
35
36
36
37 class ConfigLoaderError(ConfigError):
37 class ConfigLoaderError(ConfigError):
38 pass
38 pass
39
39
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41 # Argparse fix
41 # Argparse fix
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43 # Unfortunately argparse by default prints help messages to stderr instead of
43 # Unfortunately argparse by default prints help messages to stderr instead of
44 # stdout. This makes it annoying to capture long help screens at the command
44 # stdout. This makes it annoying to capture long help screens at the command
45 # line, since one must know how to pipe stderr, which many users don't know how
45 # line, since one must know how to pipe stderr, which many users don't know how
46 # to do. So we override the print_help method with one that defaults to
46 # to do. So we override the print_help method with one that defaults to
47 # stdout and use our class instead.
47 # stdout and use our class instead.
48
48
49 class ArgumentParser(argparse.ArgumentParser):
49 class ArgumentParser(argparse.ArgumentParser):
50 """Simple argparse subclass that prints help to stdout by default."""
50 """Simple argparse subclass that prints help to stdout by default."""
51
51
52 def print_help(self, file=None):
52 def print_help(self, file=None):
53 if file is None:
53 if file is None:
54 file = sys.stdout
54 file = sys.stdout
55 return super(ArgumentParser, self).print_help(file)
55 return super(ArgumentParser, self).print_help(file)
56
56
57 print_help.__doc__ = argparse.ArgumentParser.print_help.__doc__
57 print_help.__doc__ = argparse.ArgumentParser.print_help.__doc__
58
58
59 #-----------------------------------------------------------------------------
59 #-----------------------------------------------------------------------------
60 # Config class for holding config information
60 # Config class for holding config information
61 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
62
62
63
63
64 class Config(dict):
64 class Config(dict):
65 """An attribute based dict that can do smart merges."""
65 """An attribute based dict that can do smart merges."""
66
66
67 def __init__(self, *args, **kwds):
67 def __init__(self, *args, **kwds):
68 dict.__init__(self, *args, **kwds)
68 dict.__init__(self, *args, **kwds)
69 # This sets self.__dict__ = self, but it has to be done this way
69 # This sets self.__dict__ = self, but it has to be done this way
70 # because we are also overriding __setattr__.
70 # because we are also overriding __setattr__.
71 dict.__setattr__(self, '__dict__', self)
71 dict.__setattr__(self, '__dict__', self)
72
72
73 def _merge(self, other):
73 def _merge(self, other):
74 to_update = {}
74 to_update = {}
75 for k, v in other.items():
75 for k, v in other.items():
76 if not self.has_key(k):
76 if not self.has_key(k):
77 to_update[k] = v
77 to_update[k] = v
78 else: # I have this key
78 else: # I have this key
79 if isinstance(v, Config):
79 if isinstance(v, Config):
80 # Recursively merge common sub Configs
80 # Recursively merge common sub Configs
81 self[k]._merge(v)
81 self[k]._merge(v)
82 else:
82 else:
83 # Plain updates for non-Configs
83 # Plain updates for non-Configs
84 to_update[k] = v
84 to_update[k] = v
85
85
86 self.update(to_update)
86 self.update(to_update)
87
87
88 def _is_section_key(self, key):
88 def _is_section_key(self, key):
89 if key[0].upper()==key[0] and not key.startswith('_'):
89 if key[0].upper()==key[0] and not key.startswith('_'):
90 return True
90 return True
91 else:
91 else:
92 return False
92 return False
93
93
94 def has_key(self, key):
94 def has_key(self, key):
95 if self._is_section_key(key):
95 if self._is_section_key(key):
96 return True
96 return True
97 else:
97 else:
98 return dict.has_key(self, key)
98 return dict.has_key(self, key)
99
99
100 def _has_section(self, key):
100 def _has_section(self, key):
101 if self._is_section_key(key):
101 if self._is_section_key(key):
102 if dict.has_key(self, key):
102 if dict.has_key(self, key):
103 return True
103 return True
104 return False
104 return False
105
105
106 def copy(self):
106 def copy(self):
107 return type(self)(dict.copy(self))
107 return type(self)(dict.copy(self))
108
108
109 def __copy__(self):
109 def __copy__(self):
110 return self.copy()
110 return self.copy()
111
111
112 def __deepcopy__(self, memo):
112 def __deepcopy__(self, memo):
113 import copy
113 import copy
114 return type(self)(copy.deepcopy(self.items()))
114 return type(self)(copy.deepcopy(self.items()))
115
115
116 def __getitem__(self, key):
116 def __getitem__(self, key):
117 # Because we use this for an exec namespace, we need to delegate
117 # Because we use this for an exec namespace, we need to delegate
118 # the lookup of names in __builtin__ to itself. This means
118 # the lookup of names in __builtin__ to itself. This means
119 # that you can't have section or attribute names that are
119 # that you can't have section or attribute names that are
120 # builtins.
120 # builtins.
121 try:
121 try:
122 return getattr(__builtin__, key)
122 return getattr(__builtin__, key)
123 except AttributeError:
123 except AttributeError:
124 pass
124 pass
125 if self._is_section_key(key):
125 if self._is_section_key(key):
126 try:
126 try:
127 return dict.__getitem__(self, key)
127 return dict.__getitem__(self, key)
128 except KeyError:
128 except KeyError:
129 c = Config()
129 c = Config()
130 dict.__setitem__(self, key, c)
130 dict.__setitem__(self, key, c)
131 return c
131 return c
132 else:
132 else:
133 return dict.__getitem__(self, key)
133 return dict.__getitem__(self, key)
134
134
135 def __setitem__(self, key, value):
135 def __setitem__(self, key, value):
136 # Don't allow names in __builtin__ to be modified.
136 # Don't allow names in __builtin__ to be modified.
137 if hasattr(__builtin__, key):
137 if hasattr(__builtin__, key):
138 raise ConfigError('Config variable names cannot have the same name '
138 raise ConfigError('Config variable names cannot have the same name '
139 'as a Python builtin: %s' % key)
139 'as a Python builtin: %s' % key)
140 if self._is_section_key(key):
140 if self._is_section_key(key):
141 if not isinstance(value, Config):
141 if not isinstance(value, Config):
142 raise ValueError('values whose keys begin with an uppercase '
142 raise ValueError('values whose keys begin with an uppercase '
143 'char must be Config instances: %r, %r' % (key, value))
143 'char must be Config instances: %r, %r' % (key, value))
144 else:
144 else:
145 dict.__setitem__(self, key, value)
145 dict.__setitem__(self, key, value)
146
146
147 def __getattr__(self, key):
147 def __getattr__(self, key):
148 try:
148 try:
149 return self.__getitem__(key)
149 return self.__getitem__(key)
150 except KeyError, e:
150 except KeyError, e:
151 raise AttributeError(e)
151 raise AttributeError(e)
152
152
153 def __setattr__(self, key, value):
153 def __setattr__(self, key, value):
154 try:
154 try:
155 self.__setitem__(key, value)
155 self.__setitem__(key, value)
156 except KeyError, e:
156 except KeyError, e:
157 raise AttributeError(e)
157 raise AttributeError(e)
158
158
159 def __delattr__(self, key):
159 def __delattr__(self, key):
160 try:
160 try:
161 dict.__delitem__(self, key)
161 dict.__delitem__(self, key)
162 except KeyError, e:
162 except KeyError, e:
163 raise AttributeError(e)
163 raise AttributeError(e)
164
164
165
165
166 #-----------------------------------------------------------------------------
166 #-----------------------------------------------------------------------------
167 # Config loading classes
167 # Config loading classes
168 #-----------------------------------------------------------------------------
168 #-----------------------------------------------------------------------------
169
169
170
170
171 class ConfigLoader(object):
171 class ConfigLoader(object):
172 """A object for loading configurations from just about anywhere.
172 """A object for loading configurations from just about anywhere.
173
173
174 The resulting configuration is packaged as a :class:`Struct`.
174 The resulting configuration is packaged as a :class:`Struct`.
175
175
176 Notes
176 Notes
177 -----
177 -----
178 A :class:`ConfigLoader` does one thing: load a config from a source
178 A :class:`ConfigLoader` does one thing: load a config from a source
179 (file, command line arguments) and returns the data as a :class:`Struct`.
179 (file, command line arguments) and returns the data as a :class:`Struct`.
180 There are lots of things that :class:`ConfigLoader` does not do. It does
180 There are lots of things that :class:`ConfigLoader` does not do. It does
181 not implement complex logic for finding config files. It does not handle
181 not implement complex logic for finding config files. It does not handle
182 default values or merge multiple configs. These things need to be
182 default values or merge multiple configs. These things need to be
183 handled elsewhere.
183 handled elsewhere.
184 """
184 """
185
185
186 def __init__(self):
186 def __init__(self):
187 """A base class for config loaders.
187 """A base class for config loaders.
188
188
189 Examples
189 Examples
190 --------
190 --------
191
191
192 >>> cl = ConfigLoader()
192 >>> cl = ConfigLoader()
193 >>> config = cl.load_config()
193 >>> config = cl.load_config()
194 >>> config
194 >>> config
195 {}
195 {}
196 """
196 """
197 self.clear()
197 self.clear()
198
198
199 def clear(self):
199 def clear(self):
200 self.config = Config()
200 self.config = Config()
201
201
202 def load_config(self):
202 def load_config(self):
203 """Load a config from somewhere, return a Struct.
203 """Load a config from somewhere, return a Struct.
204
204
205 Usually, this will cause self.config to be set and then returned.
205 Usually, this will cause self.config to be set and then returned.
206 """
206 """
207 return self.config
207 return self.config
208
208
209
209
210 class FileConfigLoader(ConfigLoader):
210 class FileConfigLoader(ConfigLoader):
211 """A base class for file based configurations.
211 """A base class for file based configurations.
212
212
213 As we add more file based config loaders, the common logic should go
213 As we add more file based config loaders, the common logic should go
214 here.
214 here.
215 """
215 """
216 pass
216 pass
217
217
218
218
219 class PyFileConfigLoader(FileConfigLoader):
219 class PyFileConfigLoader(FileConfigLoader):
220 """A config loader for pure python files.
220 """A config loader for pure python files.
221
221
222 This calls execfile on a plain python file and looks for attributes
222 This calls execfile on a plain python file and looks for attributes
223 that are all caps. These attribute are added to the config Struct.
223 that are all caps. These attribute are added to the config Struct.
224 """
224 """
225
225
226 def __init__(self, filename, path=None):
226 def __init__(self, filename, path=None):
227 """Build a config loader for a filename and path.
227 """Build a config loader for a filename and path.
228
228
229 Parameters
229 Parameters
230 ----------
230 ----------
231 filename : str
231 filename : str
232 The file name of the config file.
232 The file name of the config file.
233 path : str, list, tuple
233 path : str, list, tuple
234 The path to search for the config file on, or a sequence of
234 The path to search for the config file on, or a sequence of
235 paths to try in order.
235 paths to try in order.
236 """
236 """
237 super(PyFileConfigLoader, self).__init__()
237 super(PyFileConfigLoader, self).__init__()
238 self.filename = filename
238 self.filename = filename
239 self.path = path
239 self.path = path
240 self.full_filename = ''
240 self.full_filename = ''
241 self.data = None
241 self.data = None
242
242
243 def load_config(self):
243 def load_config(self):
244 """Load the config from a file and return it as a Struct."""
244 """Load the config from a file and return it as a Struct."""
245 self._find_file()
245 self._find_file()
246 self._read_file_as_dict()
246 self._read_file_as_dict()
247 self._convert_to_config()
247 self._convert_to_config()
248 return self.config
248 return self.config
249
249
250 def _find_file(self):
250 def _find_file(self):
251 """Try to find the file by searching the paths."""
251 """Try to find the file by searching the paths."""
252 self.full_filename = filefind(self.filename, self.path)
252 self.full_filename = filefind(self.filename, self.path)
253
253
254 def _read_file_as_dict(self):
254 def _read_file_as_dict(self):
255 """Load the config file into self.config, with recursive loading."""
255 """Load the config file into self.config, with recursive loading."""
256 # This closure is made available in the namespace that is used
256 # This closure is made available in the namespace that is used
257 # to exec the config file. This allows users to call
257 # to exec the config file. This allows users to call
258 # load_subconfig('myconfig.py') to load config files recursively.
258 # load_subconfig('myconfig.py') to load config files recursively.
259 # It needs to be a closure because it has references to self.path
259 # It needs to be a closure because it has references to self.path
260 # and self.config. The sub-config is loaded with the same path
260 # and self.config. The sub-config is loaded with the same path
261 # as the parent, but it uses an empty config which is then merged
261 # as the parent, but it uses an empty config which is then merged
262 # with the parents.
262 # with the parents.
263 def load_subconfig(fname):
263 def load_subconfig(fname):
264 loader = PyFileConfigLoader(fname, self.path)
264 loader = PyFileConfigLoader(fname, self.path)
265 try:
265 try:
266 sub_config = loader.load_config()
266 sub_config = loader.load_config()
267 except IOError:
267 except IOError:
268 # Pass silently if the sub config is not there. This happens
268 # Pass silently if the sub config is not there. This happens
269 # when a user us using a profile, but not the default config.
269 # when a user us using a profile, but not the default config.
270 pass
270 pass
271 else:
271 else:
272 self.config._merge(sub_config)
272 self.config._merge(sub_config)
273
273
274 # Again, this needs to be a closure and should be used in config
274 # Again, this needs to be a closure and should be used in config
275 # files to get the config being loaded.
275 # files to get the config being loaded.
276 def get_config():
276 def get_config():
277 return self.config
277 return self.config
278
278
279 namespace = dict(load_subconfig=load_subconfig, get_config=get_config)
279 namespace = dict(load_subconfig=load_subconfig, get_config=get_config)
280 execfile(self.full_filename, namespace)
280 execfile(self.full_filename, namespace)
281
281
282 def _convert_to_config(self):
282 def _convert_to_config(self):
283 if self.data is None:
283 if self.data is None:
284 ConfigLoaderError('self.data does not exist')
284 ConfigLoaderError('self.data does not exist')
285
285
286
286
287 class CommandLineConfigLoader(ConfigLoader):
287 class CommandLineConfigLoader(ConfigLoader):
288 """A config loader for command line arguments.
288 """A config loader for command line arguments.
289
289
290 As we add more command line based loaders, the common logic should go
290 As we add more command line based loaders, the common logic should go
291 here.
291 here.
292 """
292 """
293
293
294
294
295 class __NoConfigDefault(object): pass
295 class __NoConfigDefault(object): pass
296 NoConfigDefault = __NoConfigDefault()
296 NoConfigDefault = __NoConfigDefault()
297
297
298
298
299 class ArgParseConfigLoader(CommandLineConfigLoader):
299 class ArgParseConfigLoader(CommandLineConfigLoader):
300 #: Global default for arguments (see argparse docs for details)
301 argument_default = NoConfigDefault
300
302
301 def __init__(self, argv=None, arguments=(), *args, **kw):
303 def __init__(self, argv=None, arguments=(), *args, **kw):
302 """Create a config loader for use with argparse.
304 """Create a config loader for use with argparse.
303
305
304 With the exception of ``argv`` and ``arguments``, other args and kwargs
306 With the exception of ``argv`` and ``arguments``, other args and kwargs
305 arguments here are passed onto the constructor of
307 arguments here are passed onto the constructor of
306 :class:`argparse.ArgumentParser`.
308 :class:`argparse.ArgumentParser`.
307
309
308 Parameters
310 Parameters
309 ----------
311 ----------
310
312
311 argv : optional, list
313 argv : optional, list
312 If given, used to read command-line arguments from, otherwise
314 If given, used to read command-line arguments from, otherwise
313 sys.argv[1:] is used.
315 sys.argv[1:] is used.
314
316
315 arguments : optional, tuple
317 arguments : optional, tuple
316 Description of valid command-line arguments, to be called in sequence
318 Description of valid command-line arguments, to be called in sequence
317 with parser.add_argument() to configure the parser.
319 with parser.add_argument() to configure the parser.
318 """
320 """
319 super(CommandLineConfigLoader, self).__init__()
321 super(CommandLineConfigLoader, self).__init__()
320 if argv == None:
322 if argv == None:
321 argv = sys.argv[1:]
323 argv = sys.argv[1:]
322 self.argv = argv
324 self.argv = argv
323 self.arguments = arguments
325 self.arguments = arguments
324 self.args = args
326 self.args = args
325 self.kw = kw
327 kwargs = dict(argument_default=self.argument_default)
328 kwargs.update(kw)
329 self.kw = kwargs
326
330
327 def load_config(self, args=None):
331 def load_config(self, args=None):
328 """Parse command line arguments and return as a Struct.
332 """Parse command line arguments and return as a Struct.
329
333
330 Parameters
334 Parameters
331 ----------
335 ----------
332
336
333 args : optional, list
337 args : optional, list
334 If given, a list with the structure of sys.argv[1:] to parse arguments
338 If given, a list with the structure of sys.argv[1:] to parse arguments
335 from. If not given, the instance's self.argv attribute (given at
339 from. If not given, the instance's self.argv attribute (given at
336 construction time) is used."""
340 construction time) is used."""
337
341
338 if args is None:
342 if args is None:
339 args = self.argv
343 args = self.argv
340 self._create_parser()
344 self._create_parser()
341 self._parse_args(args)
345 self._parse_args(args)
342 self._convert_to_config()
346 self._convert_to_config()
343 return self.config
347 return self.config
344
348
345 def get_extra_args(self):
349 def get_extra_args(self):
346 if hasattr(self, 'extra_args'):
350 if hasattr(self, 'extra_args'):
347 return self.extra_args
351 return self.extra_args
348 else:
352 else:
349 return []
353 return []
350
354
351 def _create_parser(self):
355 def _create_parser(self):
352 self.parser = ArgumentParser(*self.args, **self.kw)
356 self.parser = ArgumentParser(*self.args, **self.kw)
353 self._add_arguments()
357 self._add_arguments()
354 self._add_other_arguments()
358 self._add_other_arguments()
355
359
356 def _add_other_arguments(self):
357 pass
358
359 def _add_arguments(self):
360 def _add_arguments(self):
360 for argument in self.arguments:
361 for argument in self.arguments:
361 argument[1].setdefault('default', NoConfigDefault)
362 self.parser.add_argument(*argument[0],**argument[1])
362 self.parser.add_argument(*argument[0],**argument[1])
363
363
364 def _add_other_arguments(self):
365 pass
366
364 def _parse_args(self, args):
367 def _parse_args(self, args):
365 """self.parser->self.parsed_data"""
368 """self.parser->self.parsed_data"""
366 self.parsed_data, self.extra_args = self.parser.parse_known_args(args)
369 self.parsed_data, self.extra_args = self.parser.parse_known_args(args)
367
370
368 def _convert_to_config(self):
371 def _convert_to_config(self):
369 """self.parsed_data->self.config"""
372 """self.parsed_data->self.config"""
370 for k, v in vars(self.parsed_data).items():
373 for k, v in vars(self.parsed_data).items():
371 if v is not NoConfigDefault:
374 if v is not NoConfigDefault:
372 exec_str = 'self.config.' + k + '= v'
375 exec_str = 'self.config.' + k + '= v'
373 exec exec_str in locals(), globals()
376 exec exec_str in locals(), globals()
@@ -1,422 +1,417 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 An application for IPython.
4 An application for IPython.
5
5
6 All top-level applications should use the classes in this module for
6 All top-level applications should use the classes in this module for
7 handling configuration and creating componenets.
7 handling configuration and creating componenets.
8
8
9 The job of an :class:`Application` is to create the master configuration
9 The job of an :class:`Application` is to create the master configuration
10 object and then create the components, passing the config to them.
10 object and then create the components, passing the config to them.
11
11
12 Authors:
12 Authors:
13
13
14 * Brian Granger
14 * Brian Granger
15 * Fernando Perez
15 * Fernando Perez
16
16
17 Notes
17 Notes
18 -----
18 -----
19 """
19 """
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Copyright (C) 2008-2009 The IPython Development Team
22 # Copyright (C) 2008-2009 The IPython Development Team
23 #
23 #
24 # Distributed under the terms of the BSD License. The full license is in
24 # Distributed under the terms of the BSD License. The full license is in
25 # the file COPYING, distributed as part of this software.
25 # the file COPYING, distributed as part of this software.
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27
27
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29 # Imports
29 # Imports
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31
31
32 import logging
32 import logging
33 import os
33 import os
34 import sys
34 import sys
35
35
36 from IPython.core import release, crashhandler
36 from IPython.core import release, crashhandler
37 from IPython.utils.genutils import get_ipython_dir, get_ipython_package_dir
37 from IPython.utils.genutils import get_ipython_dir, get_ipython_package_dir
38 from IPython.config.loader import (
38 from IPython.config.loader import (
39 PyFileConfigLoader,
39 PyFileConfigLoader,
40 ArgParseConfigLoader,
40 ArgParseConfigLoader,
41 Config,
41 Config,
42 NoConfigDefault
43 )
42 )
44
43
45 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
46 # Classes and functions
45 # Classes and functions
47 #-----------------------------------------------------------------------------
46 #-----------------------------------------------------------------------------
48
47
49 class ApplicationError(Exception):
48 class ApplicationError(Exception):
50 pass
49 pass
51
50
52
51
53 app_cl_args = (
52 app_cl_args = (
54 (('--ipython-dir', ), dict(
53 (('--ipython-dir', ), dict(
55 dest='Global.ipython_dir',type=unicode,
54 dest='Global.ipython_dir',type=unicode,
56 help=
55 help=
57 """Set to override default location of the IPython directory
56 """Set to override default location of the IPython directory
58 IPYTHON_DIR, stored as Global.ipython_dir. This can also be specified
57 IPYTHON_DIR, stored as Global.ipython_dir. This can also be specified
59 through the environment variable IPYTHON_DIR.""",
58 through the environment variable IPYTHON_DIR.""",
60 default=NoConfigDefault,
61 metavar='Global.ipython_dir') ),
59 metavar='Global.ipython_dir') ),
62 (('-p', '--profile',), dict(
60 (('-p', '--profile',), dict(
63 dest='Global.profile',type=unicode,
61 dest='Global.profile',type=unicode,
64 help=
62 help=
65 """The string name of the ipython profile to be used. Assume that your
63 """The string name of the ipython profile to be used. Assume that your
66 config file is ipython_config-<name>.py (looks in current dir first,
64 config file is ipython_config-<name>.py (looks in current dir first,
67 then in IPYTHON_DIR). This is a quick way to keep and load multiple
65 then in IPYTHON_DIR). This is a quick way to keep and load multiple
68 config files for different tasks, especially if include your basic one
66 config files for different tasks, especially if include your basic one
69 in your more specialized ones. You can keep a basic
67 in your more specialized ones. You can keep a basic
70 IPYTHON_DIR/ipython_config.py file and then have other 'profiles' which
68 IPYTHON_DIR/ipython_config.py file and then have other 'profiles' which
71 include this one and load extra things for particular tasks.""",
69 include this one and load extra things for particular tasks.""",
72 default=NoConfigDefault,
73 metavar='Global.profile') ),
70 metavar='Global.profile') ),
74 (('--log-level',), dict(
71 (('--log-level',), dict(
75 dest="Global.log_level",type=int,
72 dest="Global.log_level",type=int,
76 help='Set the log level (0,10,20,30,40,50). Default is 30.',
73 help='Set the log level (0,10,20,30,40,50). Default is 30.',
77 default=NoConfigDefault,
78 metavar='Global.log_level')),
74 metavar='Global.log_level')),
79 (('--config-file',), dict(
75 (('--config-file',), dict(
80 dest='Global.config_file',type=unicode,
76 dest='Global.config_file',type=unicode,
81 help=
77 help=
82 """Set the config file name to override default. Normally IPython
78 """Set the config file name to override default. Normally IPython
83 loads ipython_config.py (from current directory) or
79 loads ipython_config.py (from current directory) or
84 IPYTHON_DIR/ipython_config.py. If the loading of your config file
80 IPYTHON_DIR/ipython_config.py. If the loading of your config file
85 fails, IPython starts with a bare bones configuration (no modules
81 fails, IPython starts with a bare bones configuration (no modules
86 loaded at all).""",
82 loaded at all).""",
87 default=NoConfigDefault,
88 metavar='Global.config_file')),
83 metavar='Global.config_file')),
89 )
84 )
90
85
91 class Application(object):
86 class Application(object):
92 """Load a config, construct components and set them running."""
87 """Load a config, construct components and set them running."""
93
88
94 name = u'ipython'
89 name = u'ipython'
95 description = 'IPython: an enhanced interactive Python shell.'
90 description = 'IPython: an enhanced interactive Python shell.'
96 #: usage message printed by argparse. If None, auto-generate
91 #: usage message printed by argparse. If None, auto-generate
97 usage = None
92 usage = None
98 config_file_name = u'ipython_config.py'
93 config_file_name = u'ipython_config.py'
99 # Track the default and actual separately because some messages are
94 # Track the default and actual separately because some messages are
100 # only printed if we aren't using the default.
95 # only printed if we aren't using the default.
101 default_config_file_name = config_file_name
96 default_config_file_name = config_file_name
102 default_log_level = logging.WARN
97 default_log_level = logging.WARN
103 # Set by --profile option
98 # Set by --profile option
104 profile_name = None
99 profile_name = None
105 #: User's ipython directory, typically ~/.ipython/
100 #: User's ipython directory, typically ~/.ipython/
106 ipython_dir = None
101 ipython_dir = None
107 #: A reference to the argv to be used (typically ends up being sys.argv[1:])
102 #: A reference to the argv to be used (typically ends up being sys.argv[1:])
108 argv = None
103 argv = None
109 #: Default command line arguments. Subclasses should create a new tuple
104 #: Default command line arguments. Subclasses should create a new tuple
110 #: that *includes* these.
105 #: that *includes* these.
111 cl_arguments = app_cl_args
106 cl_arguments = app_cl_args
112
107
113 # Private attributes
108 # Private attributes
114 _exiting = False
109 _exiting = False
115 _initialized = False
110 _initialized = False
116
111
117 # Class choices for things that will be instantiated at runtime.
112 # Class choices for things that will be instantiated at runtime.
118 _CrashHandler = crashhandler.CrashHandler
113 _CrashHandler = crashhandler.CrashHandler
119
114
120 def __init__(self, argv=None):
115 def __init__(self, argv=None):
121 self.argv = sys.argv[1:] if argv is None else argv
116 self.argv = sys.argv[1:] if argv is None else argv
122 self.init_logger()
117 self.init_logger()
123
118
124 def init_logger(self):
119 def init_logger(self):
125 self.log = logging.getLogger(self.__class__.__name__)
120 self.log = logging.getLogger(self.__class__.__name__)
126 # This is used as the default until the command line arguments are read.
121 # This is used as the default until the command line arguments are read.
127 self.log.setLevel(self.default_log_level)
122 self.log.setLevel(self.default_log_level)
128 self._log_handler = logging.StreamHandler()
123 self._log_handler = logging.StreamHandler()
129 self._log_formatter = logging.Formatter("[%(name)s] %(message)s")
124 self._log_formatter = logging.Formatter("[%(name)s] %(message)s")
130 self._log_handler.setFormatter(self._log_formatter)
125 self._log_handler.setFormatter(self._log_formatter)
131 self.log.addHandler(self._log_handler)
126 self.log.addHandler(self._log_handler)
132
127
133 def _set_log_level(self, level):
128 def _set_log_level(self, level):
134 self.log.setLevel(level)
129 self.log.setLevel(level)
135
130
136 def _get_log_level(self):
131 def _get_log_level(self):
137 return self.log.level
132 return self.log.level
138
133
139 log_level = property(_get_log_level, _set_log_level)
134 log_level = property(_get_log_level, _set_log_level)
140
135
141 def initialize(self):
136 def initialize(self):
142 """Start the application."""
137 """Start the application."""
143
138
144 if self._initialized:
139 if self._initialized:
145 return
140 return
146
141
147 # The first part is protected with an 'attempt' wrapper, that will log
142 # The first part is protected with an 'attempt' wrapper, that will log
148 # failures with the basic system traceback machinery. Once our crash
143 # failures with the basic system traceback machinery. Once our crash
149 # handler is in place, we can let any subsequent exception propagate,
144 # handler is in place, we can let any subsequent exception propagate,
150 # as our handler will log it with much better detail than the default.
145 # as our handler will log it with much better detail than the default.
151 self.attempt(self.create_crash_handler)
146 self.attempt(self.create_crash_handler)
152 self.create_default_config()
147 self.create_default_config()
153 self.log_default_config()
148 self.log_default_config()
154 self.set_default_config_log_level()
149 self.set_default_config_log_level()
155 self.pre_load_command_line_config()
150 self.pre_load_command_line_config()
156 self.load_command_line_config()
151 self.load_command_line_config()
157 self.set_command_line_config_log_level()
152 self.set_command_line_config_log_level()
158 self.post_load_command_line_config()
153 self.post_load_command_line_config()
159 self.log_command_line_config()
154 self.log_command_line_config()
160 self.find_ipython_dir()
155 self.find_ipython_dir()
161 self.find_resources()
156 self.find_resources()
162 self.find_config_file_name()
157 self.find_config_file_name()
163 self.find_config_file_paths()
158 self.find_config_file_paths()
164 self.pre_load_file_config()
159 self.pre_load_file_config()
165 self.load_file_config()
160 self.load_file_config()
166 self.set_file_config_log_level()
161 self.set_file_config_log_level()
167 self.post_load_file_config()
162 self.post_load_file_config()
168 self.log_file_config()
163 self.log_file_config()
169 self.merge_configs()
164 self.merge_configs()
170 self.log_master_config()
165 self.log_master_config()
171 self.pre_construct()
166 self.pre_construct()
172 self.construct()
167 self.construct()
173 self.post_construct()
168 self.post_construct()
174 self._initialized = True
169 self._initialized = True
175
170
176 def start(self):
171 def start(self):
177 self.initialize()
172 self.initialize()
178 self.start_app()
173 self.start_app()
179
174
180 #-------------------------------------------------------------------------
175 #-------------------------------------------------------------------------
181 # Various stages of Application creation
176 # Various stages of Application creation
182 #-------------------------------------------------------------------------
177 #-------------------------------------------------------------------------
183
178
184 def create_crash_handler(self):
179 def create_crash_handler(self):
185 """Create a crash handler, typically setting sys.excepthook to it."""
180 """Create a crash handler, typically setting sys.excepthook to it."""
186 self.crash_handler = self._CrashHandler(self, self.name)
181 self.crash_handler = self._CrashHandler(self, self.name)
187 sys.excepthook = self.crash_handler
182 sys.excepthook = self.crash_handler
188
183
189 def create_default_config(self):
184 def create_default_config(self):
190 """Create defaults that can't be set elsewhere.
185 """Create defaults that can't be set elsewhere.
191
186
192 For the most part, we try to set default in the class attributes
187 For the most part, we try to set default in the class attributes
193 of Components. But, defaults the top-level Application (which is
188 of Components. But, defaults the top-level Application (which is
194 not a HasTraitlets or Component) are not set in this way. Instead
189 not a HasTraitlets or Component) are not set in this way. Instead
195 we set them here. The Global section is for variables like this that
190 we set them here. The Global section is for variables like this that
196 don't belong to a particular component.
191 don't belong to a particular component.
197 """
192 """
198 c = Config()
193 c = Config()
199 c.Global.ipython_dir = get_ipython_dir()
194 c.Global.ipython_dir = get_ipython_dir()
200 c.Global.log_level = self.log_level
195 c.Global.log_level = self.log_level
201 self.default_config = c
196 self.default_config = c
202
197
203 def log_default_config(self):
198 def log_default_config(self):
204 self.log.debug('Default config loaded:')
199 self.log.debug('Default config loaded:')
205 self.log.debug(repr(self.default_config))
200 self.log.debug(repr(self.default_config))
206
201
207 def set_default_config_log_level(self):
202 def set_default_config_log_level(self):
208 try:
203 try:
209 self.log_level = self.default_config.Global.log_level
204 self.log_level = self.default_config.Global.log_level
210 except AttributeError:
205 except AttributeError:
211 # Fallback to the default_log_level class attribute
206 # Fallback to the default_log_level class attribute
212 pass
207 pass
213
208
214 def create_command_line_config(self):
209 def create_command_line_config(self):
215 """Create and return a command line config loader."""
210 """Create and return a command line config loader."""
216 return ArgParseConfigLoader(self.argv, self.cl_arguments,
211 return ArgParseConfigLoader(self.argv, self.cl_arguments,
217 description=self.description,
212 description=self.description,
218 version=release.version,
213 version=release.version,
219 usage=self.usage,
214 usage=self.usage,
220 )
215 )
221
216
222 def pre_load_command_line_config(self):
217 def pre_load_command_line_config(self):
223 """Do actions just before loading the command line config."""
218 """Do actions just before loading the command line config."""
224 pass
219 pass
225
220
226 def load_command_line_config(self):
221 def load_command_line_config(self):
227 """Load the command line config."""
222 """Load the command line config."""
228 loader = self.create_command_line_config()
223 loader = self.create_command_line_config()
229 self.command_line_config = loader.load_config()
224 self.command_line_config = loader.load_config()
230 self.extra_args = loader.get_extra_args()
225 self.extra_args = loader.get_extra_args()
231
226
232 def set_command_line_config_log_level(self):
227 def set_command_line_config_log_level(self):
233 try:
228 try:
234 self.log_level = self.command_line_config.Global.log_level
229 self.log_level = self.command_line_config.Global.log_level
235 except AttributeError:
230 except AttributeError:
236 pass
231 pass
237
232
238 def post_load_command_line_config(self):
233 def post_load_command_line_config(self):
239 """Do actions just after loading the command line config."""
234 """Do actions just after loading the command line config."""
240 pass
235 pass
241
236
242 def log_command_line_config(self):
237 def log_command_line_config(self):
243 self.log.debug("Command line config loaded:")
238 self.log.debug("Command line config loaded:")
244 self.log.debug(repr(self.command_line_config))
239 self.log.debug(repr(self.command_line_config))
245
240
246 def find_ipython_dir(self):
241 def find_ipython_dir(self):
247 """Set the IPython directory.
242 """Set the IPython directory.
248
243
249 This sets ``self.ipython_dir``, but the actual value that is passed to
244 This sets ``self.ipython_dir``, but the actual value that is passed to
250 the application is kept in either ``self.default_config`` or
245 the application is kept in either ``self.default_config`` or
251 ``self.command_line_config``. This also adds ``self.ipython_dir`` to
246 ``self.command_line_config``. This also adds ``self.ipython_dir`` to
252 ``sys.path`` so config files there can be referenced by other config
247 ``sys.path`` so config files there can be referenced by other config
253 files.
248 files.
254 """
249 """
255
250
256 try:
251 try:
257 self.ipython_dir = self.command_line_config.Global.ipython_dir
252 self.ipython_dir = self.command_line_config.Global.ipython_dir
258 except AttributeError:
253 except AttributeError:
259 self.ipython_dir = self.default_config.Global.ipython_dir
254 self.ipython_dir = self.default_config.Global.ipython_dir
260 sys.path.append(os.path.abspath(self.ipython_dir))
255 sys.path.append(os.path.abspath(self.ipython_dir))
261 if not os.path.isdir(self.ipython_dir):
256 if not os.path.isdir(self.ipython_dir):
262 os.makedirs(self.ipython_dir, mode=0777)
257 os.makedirs(self.ipython_dir, mode=0777)
263 self.log.debug("IPYTHON_DIR set to: %s" % self.ipython_dir)
258 self.log.debug("IPYTHON_DIR set to: %s" % self.ipython_dir)
264
259
265 def find_resources(self):
260 def find_resources(self):
266 """Find other resources that need to be in place.
261 """Find other resources that need to be in place.
267
262
268 Things like cluster directories need to be in place to find the
263 Things like cluster directories need to be in place to find the
269 config file. These happen right after the IPython directory has
264 config file. These happen right after the IPython directory has
270 been set.
265 been set.
271 """
266 """
272 pass
267 pass
273
268
274 def find_config_file_name(self):
269 def find_config_file_name(self):
275 """Find the config file name for this application.
270 """Find the config file name for this application.
276
271
277 This must set ``self.config_file_name`` to the filename of the
272 This must set ``self.config_file_name`` to the filename of the
278 config file to use (just the filename). The search paths for the
273 config file to use (just the filename). The search paths for the
279 config file are set in :meth:`find_config_file_paths` and then passed
274 config file are set in :meth:`find_config_file_paths` and then passed
280 to the config file loader where they are resolved to an absolute path.
275 to the config file loader where they are resolved to an absolute path.
281
276
282 If a profile has been set at the command line, this will resolve it.
277 If a profile has been set at the command line, this will resolve it.
283 """
278 """
284
279
285 try:
280 try:
286 self.config_file_name = self.command_line_config.Global.config_file
281 self.config_file_name = self.command_line_config.Global.config_file
287 except AttributeError:
282 except AttributeError:
288 pass
283 pass
289
284
290 try:
285 try:
291 self.profile_name = self.command_line_config.Global.profile
286 self.profile_name = self.command_line_config.Global.profile
292 except AttributeError:
287 except AttributeError:
293 pass
288 pass
294 else:
289 else:
295 name_parts = self.config_file_name.split('.')
290 name_parts = self.config_file_name.split('.')
296 name_parts.insert(1, u'_' + self.profile_name + u'.')
291 name_parts.insert(1, u'_' + self.profile_name + u'.')
297 self.config_file_name = ''.join(name_parts)
292 self.config_file_name = ''.join(name_parts)
298
293
299 def find_config_file_paths(self):
294 def find_config_file_paths(self):
300 """Set the search paths for resolving the config file.
295 """Set the search paths for resolving the config file.
301
296
302 This must set ``self.config_file_paths`` to a sequence of search
297 This must set ``self.config_file_paths`` to a sequence of search
303 paths to pass to the config file loader.
298 paths to pass to the config file loader.
304 """
299 """
305 # Include our own profiles directory last, so that users can still find
300 # Include our own profiles directory last, so that users can still find
306 # our shipped copies of builtin profiles even if they don't have them
301 # our shipped copies of builtin profiles even if they don't have them
307 # in their local ipython directory.
302 # in their local ipython directory.
308 prof_dir = os.path.join(get_ipython_package_dir(), 'config', 'profile')
303 prof_dir = os.path.join(get_ipython_package_dir(), 'config', 'profile')
309 self.config_file_paths = (os.getcwd(), self.ipython_dir, prof_dir)
304 self.config_file_paths = (os.getcwd(), self.ipython_dir, prof_dir)
310
305
311 def pre_load_file_config(self):
306 def pre_load_file_config(self):
312 """Do actions before the config file is loaded."""
307 """Do actions before the config file is loaded."""
313 pass
308 pass
314
309
315 def load_file_config(self):
310 def load_file_config(self):
316 """Load the config file.
311 """Load the config file.
317
312
318 This tries to load the config file from disk. If successful, the
313 This tries to load the config file from disk. If successful, the
319 ``CONFIG_FILE`` config variable is set to the resolved config file
314 ``CONFIG_FILE`` config variable is set to the resolved config file
320 location. If not successful, an empty config is used.
315 location. If not successful, an empty config is used.
321 """
316 """
322 self.log.debug("Attempting to load config file: %s" %
317 self.log.debug("Attempting to load config file: %s" %
323 self.config_file_name)
318 self.config_file_name)
324 loader = PyFileConfigLoader(self.config_file_name,
319 loader = PyFileConfigLoader(self.config_file_name,
325 path=self.config_file_paths)
320 path=self.config_file_paths)
326 try:
321 try:
327 self.file_config = loader.load_config()
322 self.file_config = loader.load_config()
328 self.file_config.Global.config_file = loader.full_filename
323 self.file_config.Global.config_file = loader.full_filename
329 except IOError:
324 except IOError:
330 # Only warn if the default config file was NOT being used.
325 # Only warn if the default config file was NOT being used.
331 if not self.config_file_name==self.default_config_file_name:
326 if not self.config_file_name==self.default_config_file_name:
332 self.log.warn("Config file not found, skipping: %s" %
327 self.log.warn("Config file not found, skipping: %s" %
333 self.config_file_name, exc_info=True)
328 self.config_file_name, exc_info=True)
334 self.file_config = Config()
329 self.file_config = Config()
335 except:
330 except:
336 self.log.warn("Error loading config file: %s" %
331 self.log.warn("Error loading config file: %s" %
337 self.config_file_name, exc_info=True)
332 self.config_file_name, exc_info=True)
338 self.file_config = Config()
333 self.file_config = Config()
339
334
340 def set_file_config_log_level(self):
335 def set_file_config_log_level(self):
341 # We need to keeep self.log_level updated. But we only use the value
336 # We need to keeep self.log_level updated. But we only use the value
342 # of the file_config if a value was not specified at the command
337 # of the file_config if a value was not specified at the command
343 # line, because the command line overrides everything.
338 # line, because the command line overrides everything.
344 if not hasattr(self.command_line_config.Global, 'log_level'):
339 if not hasattr(self.command_line_config.Global, 'log_level'):
345 try:
340 try:
346 self.log_level = self.file_config.Global.log_level
341 self.log_level = self.file_config.Global.log_level
347 except AttributeError:
342 except AttributeError:
348 pass # Use existing value
343 pass # Use existing value
349
344
350 def post_load_file_config(self):
345 def post_load_file_config(self):
351 """Do actions after the config file is loaded."""
346 """Do actions after the config file is loaded."""
352 pass
347 pass
353
348
354 def log_file_config(self):
349 def log_file_config(self):
355 if hasattr(self.file_config.Global, 'config_file'):
350 if hasattr(self.file_config.Global, 'config_file'):
356 self.log.debug("Config file loaded: %s" %
351 self.log.debug("Config file loaded: %s" %
357 self.file_config.Global.config_file)
352 self.file_config.Global.config_file)
358 self.log.debug(repr(self.file_config))
353 self.log.debug(repr(self.file_config))
359
354
360 def merge_configs(self):
355 def merge_configs(self):
361 """Merge the default, command line and file config objects."""
356 """Merge the default, command line and file config objects."""
362 config = Config()
357 config = Config()
363 config._merge(self.default_config)
358 config._merge(self.default_config)
364 config._merge(self.file_config)
359 config._merge(self.file_config)
365 config._merge(self.command_line_config)
360 config._merge(self.command_line_config)
366 self.master_config = config
361 self.master_config = config
367
362
368 def log_master_config(self):
363 def log_master_config(self):
369 self.log.debug("Master config created:")
364 self.log.debug("Master config created:")
370 self.log.debug(repr(self.master_config))
365 self.log.debug(repr(self.master_config))
371
366
372 def pre_construct(self):
367 def pre_construct(self):
373 """Do actions after the config has been built, but before construct."""
368 """Do actions after the config has been built, but before construct."""
374 pass
369 pass
375
370
376 def construct(self):
371 def construct(self):
377 """Construct the main components that make up this app."""
372 """Construct the main components that make up this app."""
378 self.log.debug("Constructing components for application")
373 self.log.debug("Constructing components for application")
379
374
380 def post_construct(self):
375 def post_construct(self):
381 """Do actions after construct, but before starting the app."""
376 """Do actions after construct, but before starting the app."""
382 pass
377 pass
383
378
384 def start_app(self):
379 def start_app(self):
385 """Actually start the app."""
380 """Actually start the app."""
386 self.log.debug("Starting application")
381 self.log.debug("Starting application")
387
382
388 #-------------------------------------------------------------------------
383 #-------------------------------------------------------------------------
389 # Utility methods
384 # Utility methods
390 #-------------------------------------------------------------------------
385 #-------------------------------------------------------------------------
391
386
392 def abort(self):
387 def abort(self):
393 """Abort the starting of the application."""
388 """Abort the starting of the application."""
394 if self._exiting:
389 if self._exiting:
395 pass
390 pass
396 else:
391 else:
397 self.log.critical("Aborting application: %s" % self.name, exc_info=True)
392 self.log.critical("Aborting application: %s" % self.name, exc_info=True)
398 self._exiting = True
393 self._exiting = True
399 sys.exit(1)
394 sys.exit(1)
400
395
401 def exit(self, exit_status=0):
396 def exit(self, exit_status=0):
402 if self._exiting:
397 if self._exiting:
403 pass
398 pass
404 else:
399 else:
405 self.log.debug("Exiting application: %s" % self.name)
400 self.log.debug("Exiting application: %s" % self.name)
406 self._exiting = True
401 self._exiting = True
407 sys.exit(exit_status)
402 sys.exit(exit_status)
408
403
409 def attempt(self, func, action='abort'):
404 def attempt(self, func, action='abort'):
410 try:
405 try:
411 func()
406 func()
412 except SystemExit:
407 except SystemExit:
413 raise
408 raise
414 except:
409 except:
415 if action == 'abort':
410 if action == 'abort':
416 self.log.critical("Aborting application: %s" % self.name,
411 self.log.critical("Aborting application: %s" % self.name,
417 exc_info=True)
412 exc_info=True)
418 self.abort()
413 self.abort()
419 raise
414 raise
420 elif action == 'exit':
415 elif action == 'exit':
421 self.exit(0)
416 self.exit(0)
422
417
@@ -1,674 +1,643 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 The :class:`~IPython.core.application.Application` object for the command
4 The :class:`~IPython.core.application.Application` object for the command
5 line :command:`ipython` program.
5 line :command:`ipython` program.
6
6
7 Authors
7 Authors
8 -------
8 -------
9
9
10 * Brian Granger
10 * Brian Granger
11 * Fernando Perez
11 * Fernando Perez
12 """
12 """
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Copyright (C) 2008-2010 The IPython Development Team
15 # Copyright (C) 2008-2010 The IPython Development Team
16 #
16 #
17 # Distributed under the terms of the BSD License. The full license is in
17 # Distributed under the terms of the BSD License. The full license is in
18 # the file COPYING, distributed as part of this software.
18 # the file COPYING, distributed as part of this software.
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # Imports
22 # Imports
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24 from __future__ import absolute_import
24 from __future__ import absolute_import
25
25
26 import logging
26 import logging
27 import os
27 import os
28 import sys
28 import sys
29
29
30 from IPython.core import crashhandler
30 from IPython.core import crashhandler
31 from IPython.core import release
32 from IPython.core.application import Application
31 from IPython.core.application import Application
33 from IPython.core.error import UsageError
34 from IPython.core.iplib import InteractiveShell
32 from IPython.core.iplib import InteractiveShell
35 from IPython.core.pylabtools import pylab_activate
36 from IPython.config.loader import (
33 from IPython.config.loader import (
37 NoConfigDefault,
38 Config,
34 Config,
39 PyFileConfigLoader
35 PyFileConfigLoader,
36 # NoConfigDefault,
40 )
37 )
41 from IPython.lib import inputhook
38 from IPython.lib import inputhook
42 from IPython.utils.genutils import filefind, get_ipython_dir
39 from IPython.utils.genutils import filefind, get_ipython_dir
43 from . import usage
40 from . import usage
44
41
45 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
46 # Globals, utilities and helpers
43 # Globals, utilities and helpers
47 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
48
45
49 default_config_file_name = u'ipython_config.py'
46 default_config_file_name = u'ipython_config.py'
50
47
51 cl_args = (
48 cl_args = (
52 (('--autocall',), dict(
49 (('--autocall',), dict(
53 type=int, dest='InteractiveShell.autocall', default=NoConfigDefault,
50 type=int, dest='InteractiveShell.autocall',
54 help=
51 help=
55 """Make IPython automatically call any callable object even if you
52 """Make IPython automatically call any callable object even if you
56 didn't type explicit parentheses. For example, 'str 43' becomes
53 didn't type explicit parentheses. For example, 'str 43' becomes
57 'str(43)' automatically. The value can be '0' to disable the feature,
54 'str(43)' automatically. The value can be '0' to disable the feature,
58 '1' for 'smart' autocall, where it is not applied if there are no more
55 '1' for 'smart' autocall, where it is not applied if there are no more
59 arguments on the line, and '2' for 'full' autocall, where all callable
56 arguments on the line, and '2' for 'full' autocall, where all callable
60 objects are automatically called (even if no arguments are present).
57 objects are automatically called (even if no arguments are present).
61 The default is '1'.""",
58 The default is '1'.""",
62 metavar='InteractiveShell.autocall')
59 metavar='InteractiveShell.autocall')
63 ),
60 ),
64 (('--autoindent',), dict(
61 (('--autoindent',), dict(
65 action='store_true', dest='InteractiveShell.autoindent',
62 action='store_true', dest='InteractiveShell.autoindent',
66 default=NoConfigDefault,
67 help='Turn on autoindenting.')
63 help='Turn on autoindenting.')
68 ),
64 ),
69 (('--no-autoindent',), dict(
65 (('--no-autoindent',), dict(
70 action='store_false', dest='InteractiveShell.autoindent',
66 action='store_false', dest='InteractiveShell.autoindent',
71 default=NoConfigDefault,
72 help='Turn off autoindenting.')
67 help='Turn off autoindenting.')
73 ),
68 ),
74 (('--automagic',), dict(
69 (('--automagic',), dict(
75 action='store_true', dest='InteractiveShell.automagic',
70 action='store_true', dest='InteractiveShell.automagic',
76 default=NoConfigDefault,
77 help='Turn on the auto calling of magic commands.'
71 help='Turn on the auto calling of magic commands.'
78 'Type %%magic at the IPython prompt for more information.')
72 'Type %%magic at the IPython prompt for more information.')
79 ),
73 ),
80 (('--no-automagic',), dict(
74 (('--no-automagic',), dict(
81 action='store_false', dest='InteractiveShell.automagic',
75 action='store_false', dest='InteractiveShell.automagic',
82 default=NoConfigDefault,
83 help='Turn off the auto calling of magic commands.')
76 help='Turn off the auto calling of magic commands.')
84 ),
77 ),
85 (('--autoedit-syntax',), dict(
78 (('--autoedit-syntax',), dict(
86 action='store_true', dest='InteractiveShell.autoedit_syntax',
79 action='store_true', dest='InteractiveShell.autoedit_syntax',
87 default=NoConfigDefault,
88 help='Turn on auto editing of files with syntax errors.')
80 help='Turn on auto editing of files with syntax errors.')
89 ),
81 ),
90 (('--no-autoedit-syntax',), dict(
82 (('--no-autoedit-syntax',), dict(
91 action='store_false', dest='InteractiveShell.autoedit_syntax',
83 action='store_false', dest='InteractiveShell.autoedit_syntax',
92 default=NoConfigDefault,
93 help='Turn off auto editing of files with syntax errors.')
84 help='Turn off auto editing of files with syntax errors.')
94 ),
85 ),
95 (('--banner',), dict(
86 (('--banner',), dict(
96 action='store_true', dest='Global.display_banner',
87 action='store_true', dest='Global.display_banner',
97 default=NoConfigDefault,
98 help='Display a banner upon starting IPython.')
88 help='Display a banner upon starting IPython.')
99 ),
89 ),
100 (('--no-banner',), dict(
90 (('--no-banner',), dict(
101 action='store_false', dest='Global.display_banner',
91 action='store_false', dest='Global.display_banner',
102 default=NoConfigDefault,
103 help="Don't display a banner upon starting IPython.")
92 help="Don't display a banner upon starting IPython.")
104 ),
93 ),
105 (('--cache-size',), dict(
94 (('--cache-size',), dict(
106 type=int, dest='InteractiveShell.cache_size', default=NoConfigDefault,
95 type=int, dest='InteractiveShell.cache_size',
107 help=
96 help=
108 """Set the size of the output cache. The default is 1000, you can
97 """Set the size of the output cache. The default is 1000, you can
109 change it permanently in your config file. Setting it to 0 completely
98 change it permanently in your config file. Setting it to 0 completely
110 disables the caching system, and the minimum value accepted is 20 (if
99 disables the caching system, and the minimum value accepted is 20 (if
111 you provide a value less than 20, it is reset to 0 and a warning is
100 you provide a value less than 20, it is reset to 0 and a warning is
112 issued). This limit is defined because otherwise you'll spend more
101 issued). This limit is defined because otherwise you'll spend more
113 time re-flushing a too small cache than working.
102 time re-flushing a too small cache than working.
114 """,
103 """,
115 metavar='InteractiveShell.cache_size')
104 metavar='InteractiveShell.cache_size')
116 ),
105 ),
117 (('--classic',), dict(
106 (('--classic',), dict(
118 action='store_true', dest='Global.classic', default=NoConfigDefault,
107 action='store_true', dest='Global.classic',
119 help="Gives IPython a similar feel to the classic Python prompt.")
108 help="Gives IPython a similar feel to the classic Python prompt.")
120 ),
109 ),
121 (('--colors',), dict(
110 (('--colors',), dict(
122 type=str, dest='InteractiveShell.colors', default=NoConfigDefault,
111 type=str, dest='InteractiveShell.colors',
123 help="Set the color scheme (NoColor, Linux, and LightBG).",
112 help="Set the color scheme (NoColor, Linux, and LightBG).",
124 metavar='InteractiveShell.colors')
113 metavar='InteractiveShell.colors')
125 ),
114 ),
126 (('--color-info',), dict(
115 (('--color-info',), dict(
127 action='store_true', dest='InteractiveShell.color_info',
116 action='store_true', dest='InteractiveShell.color_info',
128 default=NoConfigDefault,
129 help=
117 help=
130 """IPython can display information about objects via a set of func-
118 """IPython can display information about objects via a set of func-
131 tions, and optionally can use colors for this, syntax highlighting
119 tions, and optionally can use colors for this, syntax highlighting
132 source code and various other elements. However, because this
120 source code and various other elements. However, because this
133 information is passed through a pager (like 'less') and many pagers get
121 information is passed through a pager (like 'less') and many pagers get
134 confused with color codes, this option is off by default. You can test
122 confused with color codes, this option is off by default. You can test
135 it and turn it on permanently in your ipython_config.py file if it
123 it and turn it on permanently in your ipython_config.py file if it
136 works for you. Test it and turn it on permanently if it works with
124 works for you. Test it and turn it on permanently if it works with
137 your system. The magic function %%color_info allows you to toggle this
125 your system. The magic function %%color_info allows you to toggle this
138 inter- actively for testing."""
126 inter- actively for testing."""
139 )
127 )
140 ),
128 ),
141 (('--no-color-info',), dict(
129 (('--no-color-info',), dict(
142 action='store_false', dest='InteractiveShell.color_info',
130 action='store_false', dest='InteractiveShell.color_info',
143 default=NoConfigDefault,
144 help="Disable using colors for info related things.")
131 help="Disable using colors for info related things.")
145 ),
132 ),
146 (('--confirm-exit',), dict(
133 (('--confirm-exit',), dict(
147 action='store_true', dest='InteractiveShell.confirm_exit',
134 action='store_true', dest='InteractiveShell.confirm_exit',
148 default=NoConfigDefault,
149 help=
135 help=
150 """Set to confirm when you try to exit IPython with an EOF (Control-D
136 """Set to confirm when you try to exit IPython with an EOF (Control-D
151 in Unix, Control-Z/Enter in Windows). By typing 'exit', 'quit' or
137 in Unix, Control-Z/Enter in Windows). By typing 'exit', 'quit' or
152 '%%Exit', you can force a direct exit without any confirmation.
138 '%%Exit', you can force a direct exit without any confirmation.
153 """
139 """
154 )
140 )
155 ),
141 ),
156 (('--no-confirm-exit',), dict(
142 (('--no-confirm-exit',), dict(
157 action='store_false', dest='InteractiveShell.confirm_exit',
143 action='store_false', dest='InteractiveShell.confirm_exit',
158 default=NoConfigDefault,
159 help="Don't prompt the user when exiting.")
144 help="Don't prompt the user when exiting.")
160 ),
145 ),
161 (('--deep-reload',), dict(
146 (('--deep-reload',), dict(
162 action='store_true', dest='InteractiveShell.deep_reload',
147 action='store_true', dest='InteractiveShell.deep_reload',
163 default=NoConfigDefault,
164 help=
148 help=
165 """Enable deep (recursive) reloading by default. IPython can use the
149 """Enable deep (recursive) reloading by default. IPython can use the
166 deep_reload module which reloads changes in modules recursively (it
150 deep_reload module which reloads changes in modules recursively (it
167 replaces the reload() function, so you don't need to change anything to
151 replaces the reload() function, so you don't need to change anything to
168 use it). deep_reload() forces a full reload of modules whose code may
152 use it). deep_reload() forces a full reload of modules whose code may
169 have changed, which the default reload() function does not. When
153 have changed, which the default reload() function does not. When
170 deep_reload is off, IPython will use the normal reload(), but
154 deep_reload is off, IPython will use the normal reload(), but
171 deep_reload will still be available as dreload(). This fea- ture is off
155 deep_reload will still be available as dreload(). This fea- ture is off
172 by default [which means that you have both normal reload() and
156 by default [which means that you have both normal reload() and
173 dreload()].""")
157 dreload()].""")
174 ),
158 ),
175 (('--no-deep-reload',), dict(
159 (('--no-deep-reload',), dict(
176 action='store_false', dest='InteractiveShell.deep_reload',
160 action='store_false', dest='InteractiveShell.deep_reload',
177 default=NoConfigDefault,
178 help="Disable deep (recursive) reloading by default.")
161 help="Disable deep (recursive) reloading by default.")
179 ),
162 ),
180 (('--editor',), dict(
163 (('--editor',), dict(
181 type=str, dest='InteractiveShell.editor', default=NoConfigDefault,
164 type=str, dest='InteractiveShell.editor',
182 help="Set the editor used by IPython (default to $EDITOR/vi/notepad).",
165 help="Set the editor used by IPython (default to $EDITOR/vi/notepad).",
183 metavar='InteractiveShell.editor')
166 metavar='InteractiveShell.editor')
184 ),
167 ),
185 (('--log','-l'), dict(
168 (('--log','-l'), dict(
186 action='store_true', dest='InteractiveShell.logstart',
169 action='store_true', dest='InteractiveShell.logstart',
187 default=NoConfigDefault,
188 help="Start logging to the default log file (./ipython_log.py).")
170 help="Start logging to the default log file (./ipython_log.py).")
189 ),
171 ),
190 (('--logfile','-lf'), dict(
172 (('--logfile','-lf'), dict(
191 type=unicode, dest='InteractiveShell.logfile', default=NoConfigDefault,
173 type=unicode, dest='InteractiveShell.logfile',
192 help="Start logging to logfile with this name.",
174 help="Start logging to logfile with this name.",
193 metavar='InteractiveShell.logfile')
175 metavar='InteractiveShell.logfile')
194 ),
176 ),
195 (('--log-append','-la'), dict(
177 (('--log-append','-la'), dict(
196 type=unicode, dest='InteractiveShell.logappend',
178 type=unicode, dest='InteractiveShell.logappend',
197 default=NoConfigDefault,
198 help="Start logging to the given file in append mode.",
179 help="Start logging to the given file in append mode.",
199 metavar='InteractiveShell.logfile')
180 metavar='InteractiveShell.logfile')
200 ),
181 ),
201 (('--pdb',), dict(
182 (('--pdb',), dict(
202 action='store_true', dest='InteractiveShell.pdb',
183 action='store_true', dest='InteractiveShell.pdb',
203 default=NoConfigDefault,
204 help="Enable auto calling the pdb debugger after every exception.")
184 help="Enable auto calling the pdb debugger after every exception.")
205 ),
185 ),
206 (('--no-pdb',), dict(
186 (('--no-pdb',), dict(
207 action='store_false', dest='InteractiveShell.pdb',
187 action='store_false', dest='InteractiveShell.pdb',
208 default=NoConfigDefault,
209 help="Disable auto calling the pdb debugger after every exception.")
188 help="Disable auto calling the pdb debugger after every exception.")
210 ),
189 ),
211 (('--pprint',), dict(
190 (('--pprint',), dict(
212 action='store_true', dest='InteractiveShell.pprint',
191 action='store_true', dest='InteractiveShell.pprint',
213 default=NoConfigDefault,
214 help="Enable auto pretty printing of results.")
192 help="Enable auto pretty printing of results.")
215 ),
193 ),
216 (('--no-pprint',), dict(
194 (('--no-pprint',), dict(
217 action='store_false', dest='InteractiveShell.pprint',
195 action='store_false', dest='InteractiveShell.pprint',
218 default=NoConfigDefault,
219 help="Disable auto auto pretty printing of results.")
196 help="Disable auto auto pretty printing of results.")
220 ),
197 ),
221 (('--prompt-in1','-pi1'), dict(
198 (('--prompt-in1','-pi1'), dict(
222 type=str, dest='InteractiveShell.prompt_in1', default=NoConfigDefault,
199 type=str, dest='InteractiveShell.prompt_in1',
223 help=
200 help=
224 """Set the main input prompt ('In [\#]: '). Note that if you are using
201 """Set the main input prompt ('In [\#]: '). Note that if you are using
225 numbered prompts, the number is represented with a '\#' in the string.
202 numbered prompts, the number is represented with a '\#' in the string.
226 Don't forget to quote strings with spaces embedded in them. Most
203 Don't forget to quote strings with spaces embedded in them. Most
227 bash-like escapes can be used to customize IPython's prompts, as well
204 bash-like escapes can be used to customize IPython's prompts, as well
228 as a few additional ones which are IPython-spe- cific. All valid
205 as a few additional ones which are IPython-spe- cific. All valid
229 prompt escapes are described in detail in the Customization section of
206 prompt escapes are described in detail in the Customization section of
230 the IPython manual.""",
207 the IPython manual.""",
231 metavar='InteractiveShell.prompt_in1')
208 metavar='InteractiveShell.prompt_in1')
232 ),
209 ),
233 (('--prompt-in2','-pi2'), dict(
210 (('--prompt-in2','-pi2'), dict(
234 type=str, dest='InteractiveShell.prompt_in2', default=NoConfigDefault,
211 type=str, dest='InteractiveShell.prompt_in2',
235 help=
212 help=
236 """Set the secondary input prompt (' .\D.: '). Similar to the previous
213 """Set the secondary input prompt (' .\D.: '). Similar to the previous
237 option, but used for the continuation prompts. The special sequence
214 option, but used for the continuation prompts. The special sequence
238 '\D' is similar to '\#', but with all digits replaced by dots (so you
215 '\D' is similar to '\#', but with all digits replaced by dots (so you
239 can have your continuation prompt aligned with your input prompt).
216 can have your continuation prompt aligned with your input prompt).
240 Default: ' .\D.: ' (note three spaces at the start for alignment with
217 Default: ' .\D.: ' (note three spaces at the start for alignment with
241 'In [\#]')""",
218 'In [\#]')""",
242 metavar='InteractiveShell.prompt_in2')
219 metavar='InteractiveShell.prompt_in2')
243 ),
220 ),
244 (('--prompt-out','-po'), dict(
221 (('--prompt-out','-po'), dict(
245 type=str, dest='InteractiveShell.prompt_out', default=NoConfigDefault,
222 type=str, dest='InteractiveShell.prompt_out',
246 help="Set the output prompt ('Out[\#]:')",
223 help="Set the output prompt ('Out[\#]:')",
247 metavar='InteractiveShell.prompt_out')
224 metavar='InteractiveShell.prompt_out')
248 ),
225 ),
249 (('--quick',), dict(
226 (('--quick',), dict(
250 action='store_true', dest='Global.quick', default=NoConfigDefault,
227 action='store_true', dest='Global.quick',
251 help="Enable quick startup with no config files.")
228 help="Enable quick startup with no config files.")
252 ),
229 ),
253 (('--readline',), dict(
230 (('--readline',), dict(
254 action='store_true', dest='InteractiveShell.readline_use',
231 action='store_true', dest='InteractiveShell.readline_use',
255 default=NoConfigDefault,
256 help="Enable readline for command line usage.")
232 help="Enable readline for command line usage.")
257 ),
233 ),
258 (('--no-readline',), dict(
234 (('--no-readline',), dict(
259 action='store_false', dest='InteractiveShell.readline_use',
235 action='store_false', dest='InteractiveShell.readline_use',
260 default=NoConfigDefault,
261 help="Disable readline for command line usage.")
236 help="Disable readline for command line usage.")
262 ),
237 ),
263 (('--screen-length','-sl'), dict(
238 (('--screen-length','-sl'), dict(
264 type=int, dest='InteractiveShell.screen_length',
239 type=int, dest='InteractiveShell.screen_length',
265 default=NoConfigDefault,
266 help=
240 help=
267 """Number of lines of your screen, used to control printing of very
241 """Number of lines of your screen, used to control printing of very
268 long strings. Strings longer than this number of lines will be sent
242 long strings. Strings longer than this number of lines will be sent
269 through a pager instead of directly printed. The default value for
243 through a pager instead of directly printed. The default value for
270 this is 0, which means IPython will auto-detect your screen size every
244 this is 0, which means IPython will auto-detect your screen size every
271 time it needs to print certain potentially long strings (this doesn't
245 time it needs to print certain potentially long strings (this doesn't
272 change the behavior of the 'print' keyword, it's only triggered
246 change the behavior of the 'print' keyword, it's only triggered
273 internally). If for some reason this isn't working well (it needs
247 internally). If for some reason this isn't working well (it needs
274 curses support), specify it yourself. Otherwise don't change the
248 curses support), specify it yourself. Otherwise don't change the
275 default.""",
249 default.""",
276 metavar='InteractiveShell.screen_length')
250 metavar='InteractiveShell.screen_length')
277 ),
251 ),
278 (('--separate-in','-si'), dict(
252 (('--separate-in','-si'), dict(
279 type=str, dest='InteractiveShell.separate_in', default=NoConfigDefault,
253 type=str, dest='InteractiveShell.separate_in',
280 help="Separator before input prompts. Default '\\n'.",
254 help="Separator before input prompts. Default '\\n'.",
281 metavar='InteractiveShell.separate_in')
255 metavar='InteractiveShell.separate_in')
282 ),
256 ),
283 (('--separate-out','-so'), dict(
257 (('--separate-out','-so'), dict(
284 type=str, dest='InteractiveShell.separate_out',
258 type=str, dest='InteractiveShell.separate_out',
285 default=NoConfigDefault,
286 help="Separator before output prompts. Default 0 (nothing).",
259 help="Separator before output prompts. Default 0 (nothing).",
287 metavar='InteractiveShell.separate_out')
260 metavar='InteractiveShell.separate_out')
288 ),
261 ),
289 (('--separate-out2','-so2'), dict(
262 (('--separate-out2','-so2'), dict(
290 type=str, dest='InteractiveShell.separate_out2',
263 type=str, dest='InteractiveShell.separate_out2',
291 default=NoConfigDefault,
292 help="Separator after output prompts. Default 0 (nonight).",
264 help="Separator after output prompts. Default 0 (nonight).",
293 metavar='InteractiveShell.separate_out2')
265 metavar='InteractiveShell.separate_out2')
294 ),
266 ),
295 (('-no-sep',), dict(
267 (('-no-sep',), dict(
296 action='store_true', dest='Global.nosep', default=NoConfigDefault,
268 action='store_true', dest='Global.nosep',
297 help="Eliminate all spacing between prompts.")
269 help="Eliminate all spacing between prompts.")
298 ),
270 ),
299 (('--term-title',), dict(
271 (('--term-title',), dict(
300 action='store_true', dest='InteractiveShell.term_title',
272 action='store_true', dest='InteractiveShell.term_title',
301 default=NoConfigDefault,
302 help="Enable auto setting the terminal title.")
273 help="Enable auto setting the terminal title.")
303 ),
274 ),
304 (('--no-term-title',), dict(
275 (('--no-term-title',), dict(
305 action='store_false', dest='InteractiveShell.term_title',
276 action='store_false', dest='InteractiveShell.term_title',
306 default=NoConfigDefault,
307 help="Disable auto setting the terminal title.")
277 help="Disable auto setting the terminal title.")
308 ),
278 ),
309 (('--xmode',), dict(
279 (('--xmode',), dict(
310 type=str, dest='InteractiveShell.xmode', default=NoConfigDefault,
280 type=str, dest='InteractiveShell.xmode',
311 help=
281 help=
312 """Exception reporting mode ('Plain','Context','Verbose'). Plain:
282 """Exception reporting mode ('Plain','Context','Verbose'). Plain:
313 similar to python's normal traceback printing. Context: prints 5 lines
283 similar to python's normal traceback printing. Context: prints 5 lines
314 of context source code around each line in the traceback. Verbose:
284 of context source code around each line in the traceback. Verbose:
315 similar to Context, but additionally prints the variables currently
285 similar to Context, but additionally prints the variables currently
316 visible where the exception happened (shortening their strings if too
286 visible where the exception happened (shortening their strings if too
317 long). This can potentially be very slow, if you happen to have a huge
287 long). This can potentially be very slow, if you happen to have a huge
318 data structure whose string representation is complex to compute.
288 data structure whose string representation is complex to compute.
319 Your computer may appear to freeze for a while with cpu usage at 100%%.
289 Your computer may appear to freeze for a while with cpu usage at 100%%.
320 If this occurs, you can cancel the traceback with Ctrl-C (maybe hitting
290 If this occurs, you can cancel the traceback with Ctrl-C (maybe hitting
321 it more than once).
291 it more than once).
322 """,
292 """,
323 metavar='InteractiveShell.xmode')
293 metavar='InteractiveShell.xmode')
324 ),
294 ),
325 (('--ext',), dict(
295 (('--ext',), dict(
326 type=str, dest='Global.extra_extension', default=NoConfigDefault,
296 type=str, dest='Global.extra_extension',
327 help="The dotted module name of an IPython extension to load.",
297 help="The dotted module name of an IPython extension to load.",
328 metavar='Global.extra_extension')
298 metavar='Global.extra_extension')
329 ),
299 ),
330 (('-c',), dict(
300 (('-c',), dict(
331 type=str, dest='Global.code_to_run', default=NoConfigDefault,
301 type=str, dest='Global.code_to_run',
332 help="Execute the given command string.",
302 help="Execute the given command string.",
333 metavar='Global.code_to_run')
303 metavar='Global.code_to_run')
334 ),
304 ),
335 (('-i',), dict(
305 (('-i',), dict(
336 action='store_true', dest='Global.force_interact',
306 action='store_true', dest='Global.force_interact',
337 default=NoConfigDefault,
338 help=
307 help=
339 "If running code from the command line, become interactive afterwards."
308 "If running code from the command line, become interactive afterwards."
340 )
309 )
341 ),
310 ),
342
311
343 # Options to start with GUI control enabled from the beginning
312 # Options to start with GUI control enabled from the beginning
344 (('--gui',), dict(
313 (('--gui',), dict(
345 type=str, dest='Global.gui', default=NoConfigDefault,
314 type=str, dest='Global.gui',
346 help="Enable GUI event loop integration ('qt', 'wx', 'gtk').",
315 help="Enable GUI event loop integration ('qt', 'wx', 'gtk').",
347 metavar='gui-mode')
316 metavar='gui-mode')
348 ),
317 ),
349
318
350 (('--pylab','-pylab'), dict(
319 (('--pylab','-pylab'), dict(
351 type=str, dest='Global.pylab', default=NoConfigDefault,
320 type=str, dest='Global.pylab',
352 nargs='?', const='auto', metavar='gui-mode',
321 nargs='?', const='auto', metavar='gui-mode',
353 help="Pre-load matplotlib and numpy for interactive use. "+
322 help="Pre-load matplotlib and numpy for interactive use. "+
354 "If no value is given, the gui backend is matplotlib's, else use "+
323 "If no value is given, the gui backend is matplotlib's, else use "+
355 "one of: ['tk', 'qt', 'wx', 'gtk'].")
324 "one of: ['tk', 'qt', 'wx', 'gtk'].")
356 ),
325 ),
357
326
358 # Legacy GUI options. Leave them in for backwards compatibility, but the
327 # Legacy GUI options. Leave them in for backwards compatibility, but the
359 # 'thread' names are really a misnomer now.
328 # 'thread' names are really a misnomer now.
360 (('--wthread','-wthread'), dict(
329 (('--wthread','-wthread'), dict(
361 action='store_true', dest='Global.wthread', default=NoConfigDefault,
330 action='store_true', dest='Global.wthread',
362 help="Enable wxPython event loop integration "+
331 help="Enable wxPython event loop integration "+
363 "(DEPRECATED, use --gui wx)")
332 "(DEPRECATED, use --gui wx)")
364 ),
333 ),
365 (('--q4thread','--qthread','-q4thread','-qthread'), dict(
334 (('--q4thread','--qthread','-q4thread','-qthread'), dict(
366 action='store_true', dest='Global.q4thread', default=NoConfigDefault,
335 action='store_true', dest='Global.q4thread',
367 help="Enable Qt4 event loop integration. Qt3 is no longer supported. "+
336 help="Enable Qt4 event loop integration. Qt3 is no longer supported. "+
368 "(DEPRECATED, use --gui qt)")
337 "(DEPRECATED, use --gui qt)")
369 ),
338 ),
370 (('--gthread','-gthread'), dict(
339 (('--gthread','-gthread'), dict(
371 action='store_true', dest='Global.gthread', default=NoConfigDefault,
340 action='store_true', dest='Global.gthread',
372 help="Enable GTK event loop integration. "+
341 help="Enable GTK event loop integration. "+
373 "(DEPRECATED, use --gui gtk)")
342 "(DEPRECATED, use --gui gtk)")
374 ),
343 ),
375 )
344 )
376
345
377 #-----------------------------------------------------------------------------
346 #-----------------------------------------------------------------------------
378 # Main classes and functions
347 # Main classes and functions
379 #-----------------------------------------------------------------------------
348 #-----------------------------------------------------------------------------
380
349
381 class IPythonApp(Application):
350 class IPythonApp(Application):
382 name = u'ipython'
351 name = u'ipython'
383 #: argparse formats better the 'usage' than the 'description' field
352 #: argparse formats better the 'usage' than the 'description' field
384 description = None
353 description = None
385 #: usage message printed by argparse. If None, auto-generate
354 #: usage message printed by argparse. If None, auto-generate
386 usage = usage.cl_usage
355 usage = usage.cl_usage
387
356
388 config_file_name = default_config_file_name
357 config_file_name = default_config_file_name
389
358
390 cl_arguments = Application.cl_arguments + cl_args
359 cl_arguments = Application.cl_arguments + cl_args
391
360
392 # Private and configuration attributes
361 # Private and configuration attributes
393 _CrashHandler = crashhandler.IPythonCrashHandler
362 _CrashHandler = crashhandler.IPythonCrashHandler
394
363
395 def __init__(self, argv=None, **shell_params):
364 def __init__(self, argv=None, **shell_params):
396 """Create a new IPythonApp.
365 """Create a new IPythonApp.
397
366
398 Parameters
367 Parameters
399 ----------
368 ----------
400 argv : optional, list
369 argv : optional, list
401 If given, used as the command-line argv environment to read arguments
370 If given, used as the command-line argv environment to read arguments
402 from.
371 from.
403
372
404 shell_params : optional, dict
373 shell_params : optional, dict
405 All other keywords are passed to the :class:`iplib.InteractiveShell`
374 All other keywords are passed to the :class:`iplib.InteractiveShell`
406 constructor.
375 constructor.
407 """
376 """
408 super(IPythonApp, self).__init__(argv)
377 super(IPythonApp, self).__init__(argv)
409 self.shell_params = shell_params
378 self.shell_params = shell_params
410
379
411 def create_default_config(self):
380 def create_default_config(self):
412 super(IPythonApp, self).create_default_config()
381 super(IPythonApp, self).create_default_config()
413 # Eliminate multiple lookups
382 # Eliminate multiple lookups
414 Global = self.default_config.Global
383 Global = self.default_config.Global
415
384
416 # Set all default values
385 # Set all default values
417 Global.display_banner = True
386 Global.display_banner = True
418
387
419 # If the -c flag is given or a file is given to run at the cmd line
388 # If the -c flag is given or a file is given to run at the cmd line
420 # like "ipython foo.py", normally we exit without starting the main
389 # like "ipython foo.py", normally we exit without starting the main
421 # loop. The force_interact config variable allows a user to override
390 # loop. The force_interact config variable allows a user to override
422 # this and interact. It is also set by the -i cmd line flag, just
391 # this and interact. It is also set by the -i cmd line flag, just
423 # like Python.
392 # like Python.
424 Global.force_interact = False
393 Global.force_interact = False
425
394
426 # By default always interact by starting the IPython mainloop.
395 # By default always interact by starting the IPython mainloop.
427 Global.interact = True
396 Global.interact = True
428
397
429 # No GUI integration by default
398 # No GUI integration by default
430 Global.gui = False
399 Global.gui = False
431 # Pylab off by default
400 # Pylab off by default
432 Global.pylab = False
401 Global.pylab = False
433
402
434 # Deprecated versions of gui support that used threading, we support
403 # Deprecated versions of gui support that used threading, we support
435 # them just for bacwards compatibility as an alternate spelling for
404 # them just for bacwards compatibility as an alternate spelling for
436 # '--gui X'
405 # '--gui X'
437 Global.qthread = False
406 Global.qthread = False
438 Global.q4thread = False
407 Global.q4thread = False
439 Global.wthread = False
408 Global.wthread = False
440 Global.gthread = False
409 Global.gthread = False
441
410
442 def load_file_config(self):
411 def load_file_config(self):
443 if hasattr(self.command_line_config.Global, 'quick'):
412 if hasattr(self.command_line_config.Global, 'quick'):
444 if self.command_line_config.Global.quick:
413 if self.command_line_config.Global.quick:
445 self.file_config = Config()
414 self.file_config = Config()
446 return
415 return
447 super(IPythonApp, self).load_file_config()
416 super(IPythonApp, self).load_file_config()
448
417
449 def post_load_file_config(self):
418 def post_load_file_config(self):
450 if hasattr(self.command_line_config.Global, 'extra_extension'):
419 if hasattr(self.command_line_config.Global, 'extra_extension'):
451 if not hasattr(self.file_config.Global, 'extensions'):
420 if not hasattr(self.file_config.Global, 'extensions'):
452 self.file_config.Global.extensions = []
421 self.file_config.Global.extensions = []
453 self.file_config.Global.extensions.append(
422 self.file_config.Global.extensions.append(
454 self.command_line_config.Global.extra_extension)
423 self.command_line_config.Global.extra_extension)
455 del self.command_line_config.Global.extra_extension
424 del self.command_line_config.Global.extra_extension
456
425
457 def pre_construct(self):
426 def pre_construct(self):
458 config = self.master_config
427 config = self.master_config
459
428
460 if hasattr(config.Global, 'classic'):
429 if hasattr(config.Global, 'classic'):
461 if config.Global.classic:
430 if config.Global.classic:
462 config.InteractiveShell.cache_size = 0
431 config.InteractiveShell.cache_size = 0
463 config.InteractiveShell.pprint = 0
432 config.InteractiveShell.pprint = 0
464 config.InteractiveShell.prompt_in1 = '>>> '
433 config.InteractiveShell.prompt_in1 = '>>> '
465 config.InteractiveShell.prompt_in2 = '... '
434 config.InteractiveShell.prompt_in2 = '... '
466 config.InteractiveShell.prompt_out = ''
435 config.InteractiveShell.prompt_out = ''
467 config.InteractiveShell.separate_in = \
436 config.InteractiveShell.separate_in = \
468 config.InteractiveShell.separate_out = \
437 config.InteractiveShell.separate_out = \
469 config.InteractiveShell.separate_out2 = ''
438 config.InteractiveShell.separate_out2 = ''
470 config.InteractiveShell.colors = 'NoColor'
439 config.InteractiveShell.colors = 'NoColor'
471 config.InteractiveShell.xmode = 'Plain'
440 config.InteractiveShell.xmode = 'Plain'
472
441
473 if hasattr(config.Global, 'nosep'):
442 if hasattr(config.Global, 'nosep'):
474 if config.Global.nosep:
443 if config.Global.nosep:
475 config.InteractiveShell.separate_in = \
444 config.InteractiveShell.separate_in = \
476 config.InteractiveShell.separate_out = \
445 config.InteractiveShell.separate_out = \
477 config.InteractiveShell.separate_out2 = ''
446 config.InteractiveShell.separate_out2 = ''
478
447
479 # if there is code of files to run from the cmd line, don't interact
448 # if there is code of files to run from the cmd line, don't interact
480 # unless the -i flag (Global.force_interact) is true.
449 # unless the -i flag (Global.force_interact) is true.
481 code_to_run = config.Global.get('code_to_run','')
450 code_to_run = config.Global.get('code_to_run','')
482 file_to_run = False
451 file_to_run = False
483 if len(self.extra_args)>=1:
452 if len(self.extra_args)>=1:
484 if self.extra_args[0]:
453 if self.extra_args[0]:
485 file_to_run = True
454 file_to_run = True
486 if file_to_run or code_to_run:
455 if file_to_run or code_to_run:
487 if not config.Global.force_interact:
456 if not config.Global.force_interact:
488 config.Global.interact = False
457 config.Global.interact = False
489
458
490 def construct(self):
459 def construct(self):
491 # I am a little hesitant to put these into InteractiveShell itself.
460 # I am a little hesitant to put these into InteractiveShell itself.
492 # But that might be the place for them
461 # But that might be the place for them
493 sys.path.insert(0, '')
462 sys.path.insert(0, '')
494
463
495 # Create an InteractiveShell instance
464 # Create an InteractiveShell instance
496 self.shell = InteractiveShell(None, self.master_config,
465 self.shell = InteractiveShell(None, self.master_config,
497 **self.shell_params )
466 **self.shell_params )
498
467
499 def post_construct(self):
468 def post_construct(self):
500 """Do actions after construct, but before starting the app."""
469 """Do actions after construct, but before starting the app."""
501 config = self.master_config
470 config = self.master_config
502
471
503 # shell.display_banner should always be False for the terminal
472 # shell.display_banner should always be False for the terminal
504 # based app, because we call shell.show_banner() by hand below
473 # based app, because we call shell.show_banner() by hand below
505 # so the banner shows *before* all extension loading stuff.
474 # so the banner shows *before* all extension loading stuff.
506 self.shell.display_banner = False
475 self.shell.display_banner = False
507
476
508 if config.Global.display_banner and \
477 if config.Global.display_banner and \
509 config.Global.interact:
478 config.Global.interact:
510 self.shell.show_banner()
479 self.shell.show_banner()
511
480
512 # Make sure there is a space below the banner.
481 # Make sure there is a space below the banner.
513 if self.log_level <= logging.INFO: print
482 if self.log_level <= logging.INFO: print
514
483
515 # Now a variety of things that happen after the banner is printed.
484 # Now a variety of things that happen after the banner is printed.
516 self._enable_gui_pylab()
485 self._enable_gui_pylab()
517 self._load_extensions()
486 self._load_extensions()
518 self._run_exec_lines()
487 self._run_exec_lines()
519 self._run_exec_files()
488 self._run_exec_files()
520 self._run_cmd_line_code()
489 self._run_cmd_line_code()
521 self._configure_xmode()
490 self._configure_xmode()
522
491
523 def _enable_gui_pylab(self):
492 def _enable_gui_pylab(self):
524 """Enable GUI event loop integration, taking pylab into account."""
493 """Enable GUI event loop integration, taking pylab into account."""
525 Global = self.master_config.Global
494 Global = self.master_config.Global
526
495
527 # Select which gui to use
496 # Select which gui to use
528 if Global.gui:
497 if Global.gui:
529 gui = Global.gui
498 gui = Global.gui
530 # The following are deprecated, but there's likely to be a lot of use
499 # The following are deprecated, but there's likely to be a lot of use
531 # of this form out there, so we might as well support it for now. But
500 # of this form out there, so we might as well support it for now. But
532 # the --gui option above takes precedence.
501 # the --gui option above takes precedence.
533 elif Global.wthread:
502 elif Global.wthread:
534 gui = inputhook.GUI_WX
503 gui = inputhook.GUI_WX
535 elif Global.qthread:
504 elif Global.qthread:
536 gui = inputhook.GUI_QT
505 gui = inputhook.GUI_QT
537 elif Global.gthread:
506 elif Global.gthread:
538 gui = inputhook.GUI_GTK
507 gui = inputhook.GUI_GTK
539 else:
508 else:
540 gui = None
509 gui = None
541
510
542 # Using --pylab will also require gui activation, though which toolkit
511 # Using --pylab will also require gui activation, though which toolkit
543 # to use may be chosen automatically based on mpl configuration.
512 # to use may be chosen automatically based on mpl configuration.
544 if Global.pylab:
513 if Global.pylab:
545 activate = self.shell.enable_pylab
514 activate = self.shell.enable_pylab
546 if Global.pylab == 'auto':
515 if Global.pylab == 'auto':
547 gui = None
516 gui = None
548 else:
517 else:
549 gui = Global.pylab
518 gui = Global.pylab
550 else:
519 else:
551 # Enable only GUI integration, no pylab
520 # Enable only GUI integration, no pylab
552 activate = inputhook.enable_gui
521 activate = inputhook.enable_gui
553
522
554 if gui or Global.pylab:
523 if gui or Global.pylab:
555 try:
524 try:
556 self.log.info("Enabling GUI event loop integration, "
525 self.log.info("Enabling GUI event loop integration, "
557 "toolkit=%s, pylab=%s" % (gui, Global.pylab) )
526 "toolkit=%s, pylab=%s" % (gui, Global.pylab) )
558 activate(gui)
527 activate(gui)
559 except:
528 except:
560 self.log.warn("Error in enabling GUI event loop integration:")
529 self.log.warn("Error in enabling GUI event loop integration:")
561 self.shell.showtraceback()
530 self.shell.showtraceback()
562
531
563 def _load_extensions(self):
532 def _load_extensions(self):
564 """Load all IPython extensions in Global.extensions.
533 """Load all IPython extensions in Global.extensions.
565
534
566 This uses the :meth:`InteractiveShell.load_extensions` to load all
535 This uses the :meth:`InteractiveShell.load_extensions` to load all
567 the extensions listed in ``self.master_config.Global.extensions``.
536 the extensions listed in ``self.master_config.Global.extensions``.
568 """
537 """
569 try:
538 try:
570 if hasattr(self.master_config.Global, 'extensions'):
539 if hasattr(self.master_config.Global, 'extensions'):
571 self.log.debug("Loading IPython extensions...")
540 self.log.debug("Loading IPython extensions...")
572 extensions = self.master_config.Global.extensions
541 extensions = self.master_config.Global.extensions
573 for ext in extensions:
542 for ext in extensions:
574 try:
543 try:
575 self.log.info("Loading IPython extension: %s" % ext)
544 self.log.info("Loading IPython extension: %s" % ext)
576 self.shell.load_extension(ext)
545 self.shell.load_extension(ext)
577 except:
546 except:
578 self.log.warn("Error in loading extension: %s" % ext)
547 self.log.warn("Error in loading extension: %s" % ext)
579 self.shell.showtraceback()
548 self.shell.showtraceback()
580 except:
549 except:
581 self.log.warn("Unknown error in loading extensions:")
550 self.log.warn("Unknown error in loading extensions:")
582 self.shell.showtraceback()
551 self.shell.showtraceback()
583
552
584 def _run_exec_lines(self):
553 def _run_exec_lines(self):
585 """Run lines of code in Global.exec_lines in the user's namespace."""
554 """Run lines of code in Global.exec_lines in the user's namespace."""
586 try:
555 try:
587 if hasattr(self.master_config.Global, 'exec_lines'):
556 if hasattr(self.master_config.Global, 'exec_lines'):
588 self.log.debug("Running code from Global.exec_lines...")
557 self.log.debug("Running code from Global.exec_lines...")
589 exec_lines = self.master_config.Global.exec_lines
558 exec_lines = self.master_config.Global.exec_lines
590 for line in exec_lines:
559 for line in exec_lines:
591 try:
560 try:
592 self.log.info("Running code in user namespace: %s" % line)
561 self.log.info("Running code in user namespace: %s" % line)
593 self.shell.runlines(line)
562 self.shell.runlines(line)
594 except:
563 except:
595 self.log.warn("Error in executing line in user namespace: %s" % line)
564 self.log.warn("Error in executing line in user namespace: %s" % line)
596 self.shell.showtraceback()
565 self.shell.showtraceback()
597 except:
566 except:
598 self.log.warn("Unknown error in handling Global.exec_lines:")
567 self.log.warn("Unknown error in handling Global.exec_lines:")
599 self.shell.showtraceback()
568 self.shell.showtraceback()
600
569
601 def _exec_file(self, fname):
570 def _exec_file(self, fname):
602 full_filename = filefind(fname, [u'.', self.ipython_dir])
571 full_filename = filefind(fname, [u'.', self.ipython_dir])
603 if os.path.isfile(full_filename):
572 if os.path.isfile(full_filename):
604 if full_filename.endswith(u'.py'):
573 if full_filename.endswith(u'.py'):
605 self.log.info("Running file in user namespace: %s" % full_filename)
574 self.log.info("Running file in user namespace: %s" % full_filename)
606 self.shell.safe_execfile(full_filename, self.shell.user_ns)
575 self.shell.safe_execfile(full_filename, self.shell.user_ns)
607 elif full_filename.endswith('.ipy'):
576 elif full_filename.endswith('.ipy'):
608 self.log.info("Running file in user namespace: %s" % full_filename)
577 self.log.info("Running file in user namespace: %s" % full_filename)
609 self.shell.safe_execfile_ipy(full_filename)
578 self.shell.safe_execfile_ipy(full_filename)
610 else:
579 else:
611 self.log.warn("File does not have a .py or .ipy extension: <%s>" % full_filename)
580 self.log.warn("File does not have a .py or .ipy extension: <%s>" % full_filename)
612
581
613 def _run_exec_files(self):
582 def _run_exec_files(self):
614 try:
583 try:
615 if hasattr(self.master_config.Global, 'exec_files'):
584 if hasattr(self.master_config.Global, 'exec_files'):
616 self.log.debug("Running files in Global.exec_files...")
585 self.log.debug("Running files in Global.exec_files...")
617 exec_files = self.master_config.Global.exec_files
586 exec_files = self.master_config.Global.exec_files
618 for fname in exec_files:
587 for fname in exec_files:
619 self._exec_file(fname)
588 self._exec_file(fname)
620 except:
589 except:
621 self.log.warn("Unknown error in handling Global.exec_files:")
590 self.log.warn("Unknown error in handling Global.exec_files:")
622 self.shell.showtraceback()
591 self.shell.showtraceback()
623
592
624 def _run_cmd_line_code(self):
593 def _run_cmd_line_code(self):
625 if hasattr(self.master_config.Global, 'code_to_run'):
594 if hasattr(self.master_config.Global, 'code_to_run'):
626 line = self.master_config.Global.code_to_run
595 line = self.master_config.Global.code_to_run
627 try:
596 try:
628 self.log.info("Running code given at command line (-c): %s" % line)
597 self.log.info("Running code given at command line (-c): %s" % line)
629 self.shell.runlines(line)
598 self.shell.runlines(line)
630 except:
599 except:
631 self.log.warn("Error in executing line in user namespace: %s" % line)
600 self.log.warn("Error in executing line in user namespace: %s" % line)
632 self.shell.showtraceback()
601 self.shell.showtraceback()
633 return
602 return
634 # Like Python itself, ignore the second if the first of these is present
603 # Like Python itself, ignore the second if the first of these is present
635 try:
604 try:
636 fname = self.extra_args[0]
605 fname = self.extra_args[0]
637 except:
606 except:
638 pass
607 pass
639 else:
608 else:
640 try:
609 try:
641 self._exec_file(fname)
610 self._exec_file(fname)
642 except:
611 except:
643 self.log.warn("Error in executing file in user namespace: %s" % fname)
612 self.log.warn("Error in executing file in user namespace: %s" % fname)
644 self.shell.showtraceback()
613 self.shell.showtraceback()
645
614
646 def _configure_xmode(self):
615 def _configure_xmode(self):
647 # XXX - shouldn't this be read from the config? I'm still a little
616 # XXX - shouldn't this be read from the config? I'm still a little
648 # lost with all the details of handling the new config guys...
617 # lost with all the details of handling the new config guys...
649 self.shell.InteractiveTB.set_mode(mode=self.shell.xmode)
618 self.shell.InteractiveTB.set_mode(mode=self.shell.xmode)
650
619
651 def start_app(self):
620 def start_app(self):
652 if self.master_config.Global.interact:
621 if self.master_config.Global.interact:
653 self.log.debug("Starting IPython's mainloop...")
622 self.log.debug("Starting IPython's mainloop...")
654 self.shell.mainloop()
623 self.shell.mainloop()
655 else:
624 else:
656 self.log.debug("IPython not interactive, start_app is no-op...")
625 self.log.debug("IPython not interactive, start_app is no-op...")
657
626
658
627
659 def load_default_config(ipython_dir=None):
628 def load_default_config(ipython_dir=None):
660 """Load the default config file from the default ipython_dir.
629 """Load the default config file from the default ipython_dir.
661
630
662 This is useful for embedded shells.
631 This is useful for embedded shells.
663 """
632 """
664 if ipython_dir is None:
633 if ipython_dir is None:
665 ipython_dir = get_ipython_dir()
634 ipython_dir = get_ipython_dir()
666 cl = PyFileConfigLoader(default_config_file_name, ipython_dir)
635 cl = PyFileConfigLoader(default_config_file_name, ipython_dir)
667 config = cl.load_config()
636 config = cl.load_config()
668 return config
637 return config
669
638
670
639
671 def launch_new_instance():
640 def launch_new_instance():
672 """Create and run a full blown IPython instance"""
641 """Create and run a full blown IPython instance"""
673 app = IPythonApp()
642 app = IPythonApp()
674 app.start()
643 app.start()
General Comments 0
You need to be logged in to leave comments. Login now