##// END OF EJS Templates
Manage and propagate argv correctly....
Fernando Perez -
Show More
@@ -1,352 +1,370 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
300
301 # arguments = [(('-f','--file'),dict(type=str,dest='file'))]
301 # arguments = [(('-f','--file'),dict(type=str,dest='file'))]
302 arguments = ()
302 arguments = ()
303
303
304 def __init__(self, *args, **kw):
304 def __init__(self, argv=None, *args, **kw):
305 """Create a config loader for use with argparse.
305 """Create a config loader for use with argparse.
306
306
307 The args and kwargs arguments here are passed onto the constructor
307 With the exception of argv, other args and kwargs arguments here are
308 of :class:`argparse.ArgumentParser`.
308 passed onto the constructor of :class:`argparse.ArgumentParser`.
309
310 Parameters
311 ----------
312
313 argv : optional, list
314 If given, used to read command-line arguments from, otherwise
315 sys.argv[1:] is used.
309 """
316 """
310 super(CommandLineConfigLoader, self).__init__()
317 super(CommandLineConfigLoader, self).__init__()
318 if argv == None:
319 argv = sys.argv[1:]
320 self.argv = argv
311 self.args = args
321 self.args = args
312 self.kw = kw
322 self.kw = kw
313
323
314 def load_config(self, args=None):
324 def load_config(self, args=None):
315 """Parse command line arguments and return as a Struct."""
325 """Parse command line arguments and return as a Struct.
326
327 Parameters
328 ----------
329
330 args : optional, list
331 If given, a list with the structure of sys.argv[1:] to parse arguments
332 from. If not given, the instance's self.argv attribute (given at
333 construction time) is used."""
334
335 if args is None:
336 args = self.argv
316 self._create_parser()
337 self._create_parser()
317 self._parse_args(args)
338 self._parse_args(args)
318 self._convert_to_config()
339 self._convert_to_config()
319 return self.config
340 return self.config
320
341
321 def get_extra_args(self):
342 def get_extra_args(self):
322 if hasattr(self, 'extra_args'):
343 if hasattr(self, 'extra_args'):
323 return self.extra_args
344 return self.extra_args
324 else:
345 else:
325 return []
346 return []
326
347
327 def _create_parser(self):
348 def _create_parser(self):
328 self.parser = ArgumentParser(*self.args, **self.kw)
349 self.parser = ArgumentParser(*self.args, **self.kw)
329 self._add_arguments()
350 self._add_arguments()
330 self._add_other_arguments()
351 self._add_other_arguments()
331
352
332 def _add_other_arguments(self):
353 def _add_other_arguments(self):
333 pass
354 pass
334
355
335 def _add_arguments(self):
356 def _add_arguments(self):
336 for argument in self.arguments:
357 for argument in self.arguments:
337 argument[1].setdefault('default', NoConfigDefault)
358 argument[1].setdefault('default', NoConfigDefault)
338 self.parser.add_argument(*argument[0],**argument[1])
359 self.parser.add_argument(*argument[0],**argument[1])
339
360
340 def _parse_args(self, args=None):
361 def _parse_args(self, args):
341 """self.parser->self.parsed_data"""
362 """self.parser->self.parsed_data"""
342 if args is None:
343 self.parsed_data, self.extra_args = self.parser.parse_known_args()
344 else:
345 self.parsed_data, self.extra_args = self.parser.parse_known_args(args)
363 self.parsed_data, self.extra_args = self.parser.parse_known_args(args)
346
364
347 def _convert_to_config(self):
365 def _convert_to_config(self):
348 """self.parsed_data->self.config"""
366 """self.parsed_data->self.config"""
349 for k, v in vars(self.parsed_data).items():
367 for k, v in vars(self.parsed_data).items():
350 if v is not NoConfigDefault:
368 if v is not NoConfigDefault:
351 exec_str = 'self.config.' + k + '= v'
369 exec_str = 'self.config.' + k + '= v'
352 exec exec_str in locals(), globals()
370 exec exec_str in locals(), globals()
@@ -1,378 +1,381 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
36 from IPython.core import release
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
42 NoConfigDefault
43 )
43 )
44
44
45 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
46 # Classes and functions
46 # Classes and functions
47 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
48
48
49
49
50 class BaseAppArgParseConfigLoader(ArgParseConfigLoader):
50 class BaseAppArgParseConfigLoader(ArgParseConfigLoader):
51 """Default command line options for IPython based applications."""
51 """Default command line options for IPython based applications."""
52
52
53 def _add_other_arguments(self):
53 def _add_other_arguments(self):
54 self.parser.add_argument('--ipython-dir',
54 self.parser.add_argument('--ipython-dir',
55 dest='Global.ipython_dir',type=unicode,
55 dest='Global.ipython_dir',type=unicode,
56 help='Set to override default location of Global.ipython_dir.',
56 help='Set to override default location of Global.ipython_dir.',
57 default=NoConfigDefault,
57 default=NoConfigDefault,
58 metavar='Global.ipython_dir')
58 metavar='Global.ipython_dir')
59 self.parser.add_argument('-p', '--profile',
59 self.parser.add_argument('-p', '--profile',
60 dest='Global.profile',type=unicode,
60 dest='Global.profile',type=unicode,
61 help='The string name of the ipython profile to be used.',
61 help='The string name of the ipython profile to be used.',
62 default=NoConfigDefault,
62 default=NoConfigDefault,
63 metavar='Global.profile')
63 metavar='Global.profile')
64 self.parser.add_argument('--log-level',
64 self.parser.add_argument('--log-level',
65 dest="Global.log_level",type=int,
65 dest="Global.log_level",type=int,
66 help='Set the log level (0,10,20,30,40,50). Default is 30.',
66 help='Set the log level (0,10,20,30,40,50). Default is 30.',
67 default=NoConfigDefault,
67 default=NoConfigDefault,
68 metavar='Global.log_level')
68 metavar='Global.log_level')
69 self.parser.add_argument('--config-file',
69 self.parser.add_argument('--config-file',
70 dest='Global.config_file',type=unicode,
70 dest='Global.config_file',type=unicode,
71 help='Set the config file name to override default.',
71 help='Set the config file name to override default.',
72 default=NoConfigDefault,
72 default=NoConfigDefault,
73 metavar='Global.config_file')
73 metavar='Global.config_file')
74
74
75
75
76 class ApplicationError(Exception):
76 class ApplicationError(Exception):
77 pass
77 pass
78
78
79
79
80 class Application(object):
80 class Application(object):
81 """Load a config, construct components and set them running."""
81 """Load a config, construct components and set them running."""
82
82
83 name = u'ipython'
83 name = u'ipython'
84 description = 'IPython: an enhanced interactive Python shell.'
84 description = 'IPython: an enhanced interactive Python shell.'
85
85
86 config_file_name = u'ipython_config.py'
86 config_file_name = u'ipython_config.py'
87 # Track the default and actual separately because some messages are
87 # Track the default and actual separately because some messages are
88 # only printed if we aren't using the default.
88 # only printed if we aren't using the default.
89 default_config_file_name = config_file_name
89 default_config_file_name = config_file_name
90 default_log_level = logging.WARN
90 default_log_level = logging.WARN
91 # Set by --profile option
91 # Set by --profile option
92 profile_name = None
92 profile_name = None
93 #: User's ipython directory, typically ~/.ipython/
93 #: User's ipython directory, typically ~/.ipython/
94 ipython_dir = None
94 ipython_dir = None
95 #: A reference to the argv to be used (typically ends up being sys.argv[1:])
96 argv = None
95
97
96 # Private attributes
98 # Private attributes
97 _exiting = False
99 _exiting = False
98
100
99 def __init__(self):
101 def __init__(self, argv=None):
102 self.argv = sys.argv[1:] if argv is None else argv
100 self.init_logger()
103 self.init_logger()
101
104
102 def init_logger(self):
105 def init_logger(self):
103 self.log = logging.getLogger(self.__class__.__name__)
106 self.log = logging.getLogger(self.__class__.__name__)
104 # This is used as the default until the command line arguments are read.
107 # This is used as the default until the command line arguments are read.
105 self.log.setLevel(self.default_log_level)
108 self.log.setLevel(self.default_log_level)
106 self._log_handler = logging.StreamHandler()
109 self._log_handler = logging.StreamHandler()
107 self._log_formatter = logging.Formatter("[%(name)s] %(message)s")
110 self._log_formatter = logging.Formatter("[%(name)s] %(message)s")
108 self._log_handler.setFormatter(self._log_formatter)
111 self._log_handler.setFormatter(self._log_formatter)
109 self.log.addHandler(self._log_handler)
112 self.log.addHandler(self._log_handler)
110
113
111 def _set_log_level(self, level):
114 def _set_log_level(self, level):
112 self.log.setLevel(level)
115 self.log.setLevel(level)
113
116
114 def _get_log_level(self):
117 def _get_log_level(self):
115 return self.log.level
118 return self.log.level
116
119
117 log_level = property(_get_log_level, _set_log_level)
120 log_level = property(_get_log_level, _set_log_level)
118
121
119 def start(self):
122 def start(self):
120 """Start the application."""
123 """Start the application."""
121 self.attempt(self.create_default_config)
124 self.attempt(self.create_default_config)
122 self.log_default_config()
125 self.log_default_config()
123 self.set_default_config_log_level()
126 self.set_default_config_log_level()
124 self.attempt(self.pre_load_command_line_config)
127 self.attempt(self.pre_load_command_line_config)
125 self.attempt(self.load_command_line_config, action='abort')
128 self.attempt(self.load_command_line_config, action='abort')
126 self.set_command_line_config_log_level()
129 self.set_command_line_config_log_level()
127 self.attempt(self.post_load_command_line_config)
130 self.attempt(self.post_load_command_line_config)
128 self.log_command_line_config()
131 self.log_command_line_config()
129 self.attempt(self.find_ipython_dir)
132 self.attempt(self.find_ipython_dir)
130 self.attempt(self.find_resources)
133 self.attempt(self.find_resources)
131 self.attempt(self.find_config_file_name)
134 self.attempt(self.find_config_file_name)
132 self.attempt(self.find_config_file_paths)
135 self.attempt(self.find_config_file_paths)
133 self.attempt(self.pre_load_file_config)
136 self.attempt(self.pre_load_file_config)
134 self.attempt(self.load_file_config)
137 self.attempt(self.load_file_config)
135 self.set_file_config_log_level()
138 self.set_file_config_log_level()
136 self.attempt(self.post_load_file_config)
139 self.attempt(self.post_load_file_config)
137 self.log_file_config()
140 self.log_file_config()
138 self.attempt(self.merge_configs)
141 self.attempt(self.merge_configs)
139 self.log_master_config()
142 self.log_master_config()
140 self.attempt(self.pre_construct)
143 self.attempt(self.pre_construct)
141 self.attempt(self.construct)
144 self.attempt(self.construct)
142 self.attempt(self.post_construct)
145 self.attempt(self.post_construct)
143 self.attempt(self.start_app)
146 self.attempt(self.start_app)
144
147
145 #-------------------------------------------------------------------------
148 #-------------------------------------------------------------------------
146 # Various stages of Application creation
149 # Various stages of Application creation
147 #-------------------------------------------------------------------------
150 #-------------------------------------------------------------------------
148
151
149 def create_default_config(self):
152 def create_default_config(self):
150 """Create defaults that can't be set elsewhere.
153 """Create defaults that can't be set elsewhere.
151
154
152 For the most part, we try to set default in the class attributes
155 For the most part, we try to set default in the class attributes
153 of Components. But, defaults the top-level Application (which is
156 of Components. But, defaults the top-level Application (which is
154 not a HasTraitlets or Component) are not set in this way. Instead
157 not a HasTraitlets or Component) are not set in this way. Instead
155 we set them here. The Global section is for variables like this that
158 we set them here. The Global section is for variables like this that
156 don't belong to a particular component.
159 don't belong to a particular component.
157 """
160 """
158 c = Config()
161 c = Config()
159 c.Global.ipython_dir = get_ipython_dir()
162 c.Global.ipython_dir = get_ipython_dir()
160 c.Global.log_level = self.log_level
163 c.Global.log_level = self.log_level
161 self.default_config = c
164 self.default_config = c
162
165
163 def log_default_config(self):
166 def log_default_config(self):
164 self.log.debug('Default config loaded:')
167 self.log.debug('Default config loaded:')
165 self.log.debug(repr(self.default_config))
168 self.log.debug(repr(self.default_config))
166
169
167 def set_default_config_log_level(self):
170 def set_default_config_log_level(self):
168 try:
171 try:
169 self.log_level = self.default_config.Global.log_level
172 self.log_level = self.default_config.Global.log_level
170 except AttributeError:
173 except AttributeError:
171 # Fallback to the default_log_level class attribute
174 # Fallback to the default_log_level class attribute
172 pass
175 pass
173
176
174 def create_command_line_config(self):
177 def create_command_line_config(self):
175 """Create and return a command line config loader."""
178 """Create and return a command line config loader."""
176 return BaseAppArgParseConfigLoader(
179 return BaseAppArgParseConfigLoader(self.argv,
177 description=self.description,
180 description=self.description,
178 version=release.version
181 version=release.version
179 )
182 )
180
183
181 def pre_load_command_line_config(self):
184 def pre_load_command_line_config(self):
182 """Do actions just before loading the command line config."""
185 """Do actions just before loading the command line config."""
183 pass
186 pass
184
187
185 def load_command_line_config(self):
188 def load_command_line_config(self):
186 """Load the command line config."""
189 """Load the command line config."""
187 loader = self.create_command_line_config()
190 loader = self.create_command_line_config()
188 self.command_line_config = loader.load_config()
191 self.command_line_config = loader.load_config()
189 self.extra_args = loader.get_extra_args()
192 self.extra_args = loader.get_extra_args()
190
193
191 def set_command_line_config_log_level(self):
194 def set_command_line_config_log_level(self):
192 try:
195 try:
193 self.log_level = self.command_line_config.Global.log_level
196 self.log_level = self.command_line_config.Global.log_level
194 except AttributeError:
197 except AttributeError:
195 pass
198 pass
196
199
197 def post_load_command_line_config(self):
200 def post_load_command_line_config(self):
198 """Do actions just after loading the command line config."""
201 """Do actions just after loading the command line config."""
199 pass
202 pass
200
203
201 def log_command_line_config(self):
204 def log_command_line_config(self):
202 self.log.debug("Command line config loaded:")
205 self.log.debug("Command line config loaded:")
203 self.log.debug(repr(self.command_line_config))
206 self.log.debug(repr(self.command_line_config))
204
207
205 def find_ipython_dir(self):
208 def find_ipython_dir(self):
206 """Set the IPython directory.
209 """Set the IPython directory.
207
210
208 This sets ``self.ipython_dir``, but the actual value that is passed to
211 This sets ``self.ipython_dir``, but the actual value that is passed to
209 the application is kept in either ``self.default_config`` or
212 the application is kept in either ``self.default_config`` or
210 ``self.command_line_config``. This also adds ``self.ipython_dir`` to
213 ``self.command_line_config``. This also adds ``self.ipython_dir`` to
211 ``sys.path`` so config files there can be referenced by other config
214 ``sys.path`` so config files there can be referenced by other config
212 files.
215 files.
213 """
216 """
214
217
215 try:
218 try:
216 self.ipython_dir = self.command_line_config.Global.ipython_dir
219 self.ipython_dir = self.command_line_config.Global.ipython_dir
217 except AttributeError:
220 except AttributeError:
218 self.ipython_dir = self.default_config.Global.ipython_dir
221 self.ipython_dir = self.default_config.Global.ipython_dir
219 sys.path.append(os.path.abspath(self.ipython_dir))
222 sys.path.append(os.path.abspath(self.ipython_dir))
220 if not os.path.isdir(self.ipython_dir):
223 if not os.path.isdir(self.ipython_dir):
221 os.makedirs(self.ipython_dir, mode=0777)
224 os.makedirs(self.ipython_dir, mode=0777)
222 self.log.debug("IPYTHON_DIR set to: %s" % self.ipython_dir)
225 self.log.debug("IPYTHON_DIR set to: %s" % self.ipython_dir)
223
226
224 def find_resources(self):
227 def find_resources(self):
225 """Find other resources that need to be in place.
228 """Find other resources that need to be in place.
226
229
227 Things like cluster directories need to be in place to find the
230 Things like cluster directories need to be in place to find the
228 config file. These happen right after the IPython directory has
231 config file. These happen right after the IPython directory has
229 been set.
232 been set.
230 """
233 """
231 pass
234 pass
232
235
233 def find_config_file_name(self):
236 def find_config_file_name(self):
234 """Find the config file name for this application.
237 """Find the config file name for this application.
235
238
236 This must set ``self.config_file_name`` to the filename of the
239 This must set ``self.config_file_name`` to the filename of the
237 config file to use (just the filename). The search paths for the
240 config file to use (just the filename). The search paths for the
238 config file are set in :meth:`find_config_file_paths` and then passed
241 config file are set in :meth:`find_config_file_paths` and then passed
239 to the config file loader where they are resolved to an absolute path.
242 to the config file loader where they are resolved to an absolute path.
240
243
241 If a profile has been set at the command line, this will resolve it.
244 If a profile has been set at the command line, this will resolve it.
242 """
245 """
243
246
244 try:
247 try:
245 self.config_file_name = self.command_line_config.Global.config_file
248 self.config_file_name = self.command_line_config.Global.config_file
246 except AttributeError:
249 except AttributeError:
247 pass
250 pass
248
251
249 try:
252 try:
250 self.profile_name = self.command_line_config.Global.profile
253 self.profile_name = self.command_line_config.Global.profile
251 except AttributeError:
254 except AttributeError:
252 pass
255 pass
253 else:
256 else:
254 name_parts = self.config_file_name.split('.')
257 name_parts = self.config_file_name.split('.')
255 name_parts.insert(1, u'_' + self.profile_name + u'.')
258 name_parts.insert(1, u'_' + self.profile_name + u'.')
256 self.config_file_name = ''.join(name_parts)
259 self.config_file_name = ''.join(name_parts)
257
260
258 def find_config_file_paths(self):
261 def find_config_file_paths(self):
259 """Set the search paths for resolving the config file.
262 """Set the search paths for resolving the config file.
260
263
261 This must set ``self.config_file_paths`` to a sequence of search
264 This must set ``self.config_file_paths`` to a sequence of search
262 paths to pass to the config file loader.
265 paths to pass to the config file loader.
263 """
266 """
264 # Include our own profiles directory last, so that users can still find
267 # Include our own profiles directory last, so that users can still find
265 # our shipped copies of builtin profiles even if they don't have them
268 # our shipped copies of builtin profiles even if they don't have them
266 # in their local ipython directory.
269 # in their local ipython directory.
267 prof_dir = os.path.join(get_ipython_package_dir(), 'config', 'profile')
270 prof_dir = os.path.join(get_ipython_package_dir(), 'config', 'profile')
268 self.config_file_paths = (os.getcwd(), self.ipython_dir, prof_dir)
271 self.config_file_paths = (os.getcwd(), self.ipython_dir, prof_dir)
269
272
270 def pre_load_file_config(self):
273 def pre_load_file_config(self):
271 """Do actions before the config file is loaded."""
274 """Do actions before the config file is loaded."""
272 pass
275 pass
273
276
274 def load_file_config(self):
277 def load_file_config(self):
275 """Load the config file.
278 """Load the config file.
276
279
277 This tries to load the config file from disk. If successful, the
280 This tries to load the config file from disk. If successful, the
278 ``CONFIG_FILE`` config variable is set to the resolved config file
281 ``CONFIG_FILE`` config variable is set to the resolved config file
279 location. If not successful, an empty config is used.
282 location. If not successful, an empty config is used.
280 """
283 """
281 self.log.debug("Attempting to load config file: %s" %
284 self.log.debug("Attempting to load config file: %s" %
282 self.config_file_name)
285 self.config_file_name)
283 loader = PyFileConfigLoader(self.config_file_name,
286 loader = PyFileConfigLoader(self.config_file_name,
284 path=self.config_file_paths)
287 path=self.config_file_paths)
285 try:
288 try:
286 self.file_config = loader.load_config()
289 self.file_config = loader.load_config()
287 self.file_config.Global.config_file = loader.full_filename
290 self.file_config.Global.config_file = loader.full_filename
288 except IOError:
291 except IOError:
289 # Only warn if the default config file was NOT being used.
292 # Only warn if the default config file was NOT being used.
290 if not self.config_file_name==self.default_config_file_name:
293 if not self.config_file_name==self.default_config_file_name:
291 self.log.warn("Config file not found, skipping: %s" %
294 self.log.warn("Config file not found, skipping: %s" %
292 self.config_file_name, exc_info=True)
295 self.config_file_name, exc_info=True)
293 self.file_config = Config()
296 self.file_config = Config()
294 except:
297 except:
295 self.log.warn("Error loading config file: %s" %
298 self.log.warn("Error loading config file: %s" %
296 self.config_file_name, exc_info=True)
299 self.config_file_name, exc_info=True)
297 self.file_config = Config()
300 self.file_config = Config()
298
301
299 def set_file_config_log_level(self):
302 def set_file_config_log_level(self):
300 # We need to keeep self.log_level updated. But we only use the value
303 # We need to keeep self.log_level updated. But we only use the value
301 # of the file_config if a value was not specified at the command
304 # of the file_config if a value was not specified at the command
302 # line, because the command line overrides everything.
305 # line, because the command line overrides everything.
303 if not hasattr(self.command_line_config.Global, 'log_level'):
306 if not hasattr(self.command_line_config.Global, 'log_level'):
304 try:
307 try:
305 self.log_level = self.file_config.Global.log_level
308 self.log_level = self.file_config.Global.log_level
306 except AttributeError:
309 except AttributeError:
307 pass # Use existing value
310 pass # Use existing value
308
311
309 def post_load_file_config(self):
312 def post_load_file_config(self):
310 """Do actions after the config file is loaded."""
313 """Do actions after the config file is loaded."""
311 pass
314 pass
312
315
313 def log_file_config(self):
316 def log_file_config(self):
314 if hasattr(self.file_config.Global, 'config_file'):
317 if hasattr(self.file_config.Global, 'config_file'):
315 self.log.debug("Config file loaded: %s" %
318 self.log.debug("Config file loaded: %s" %
316 self.file_config.Global.config_file)
319 self.file_config.Global.config_file)
317 self.log.debug(repr(self.file_config))
320 self.log.debug(repr(self.file_config))
318
321
319 def merge_configs(self):
322 def merge_configs(self):
320 """Merge the default, command line and file config objects."""
323 """Merge the default, command line and file config objects."""
321 config = Config()
324 config = Config()
322 config._merge(self.default_config)
325 config._merge(self.default_config)
323 config._merge(self.file_config)
326 config._merge(self.file_config)
324 config._merge(self.command_line_config)
327 config._merge(self.command_line_config)
325 self.master_config = config
328 self.master_config = config
326
329
327 def log_master_config(self):
330 def log_master_config(self):
328 self.log.debug("Master config created:")
331 self.log.debug("Master config created:")
329 self.log.debug(repr(self.master_config))
332 self.log.debug(repr(self.master_config))
330
333
331 def pre_construct(self):
334 def pre_construct(self):
332 """Do actions after the config has been built, but before construct."""
335 """Do actions after the config has been built, but before construct."""
333 pass
336 pass
334
337
335 def construct(self):
338 def construct(self):
336 """Construct the main components that make up this app."""
339 """Construct the main components that make up this app."""
337 self.log.debug("Constructing components for application")
340 self.log.debug("Constructing components for application")
338
341
339 def post_construct(self):
342 def post_construct(self):
340 """Do actions after construct, but before starting the app."""
343 """Do actions after construct, but before starting the app."""
341 pass
344 pass
342
345
343 def start_app(self):
346 def start_app(self):
344 """Actually start the app."""
347 """Actually start the app."""
345 self.log.debug("Starting application")
348 self.log.debug("Starting application")
346
349
347 #-------------------------------------------------------------------------
350 #-------------------------------------------------------------------------
348 # Utility methods
351 # Utility methods
349 #-------------------------------------------------------------------------
352 #-------------------------------------------------------------------------
350
353
351 def abort(self):
354 def abort(self):
352 """Abort the starting of the application."""
355 """Abort the starting of the application."""
353 if self._exiting:
356 if self._exiting:
354 pass
357 pass
355 else:
358 else:
356 self.log.critical("Aborting application: %s" % self.name, exc_info=True)
359 self.log.critical("Aborting application: %s" % self.name, exc_info=True)
357 self._exiting = True
360 self._exiting = True
358 sys.exit(1)
361 sys.exit(1)
359
362
360 def exit(self, exit_status=0):
363 def exit(self, exit_status=0):
361 if self._exiting:
364 if self._exiting:
362 pass
365 pass
363 else:
366 else:
364 self.log.debug("Exiting application: %s" % self.name)
367 self.log.debug("Exiting application: %s" % self.name)
365 self._exiting = True
368 self._exiting = True
366 sys.exit(exit_status)
369 sys.exit(exit_status)
367
370
368 def attempt(self, func, action='abort'):
371 def attempt(self, func, action='abort'):
369 try:
372 try:
370 func()
373 func()
371 except SystemExit:
374 except SystemExit:
372 raise
375 raise
373 except:
376 except:
374 if action == 'abort':
377 if action == 'abort':
375 self.abort()
378 self.abort()
376 elif action == 'exit':
379 elif action == 'exit':
377 self.exit(0)
380 self.exit(0)
378
381
@@ -1,587 +1,587 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 * Brian Granger
9 * Brian Granger
10 * Fernando Perez
10 * Fernando Perez
11
11
12 Notes
12 Notes
13 -----
13 -----
14 """
14 """
15
15
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Copyright (C) 2008-2009 The IPython Development Team
17 # Copyright (C) 2008-2009 The IPython Development Team
18 #
18 #
19 # Distributed under the terms of the BSD License. The full license is in
19 # Distributed under the terms of the BSD License. The full license is in
20 # the file COPYING, distributed as part of this software.
20 # the file COPYING, distributed as part of this software.
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24 # Imports
24 # Imports
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26
26
27 import logging
27 import logging
28 import os
28 import os
29 import sys
29 import sys
30
30
31 from IPython.core import release
31 from IPython.core import release
32 from IPython.core.application import Application, BaseAppArgParseConfigLoader
32 from IPython.core.application import Application, BaseAppArgParseConfigLoader
33 from IPython.core.error import UsageError
33 from IPython.core.error import UsageError
34 from IPython.core.iplib import InteractiveShell
34 from IPython.core.iplib import InteractiveShell
35 from IPython.core.pylabtools import pylab_activate
35 from IPython.core.pylabtools import pylab_activate
36 from IPython.config.loader import (
36 from IPython.config.loader import (
37 NoConfigDefault,
37 NoConfigDefault,
38 Config,
38 Config,
39 PyFileConfigLoader
39 PyFileConfigLoader
40 )
40 )
41 from IPython.lib import inputhook
41 from IPython.lib import inputhook
42 from IPython.utils.genutils import filefind, get_ipython_dir
42 from IPython.utils.genutils import filefind, get_ipython_dir
43
43
44 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
45 # Utilities and helpers
45 # Utilities and helpers
46 #-----------------------------------------------------------------------------
46 #-----------------------------------------------------------------------------
47
47
48 ipython_desc = """
48 ipython_desc = """
49 A Python shell with automatic history (input and output), dynamic object
49 A Python shell with automatic history (input and output), dynamic object
50 introspection, easier configuration, command completion, access to the system
50 introspection, easier configuration, command completion, access to the system
51 shell and more.
51 shell and more.
52 """
52 """
53
53
54 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
55 # Main classes and functions
55 # Main classes and functions
56 #-----------------------------------------------------------------------------
56 #-----------------------------------------------------------------------------
57
57
58 cl_args = (
58 cl_args = (
59 (('--autocall',), dict(
59 (('--autocall',), dict(
60 type=int, dest='InteractiveShell.autocall', default=NoConfigDefault,
60 type=int, dest='InteractiveShell.autocall', default=NoConfigDefault,
61 help='Set the autocall value (0,1,2).',
61 help='Set the autocall value (0,1,2).',
62 metavar='InteractiveShell.autocall')
62 metavar='InteractiveShell.autocall')
63 ),
63 ),
64 (('--autoindent',), dict(
64 (('--autoindent',), dict(
65 action='store_true', dest='InteractiveShell.autoindent', default=NoConfigDefault,
65 action='store_true', dest='InteractiveShell.autoindent', default=NoConfigDefault,
66 help='Turn on autoindenting.')
66 help='Turn on autoindenting.')
67 ),
67 ),
68 (('--no-autoindent',), dict(
68 (('--no-autoindent',), dict(
69 action='store_false', dest='InteractiveShell.autoindent', default=NoConfigDefault,
69 action='store_false', dest='InteractiveShell.autoindent', default=NoConfigDefault,
70 help='Turn off autoindenting.')
70 help='Turn off autoindenting.')
71 ),
71 ),
72 (('--automagic',), dict(
72 (('--automagic',), dict(
73 action='store_true', dest='InteractiveShell.automagic', default=NoConfigDefault,
73 action='store_true', dest='InteractiveShell.automagic', default=NoConfigDefault,
74 help='Turn on the auto calling of magic commands.')
74 help='Turn on the auto calling of magic commands.')
75 ),
75 ),
76 (('--no-automagic',), dict(
76 (('--no-automagic',), dict(
77 action='store_false', dest='InteractiveShell.automagic', default=NoConfigDefault,
77 action='store_false', dest='InteractiveShell.automagic', default=NoConfigDefault,
78 help='Turn off the auto calling of magic commands.')
78 help='Turn off the auto calling of magic commands.')
79 ),
79 ),
80 (('--autoedit-syntax',), dict(
80 (('--autoedit-syntax',), dict(
81 action='store_true', dest='InteractiveShell.autoedit_syntax', default=NoConfigDefault,
81 action='store_true', dest='InteractiveShell.autoedit_syntax', default=NoConfigDefault,
82 help='Turn on auto editing of files with syntax errors.')
82 help='Turn on auto editing of files with syntax errors.')
83 ),
83 ),
84 (('--no-autoedit-syntax',), dict(
84 (('--no-autoedit-syntax',), dict(
85 action='store_false', dest='InteractiveShell.autoedit_syntax', default=NoConfigDefault,
85 action='store_false', dest='InteractiveShell.autoedit_syntax', default=NoConfigDefault,
86 help='Turn off auto editing of files with syntax errors.')
86 help='Turn off auto editing of files with syntax errors.')
87 ),
87 ),
88 (('--banner',), dict(
88 (('--banner',), dict(
89 action='store_true', dest='Global.display_banner', default=NoConfigDefault,
89 action='store_true', dest='Global.display_banner', default=NoConfigDefault,
90 help='Display a banner upon starting IPython.')
90 help='Display a banner upon starting IPython.')
91 ),
91 ),
92 (('--no-banner',), dict(
92 (('--no-banner',), dict(
93 action='store_false', dest='Global.display_banner', default=NoConfigDefault,
93 action='store_false', dest='Global.display_banner', default=NoConfigDefault,
94 help="Don't display a banner upon starting IPython.")
94 help="Don't display a banner upon starting IPython.")
95 ),
95 ),
96 (('--cache-size',), dict(
96 (('--cache-size',), dict(
97 type=int, dest='InteractiveShell.cache_size', default=NoConfigDefault,
97 type=int, dest='InteractiveShell.cache_size', default=NoConfigDefault,
98 help="Set the size of the output cache.",
98 help="Set the size of the output cache.",
99 metavar='InteractiveShell.cache_size')
99 metavar='InteractiveShell.cache_size')
100 ),
100 ),
101 (('--classic',), dict(
101 (('--classic',), dict(
102 action='store_true', dest='Global.classic', default=NoConfigDefault,
102 action='store_true', dest='Global.classic', default=NoConfigDefault,
103 help="Gives IPython a similar feel to the classic Python prompt.")
103 help="Gives IPython a similar feel to the classic Python prompt.")
104 ),
104 ),
105 (('--colors',), dict(
105 (('--colors',), dict(
106 type=str, dest='InteractiveShell.colors', default=NoConfigDefault,
106 type=str, dest='InteractiveShell.colors', default=NoConfigDefault,
107 help="Set the color scheme (NoColor, Linux, and LightBG).",
107 help="Set the color scheme (NoColor, Linux, and LightBG).",
108 metavar='InteractiveShell.colors')
108 metavar='InteractiveShell.colors')
109 ),
109 ),
110 (('--color-info',), dict(
110 (('--color-info',), dict(
111 action='store_true', dest='InteractiveShell.color_info', default=NoConfigDefault,
111 action='store_true', dest='InteractiveShell.color_info', default=NoConfigDefault,
112 help="Enable using colors for info related things.")
112 help="Enable using colors for info related things.")
113 ),
113 ),
114 (('--no-color-info',), dict(
114 (('--no-color-info',), dict(
115 action='store_false', dest='InteractiveShell.color_info', default=NoConfigDefault,
115 action='store_false', dest='InteractiveShell.color_info', default=NoConfigDefault,
116 help="Disable using colors for info related things.")
116 help="Disable using colors for info related things.")
117 ),
117 ),
118 (('--confirm-exit',), dict(
118 (('--confirm-exit',), dict(
119 action='store_true', dest='InteractiveShell.confirm_exit', default=NoConfigDefault,
119 action='store_true', dest='InteractiveShell.confirm_exit', default=NoConfigDefault,
120 help="Prompt the user when existing.")
120 help="Prompt the user when existing.")
121 ),
121 ),
122 (('--no-confirm-exit',), dict(
122 (('--no-confirm-exit',), dict(
123 action='store_false', dest='InteractiveShell.confirm_exit', default=NoConfigDefault,
123 action='store_false', dest='InteractiveShell.confirm_exit', default=NoConfigDefault,
124 help="Don't prompt the user when existing.")
124 help="Don't prompt the user when existing.")
125 ),
125 ),
126 (('--deep-reload',), dict(
126 (('--deep-reload',), dict(
127 action='store_true', dest='InteractiveShell.deep_reload', default=NoConfigDefault,
127 action='store_true', dest='InteractiveShell.deep_reload', default=NoConfigDefault,
128 help="Enable deep (recursive) reloading by default.")
128 help="Enable deep (recursive) reloading by default.")
129 ),
129 ),
130 (('--no-deep-reload',), dict(
130 (('--no-deep-reload',), dict(
131 action='store_false', dest='InteractiveShell.deep_reload', default=NoConfigDefault,
131 action='store_false', dest='InteractiveShell.deep_reload', default=NoConfigDefault,
132 help="Disable deep (recursive) reloading by default.")
132 help="Disable deep (recursive) reloading by default.")
133 ),
133 ),
134 (('--editor',), dict(
134 (('--editor',), dict(
135 type=str, dest='InteractiveShell.editor', default=NoConfigDefault,
135 type=str, dest='InteractiveShell.editor', default=NoConfigDefault,
136 help="Set the editor used by IPython (default to $EDITOR/vi/notepad).",
136 help="Set the editor used by IPython (default to $EDITOR/vi/notepad).",
137 metavar='InteractiveShell.editor')
137 metavar='InteractiveShell.editor')
138 ),
138 ),
139 (('--log','-l'), dict(
139 (('--log','-l'), dict(
140 action='store_true', dest='InteractiveShell.logstart', default=NoConfigDefault,
140 action='store_true', dest='InteractiveShell.logstart', default=NoConfigDefault,
141 help="Start logging to the default file (./ipython_log.py).")
141 help="Start logging to the default file (./ipython_log.py).")
142 ),
142 ),
143 (('--logfile','-lf'), dict(
143 (('--logfile','-lf'), dict(
144 type=unicode, dest='InteractiveShell.logfile', default=NoConfigDefault,
144 type=unicode, dest='InteractiveShell.logfile', default=NoConfigDefault,
145 help="Start logging to logfile.",
145 help="Start logging to logfile.",
146 metavar='InteractiveShell.logfile')
146 metavar='InteractiveShell.logfile')
147 ),
147 ),
148 (('--log-append','-la'), dict(
148 (('--log-append','-la'), dict(
149 type=unicode, dest='InteractiveShell.logappend', default=NoConfigDefault,
149 type=unicode, dest='InteractiveShell.logappend', default=NoConfigDefault,
150 help="Start logging to the give file in append mode.",
150 help="Start logging to the give file in append mode.",
151 metavar='InteractiveShell.logfile')
151 metavar='InteractiveShell.logfile')
152 ),
152 ),
153 (('--pdb',), dict(
153 (('--pdb',), dict(
154 action='store_true', dest='InteractiveShell.pdb', default=NoConfigDefault,
154 action='store_true', dest='InteractiveShell.pdb', default=NoConfigDefault,
155 help="Enable auto calling the pdb debugger after every exception.")
155 help="Enable auto calling the pdb debugger after every exception.")
156 ),
156 ),
157 (('--no-pdb',), dict(
157 (('--no-pdb',), dict(
158 action='store_false', dest='InteractiveShell.pdb', default=NoConfigDefault,
158 action='store_false', dest='InteractiveShell.pdb', default=NoConfigDefault,
159 help="Disable auto calling the pdb debugger after every exception.")
159 help="Disable auto calling the pdb debugger after every exception.")
160 ),
160 ),
161 (('--pprint',), dict(
161 (('--pprint',), dict(
162 action='store_true', dest='InteractiveShell.pprint', default=NoConfigDefault,
162 action='store_true', dest='InteractiveShell.pprint', default=NoConfigDefault,
163 help="Enable auto pretty printing of results.")
163 help="Enable auto pretty printing of results.")
164 ),
164 ),
165 (('--no-pprint',), dict(
165 (('--no-pprint',), dict(
166 action='store_false', dest='InteractiveShell.pprint', default=NoConfigDefault,
166 action='store_false', dest='InteractiveShell.pprint', default=NoConfigDefault,
167 help="Disable auto auto pretty printing of results.")
167 help="Disable auto auto pretty printing of results.")
168 ),
168 ),
169 (('--prompt-in1','-pi1'), dict(
169 (('--prompt-in1','-pi1'), dict(
170 type=str, dest='InteractiveShell.prompt_in1', default=NoConfigDefault,
170 type=str, dest='InteractiveShell.prompt_in1', default=NoConfigDefault,
171 help="Set the main input prompt ('In [\#]: ')",
171 help="Set the main input prompt ('In [\#]: ')",
172 metavar='InteractiveShell.prompt_in1')
172 metavar='InteractiveShell.prompt_in1')
173 ),
173 ),
174 (('--prompt-in2','-pi2'), dict(
174 (('--prompt-in2','-pi2'), dict(
175 type=str, dest='InteractiveShell.prompt_in2', default=NoConfigDefault,
175 type=str, dest='InteractiveShell.prompt_in2', default=NoConfigDefault,
176 help="Set the secondary input prompt (' .\D.: ')",
176 help="Set the secondary input prompt (' .\D.: ')",
177 metavar='InteractiveShell.prompt_in2')
177 metavar='InteractiveShell.prompt_in2')
178 ),
178 ),
179 (('--prompt-out','-po'), dict(
179 (('--prompt-out','-po'), dict(
180 type=str, dest='InteractiveShell.prompt_out', default=NoConfigDefault,
180 type=str, dest='InteractiveShell.prompt_out', default=NoConfigDefault,
181 help="Set the output prompt ('Out[\#]:')",
181 help="Set the output prompt ('Out[\#]:')",
182 metavar='InteractiveShell.prompt_out')
182 metavar='InteractiveShell.prompt_out')
183 ),
183 ),
184 (('--quick',), dict(
184 (('--quick',), dict(
185 action='store_true', dest='Global.quick', default=NoConfigDefault,
185 action='store_true', dest='Global.quick', default=NoConfigDefault,
186 help="Enable quick startup with no config files.")
186 help="Enable quick startup with no config files.")
187 ),
187 ),
188 (('--readline',), dict(
188 (('--readline',), dict(
189 action='store_true', dest='InteractiveShell.readline_use', default=NoConfigDefault,
189 action='store_true', dest='InteractiveShell.readline_use', default=NoConfigDefault,
190 help="Enable readline for command line usage.")
190 help="Enable readline for command line usage.")
191 ),
191 ),
192 (('--no-readline',), dict(
192 (('--no-readline',), dict(
193 action='store_false', dest='InteractiveShell.readline_use', default=NoConfigDefault,
193 action='store_false', dest='InteractiveShell.readline_use', default=NoConfigDefault,
194 help="Disable readline for command line usage.")
194 help="Disable readline for command line usage.")
195 ),
195 ),
196 (('--screen-length','-sl'), dict(
196 (('--screen-length','-sl'), dict(
197 type=int, dest='InteractiveShell.screen_length', default=NoConfigDefault,
197 type=int, dest='InteractiveShell.screen_length', default=NoConfigDefault,
198 help='Number of lines on screen, used to control printing of long strings.',
198 help='Number of lines on screen, used to control printing of long strings.',
199 metavar='InteractiveShell.screen_length')
199 metavar='InteractiveShell.screen_length')
200 ),
200 ),
201 (('--separate-in','-si'), dict(
201 (('--separate-in','-si'), dict(
202 type=str, dest='InteractiveShell.separate_in', default=NoConfigDefault,
202 type=str, dest='InteractiveShell.separate_in', default=NoConfigDefault,
203 help="Separator before input prompts. Default '\n'.",
203 help="Separator before input prompts. Default '\n'.",
204 metavar='InteractiveShell.separate_in')
204 metavar='InteractiveShell.separate_in')
205 ),
205 ),
206 (('--separate-out','-so'), dict(
206 (('--separate-out','-so'), dict(
207 type=str, dest='InteractiveShell.separate_out', default=NoConfigDefault,
207 type=str, dest='InteractiveShell.separate_out', default=NoConfigDefault,
208 help="Separator before output prompts. Default 0 (nothing).",
208 help="Separator before output prompts. Default 0 (nothing).",
209 metavar='InteractiveShell.separate_out')
209 metavar='InteractiveShell.separate_out')
210 ),
210 ),
211 (('--separate-out2','-so2'), dict(
211 (('--separate-out2','-so2'), dict(
212 type=str, dest='InteractiveShell.separate_out2', default=NoConfigDefault,
212 type=str, dest='InteractiveShell.separate_out2', default=NoConfigDefault,
213 help="Separator after output prompts. Default 0 (nonight).",
213 help="Separator after output prompts. Default 0 (nonight).",
214 metavar='InteractiveShell.separate_out2')
214 metavar='InteractiveShell.separate_out2')
215 ),
215 ),
216 (('-no-sep',), dict(
216 (('-no-sep',), dict(
217 action='store_true', dest='Global.nosep', default=NoConfigDefault,
217 action='store_true', dest='Global.nosep', default=NoConfigDefault,
218 help="Eliminate all spacing between prompts.")
218 help="Eliminate all spacing between prompts.")
219 ),
219 ),
220 (('--term-title',), dict(
220 (('--term-title',), dict(
221 action='store_true', dest='InteractiveShell.term_title', default=NoConfigDefault,
221 action='store_true', dest='InteractiveShell.term_title', default=NoConfigDefault,
222 help="Enable auto setting the terminal title.")
222 help="Enable auto setting the terminal title.")
223 ),
223 ),
224 (('--no-term-title',), dict(
224 (('--no-term-title',), dict(
225 action='store_false', dest='InteractiveShell.term_title', default=NoConfigDefault,
225 action='store_false', dest='InteractiveShell.term_title', default=NoConfigDefault,
226 help="Disable auto setting the terminal title.")
226 help="Disable auto setting the terminal title.")
227 ),
227 ),
228 (('--xmode',), dict(
228 (('--xmode',), dict(
229 type=str, dest='InteractiveShell.xmode', default=NoConfigDefault,
229 type=str, dest='InteractiveShell.xmode', default=NoConfigDefault,
230 help="Exception mode ('Plain','Context','Verbose')",
230 help="Exception mode ('Plain','Context','Verbose')",
231 metavar='InteractiveShell.xmode')
231 metavar='InteractiveShell.xmode')
232 ),
232 ),
233 (('--ext',), dict(
233 (('--ext',), dict(
234 type=str, dest='Global.extra_extension', default=NoConfigDefault,
234 type=str, dest='Global.extra_extension', default=NoConfigDefault,
235 help="The dotted module name of an IPython extension to load.",
235 help="The dotted module name of an IPython extension to load.",
236 metavar='Global.extra_extension')
236 metavar='Global.extra_extension')
237 ),
237 ),
238 (('-c',), dict(
238 (('-c',), dict(
239 type=str, dest='Global.code_to_run', default=NoConfigDefault,
239 type=str, dest='Global.code_to_run', default=NoConfigDefault,
240 help="Execute the given command string.",
240 help="Execute the given command string.",
241 metavar='Global.code_to_run')
241 metavar='Global.code_to_run')
242 ),
242 ),
243 (('-i',), dict(
243 (('-i',), dict(
244 action='store_true', dest='Global.force_interact', default=NoConfigDefault,
244 action='store_true', dest='Global.force_interact', default=NoConfigDefault,
245 help="If running code from the command line, become interactive afterwards.")
245 help="If running code from the command line, become interactive afterwards.")
246 ),
246 ),
247
247
248 # Options to start with GUI control enabled from the beginning
248 # Options to start with GUI control enabled from the beginning
249 (('--gui',), dict(
249 (('--gui',), dict(
250 type=str, dest='Global.gui', default=NoConfigDefault,
250 type=str, dest='Global.gui', default=NoConfigDefault,
251 help="Enable GUI event loop integration ('qt', 'wx', 'gtk').",
251 help="Enable GUI event loop integration ('qt', 'wx', 'gtk').",
252 metavar='gui-mode')
252 metavar='gui-mode')
253 ),
253 ),
254
254
255 (('--pylab',), dict(
255 (('--pylab',), dict(
256 type=str, dest='Global.pylab', default=NoConfigDefault,
256 type=str, dest='Global.pylab', default=NoConfigDefault,
257 nargs='?', const='auto', metavar='gui-mode',
257 nargs='?', const='auto', metavar='gui-mode',
258 help="Pre-load matplotlib and numpy for interactive use. "+
258 help="Pre-load matplotlib and numpy for interactive use. "+
259 "If no value is given, the gui backend is matplotlib's, else use "+
259 "If no value is given, the gui backend is matplotlib's, else use "+
260 "one of: ['tk', 'qt', 'wx', 'gtk'].")
260 "one of: ['tk', 'qt', 'wx', 'gtk'].")
261 ),
261 ),
262
262
263 # Legacy GUI options. Leave them in for backwards compatibility, but the
263 # Legacy GUI options. Leave them in for backwards compatibility, but the
264 # 'thread' names are really a misnomer now.
264 # 'thread' names are really a misnomer now.
265 (('--wthread','-wthread'), dict(
265 (('--wthread','-wthread'), dict(
266 action='store_true', dest='Global.wthread', default=NoConfigDefault,
266 action='store_true', dest='Global.wthread', default=NoConfigDefault,
267 help="Enable wxPython event loop integration "+
267 help="Enable wxPython event loop integration "+
268 "(DEPRECATED, use --gui wx)")
268 "(DEPRECATED, use --gui wx)")
269 ),
269 ),
270 (('--q4thread','--qthread','-q4thread','-qthread'), dict(
270 (('--q4thread','--qthread','-q4thread','-qthread'), dict(
271 action='store_true', dest='Global.q4thread', default=NoConfigDefault,
271 action='store_true', dest='Global.q4thread', default=NoConfigDefault,
272 help="Enable Qt4 event loop integration. Qt3 is no longer supported. "+
272 help="Enable Qt4 event loop integration. Qt3 is no longer supported. "+
273 "(DEPRECATED, use --gui qt)")
273 "(DEPRECATED, use --gui qt)")
274 ),
274 ),
275 (('--gthread','-gthread'), dict(
275 (('--gthread','-gthread'), dict(
276 action='store_true', dest='Global.gthread', default=NoConfigDefault,
276 action='store_true', dest='Global.gthread', default=NoConfigDefault,
277 help="Enable GTK event loop integration. "+
277 help="Enable GTK event loop integration. "+
278 "(DEPRECATED, use --gui gtk)")
278 "(DEPRECATED, use --gui gtk)")
279 ),
279 ),
280 )
280 )
281
281
282
282
283 class IPythonAppCLConfigLoader(BaseAppArgParseConfigLoader):
283 class IPythonAppCLConfigLoader(BaseAppArgParseConfigLoader):
284
284
285 arguments = cl_args
285 arguments = cl_args
286
286
287 def load_config(self):
287 def load_config(self):
288 """Do actions just before loading the command line config."""
288 """Do actions just before loading the command line config."""
289
289
290 # Special hack: there are countless uses of 'ipython -pylab' (with one
290 # Special hack: there are countless uses of 'ipython -pylab' (with one
291 # dash) in the wild, including in printed books. Since argparse does
291 # dash) in the wild, including in printed books. Since argparse does
292 # will interpret -pylab as '-p ylab', sending us in a search for a
292 # will interpret -pylab as '-p ylab', sending us in a search for a
293 # profile named 'ylab', instead we special-case here -pylab as the
293 # profile named 'ylab', instead we special-case here -pylab as the
294 # first or second option only (this is how old ipython used to work)
294 # first or second option only (this is how old ipython used to work)
295 # and convert this use to --pylab. Ugly, but needed for this one
295 # and convert this use to --pylab. Ugly, but needed for this one
296 # very widely used case.
296 # very widely used case.
297 firstargs = sys.argv[:3]
297 firstargs = sys.argv[:3]
298 try:
298 try:
299 idx = firstargs.index('-pylab')
299 idx = firstargs.index('-pylab')
300 except ValueError:
300 except ValueError:
301 pass
301 pass
302 else:
302 else:
303 sys.argv[idx] = '--pylab'
303 sys.argv[idx] = '--pylab'
304 return super(IPythonAppCLConfigLoader, self).load_config()
304 return super(IPythonAppCLConfigLoader, self).load_config()
305
305
306 default_config_file_name = u'ipython_config.py'
306 default_config_file_name = u'ipython_config.py'
307
307
308
308
309 class IPythonApp(Application):
309 class IPythonApp(Application):
310 name = u'ipython'
310 name = u'ipython'
311 description = 'IPython: an enhanced interactive Python shell.'
311 description = 'IPython: an enhanced interactive Python shell.'
312 config_file_name = default_config_file_name
312 config_file_name = default_config_file_name
313
313
314 def create_default_config(self):
314 def create_default_config(self):
315 super(IPythonApp, self).create_default_config()
315 super(IPythonApp, self).create_default_config()
316 # Eliminate multiple lookups
316 # Eliminate multiple lookups
317 Global = self.default_config.Global
317 Global = self.default_config.Global
318
318
319 # Set all default values
319 # Set all default values
320 Global.display_banner = True
320 Global.display_banner = True
321
321
322 # If the -c flag is given or a file is given to run at the cmd line
322 # If the -c flag is given or a file is given to run at the cmd line
323 # like "ipython foo.py", normally we exit without starting the main
323 # like "ipython foo.py", normally we exit without starting the main
324 # loop. The force_interact config variable allows a user to override
324 # loop. The force_interact config variable allows a user to override
325 # this and interact. It is also set by the -i cmd line flag, just
325 # this and interact. It is also set by the -i cmd line flag, just
326 # like Python.
326 # like Python.
327 Global.force_interact = False
327 Global.force_interact = False
328
328
329 # By default always interact by starting the IPython mainloop.
329 # By default always interact by starting the IPython mainloop.
330 Global.interact = True
330 Global.interact = True
331
331
332 # No GUI integration by default
332 # No GUI integration by default
333 Global.gui = False
333 Global.gui = False
334 # Pylab off by default
334 # Pylab off by default
335 Global.pylab = False
335 Global.pylab = False
336
336
337 # Deprecated versions of gui support that used threading, we support
337 # Deprecated versions of gui support that used threading, we support
338 # them just for bacwards compatibility as an alternate spelling for
338 # them just for bacwards compatibility as an alternate spelling for
339 # '--gui X'
339 # '--gui X'
340 Global.qthread = False
340 Global.qthread = False
341 Global.q4thread = False
341 Global.q4thread = False
342 Global.wthread = False
342 Global.wthread = False
343 Global.gthread = False
343 Global.gthread = False
344
344
345 def create_command_line_config(self):
345 def create_command_line_config(self):
346 """Create and return a command line config loader."""
346 """Create and return a command line config loader."""
347 return IPythonAppCLConfigLoader(
347 return IPythonAppCLConfigLoader(self.argv,
348 description=self.description,
348 description=self.description,
349 version=release.version
349 version=release.version
350 )
350 )
351
351
352
352
353 def load_file_config(self):
353 def load_file_config(self):
354 if hasattr(self.command_line_config.Global, 'quick'):
354 if hasattr(self.command_line_config.Global, 'quick'):
355 if self.command_line_config.Global.quick:
355 if self.command_line_config.Global.quick:
356 self.file_config = Config()
356 self.file_config = Config()
357 return
357 return
358 super(IPythonApp, self).load_file_config()
358 super(IPythonApp, self).load_file_config()
359
359
360 def post_load_file_config(self):
360 def post_load_file_config(self):
361 if hasattr(self.command_line_config.Global, 'extra_extension'):
361 if hasattr(self.command_line_config.Global, 'extra_extension'):
362 if not hasattr(self.file_config.Global, 'extensions'):
362 if not hasattr(self.file_config.Global, 'extensions'):
363 self.file_config.Global.extensions = []
363 self.file_config.Global.extensions = []
364 self.file_config.Global.extensions.append(
364 self.file_config.Global.extensions.append(
365 self.command_line_config.Global.extra_extension)
365 self.command_line_config.Global.extra_extension)
366 del self.command_line_config.Global.extra_extension
366 del self.command_line_config.Global.extra_extension
367
367
368 def pre_construct(self):
368 def pre_construct(self):
369 config = self.master_config
369 config = self.master_config
370
370
371 if hasattr(config.Global, 'classic'):
371 if hasattr(config.Global, 'classic'):
372 if config.Global.classic:
372 if config.Global.classic:
373 config.InteractiveShell.cache_size = 0
373 config.InteractiveShell.cache_size = 0
374 config.InteractiveShell.pprint = 0
374 config.InteractiveShell.pprint = 0
375 config.InteractiveShell.prompt_in1 = '>>> '
375 config.InteractiveShell.prompt_in1 = '>>> '
376 config.InteractiveShell.prompt_in2 = '... '
376 config.InteractiveShell.prompt_in2 = '... '
377 config.InteractiveShell.prompt_out = ''
377 config.InteractiveShell.prompt_out = ''
378 config.InteractiveShell.separate_in = \
378 config.InteractiveShell.separate_in = \
379 config.InteractiveShell.separate_out = \
379 config.InteractiveShell.separate_out = \
380 config.InteractiveShell.separate_out2 = ''
380 config.InteractiveShell.separate_out2 = ''
381 config.InteractiveShell.colors = 'NoColor'
381 config.InteractiveShell.colors = 'NoColor'
382 config.InteractiveShell.xmode = 'Plain'
382 config.InteractiveShell.xmode = 'Plain'
383
383
384 if hasattr(config.Global, 'nosep'):
384 if hasattr(config.Global, 'nosep'):
385 if config.Global.nosep:
385 if config.Global.nosep:
386 config.InteractiveShell.separate_in = \
386 config.InteractiveShell.separate_in = \
387 config.InteractiveShell.separate_out = \
387 config.InteractiveShell.separate_out = \
388 config.InteractiveShell.separate_out2 = ''
388 config.InteractiveShell.separate_out2 = ''
389
389
390 # if there is code of files to run from the cmd line, don't interact
390 # if there is code of files to run from the cmd line, don't interact
391 # unless the -i flag (Global.force_interact) is true.
391 # unless the -i flag (Global.force_interact) is true.
392 code_to_run = config.Global.get('code_to_run','')
392 code_to_run = config.Global.get('code_to_run','')
393 file_to_run = False
393 file_to_run = False
394 if len(self.extra_args)>=1:
394 if len(self.extra_args)>=1:
395 if self.extra_args[0]:
395 if self.extra_args[0]:
396 file_to_run = True
396 file_to_run = True
397 if file_to_run or code_to_run:
397 if file_to_run or code_to_run:
398 if not config.Global.force_interact:
398 if not config.Global.force_interact:
399 config.Global.interact = False
399 config.Global.interact = False
400
400
401 def construct(self):
401 def construct(self):
402 # I am a little hesitant to put these into InteractiveShell itself.
402 # I am a little hesitant to put these into InteractiveShell itself.
403 # But that might be the place for them
403 # But that might be the place for them
404 sys.path.insert(0, '')
404 sys.path.insert(0, '')
405
405
406 # Create an InteractiveShell instance
406 # Create an InteractiveShell instance
407 self.shell = InteractiveShell(
407 self.shell = InteractiveShell(
408 parent=None,
408 parent=None,
409 config=self.master_config
409 config=self.master_config
410 )
410 )
411
411
412 def post_construct(self):
412 def post_construct(self):
413 """Do actions after construct, but before starting the app."""
413 """Do actions after construct, but before starting the app."""
414 config = self.master_config
414 config = self.master_config
415
415
416 # shell.display_banner should always be False for the terminal
416 # shell.display_banner should always be False for the terminal
417 # based app, because we call shell.show_banner() by hand below
417 # based app, because we call shell.show_banner() by hand below
418 # so the banner shows *before* all extension loading stuff.
418 # so the banner shows *before* all extension loading stuff.
419 self.shell.display_banner = False
419 self.shell.display_banner = False
420
420
421 if config.Global.display_banner and \
421 if config.Global.display_banner and \
422 config.Global.interact:
422 config.Global.interact:
423 self.shell.show_banner()
423 self.shell.show_banner()
424
424
425 # Make sure there is a space below the banner.
425 # Make sure there is a space below the banner.
426 if self.log_level <= logging.INFO: print
426 if self.log_level <= logging.INFO: print
427
427
428 # Now a variety of things that happen after the banner is printed.
428 # Now a variety of things that happen after the banner is printed.
429 self._enable_gui_pylab()
429 self._enable_gui_pylab()
430 self._load_extensions()
430 self._load_extensions()
431 self._run_exec_lines()
431 self._run_exec_lines()
432 self._run_exec_files()
432 self._run_exec_files()
433 self._run_cmd_line_code()
433 self._run_cmd_line_code()
434 self._configure_xmode()
434 self._configure_xmode()
435
435
436 def _enable_gui_pylab(self):
436 def _enable_gui_pylab(self):
437 """Enable GUI event loop integration, taking pylab into account."""
437 """Enable GUI event loop integration, taking pylab into account."""
438 Global = self.master_config.Global
438 Global = self.master_config.Global
439
439
440 # Select which gui to use
440 # Select which gui to use
441 if Global.gui:
441 if Global.gui:
442 gui = Global.gui
442 gui = Global.gui
443 # The following are deprecated, but there's likely to be a lot of use
443 # The following are deprecated, but there's likely to be a lot of use
444 # of this form out there, so we might as well support it for now. But
444 # of this form out there, so we might as well support it for now. But
445 # the --gui option above takes precedence.
445 # the --gui option above takes precedence.
446 elif Global.wthread:
446 elif Global.wthread:
447 gui = inputhook.GUI_WX
447 gui = inputhook.GUI_WX
448 elif Global.qthread:
448 elif Global.qthread:
449 gui = inputhook.GUI_QT
449 gui = inputhook.GUI_QT
450 elif Global.gthread:
450 elif Global.gthread:
451 gui = inputhook.GUI_GTK
451 gui = inputhook.GUI_GTK
452 else:
452 else:
453 gui = None
453 gui = None
454
454
455 # Using --pylab will also require gui activation, though which toolkit
455 # Using --pylab will also require gui activation, though which toolkit
456 # to use may be chosen automatically based on mpl configuration.
456 # to use may be chosen automatically based on mpl configuration.
457 if Global.pylab:
457 if Global.pylab:
458 activate = self.shell.enable_pylab
458 activate = self.shell.enable_pylab
459 if Global.pylab == 'auto':
459 if Global.pylab == 'auto':
460 gui = None
460 gui = None
461 else:
461 else:
462 gui = Global.pylab
462 gui = Global.pylab
463 else:
463 else:
464 # Enable only GUI integration, no pylab
464 # Enable only GUI integration, no pylab
465 activate = inputhook.enable_gui
465 activate = inputhook.enable_gui
466
466
467 if gui or Global.pylab:
467 if gui or Global.pylab:
468 try:
468 try:
469 self.log.info("Enabling GUI event loop integration, "
469 self.log.info("Enabling GUI event loop integration, "
470 "toolkit=%s, pylab=%s" % (gui, Global.pylab) )
470 "toolkit=%s, pylab=%s" % (gui, Global.pylab) )
471 activate(gui)
471 activate(gui)
472 except:
472 except:
473 self.log.warn("Error in enabling GUI event loop integration:")
473 self.log.warn("Error in enabling GUI event loop integration:")
474 self.shell.showtraceback()
474 self.shell.showtraceback()
475
475
476 def _load_extensions(self):
476 def _load_extensions(self):
477 """Load all IPython extensions in Global.extensions.
477 """Load all IPython extensions in Global.extensions.
478
478
479 This uses the :meth:`InteractiveShell.load_extensions` to load all
479 This uses the :meth:`InteractiveShell.load_extensions` to load all
480 the extensions listed in ``self.master_config.Global.extensions``.
480 the extensions listed in ``self.master_config.Global.extensions``.
481 """
481 """
482 try:
482 try:
483 if hasattr(self.master_config.Global, 'extensions'):
483 if hasattr(self.master_config.Global, 'extensions'):
484 self.log.debug("Loading IPython extensions...")
484 self.log.debug("Loading IPython extensions...")
485 extensions = self.master_config.Global.extensions
485 extensions = self.master_config.Global.extensions
486 for ext in extensions:
486 for ext in extensions:
487 try:
487 try:
488 self.log.info("Loading IPython extension: %s" % ext)
488 self.log.info("Loading IPython extension: %s" % ext)
489 self.shell.load_extension(ext)
489 self.shell.load_extension(ext)
490 except:
490 except:
491 self.log.warn("Error in loading extension: %s" % ext)
491 self.log.warn("Error in loading extension: %s" % ext)
492 self.shell.showtraceback()
492 self.shell.showtraceback()
493 except:
493 except:
494 self.log.warn("Unknown error in loading extensions:")
494 self.log.warn("Unknown error in loading extensions:")
495 self.shell.showtraceback()
495 self.shell.showtraceback()
496
496
497 def _run_exec_lines(self):
497 def _run_exec_lines(self):
498 """Run lines of code in Global.exec_lines in the user's namespace."""
498 """Run lines of code in Global.exec_lines in the user's namespace."""
499 try:
499 try:
500 if hasattr(self.master_config.Global, 'exec_lines'):
500 if hasattr(self.master_config.Global, 'exec_lines'):
501 self.log.debug("Running code from Global.exec_lines...")
501 self.log.debug("Running code from Global.exec_lines...")
502 exec_lines = self.master_config.Global.exec_lines
502 exec_lines = self.master_config.Global.exec_lines
503 for line in exec_lines:
503 for line in exec_lines:
504 try:
504 try:
505 self.log.info("Running code in user namespace: %s" % line)
505 self.log.info("Running code in user namespace: %s" % line)
506 self.shell.runlines(line)
506 self.shell.runlines(line)
507 except:
507 except:
508 self.log.warn("Error in executing line in user namespace: %s" % line)
508 self.log.warn("Error in executing line in user namespace: %s" % line)
509 self.shell.showtraceback()
509 self.shell.showtraceback()
510 except:
510 except:
511 self.log.warn("Unknown error in handling Global.exec_lines:")
511 self.log.warn("Unknown error in handling Global.exec_lines:")
512 self.shell.showtraceback()
512 self.shell.showtraceback()
513
513
514 def _exec_file(self, fname):
514 def _exec_file(self, fname):
515 full_filename = filefind(fname, [u'.', self.ipython_dir])
515 full_filename = filefind(fname, [u'.', self.ipython_dir])
516 if os.path.isfile(full_filename):
516 if os.path.isfile(full_filename):
517 if full_filename.endswith(u'.py'):
517 if full_filename.endswith(u'.py'):
518 self.log.info("Running file in user namespace: %s" % full_filename)
518 self.log.info("Running file in user namespace: %s" % full_filename)
519 self.shell.safe_execfile(full_filename, self.shell.user_ns)
519 self.shell.safe_execfile(full_filename, self.shell.user_ns)
520 elif full_filename.endswith('.ipy'):
520 elif full_filename.endswith('.ipy'):
521 self.log.info("Running file in user namespace: %s" % full_filename)
521 self.log.info("Running file in user namespace: %s" % full_filename)
522 self.shell.safe_execfile_ipy(full_filename)
522 self.shell.safe_execfile_ipy(full_filename)
523 else:
523 else:
524 self.log.warn("File does not have a .py or .ipy extension: <%s>" % full_filename)
524 self.log.warn("File does not have a .py or .ipy extension: <%s>" % full_filename)
525
525
526 def _run_exec_files(self):
526 def _run_exec_files(self):
527 try:
527 try:
528 if hasattr(self.master_config.Global, 'exec_files'):
528 if hasattr(self.master_config.Global, 'exec_files'):
529 self.log.debug("Running files in Global.exec_files...")
529 self.log.debug("Running files in Global.exec_files...")
530 exec_files = self.master_config.Global.exec_files
530 exec_files = self.master_config.Global.exec_files
531 for fname in exec_files:
531 for fname in exec_files:
532 self._exec_file(fname)
532 self._exec_file(fname)
533 except:
533 except:
534 self.log.warn("Unknown error in handling Global.exec_files:")
534 self.log.warn("Unknown error in handling Global.exec_files:")
535 self.shell.showtraceback()
535 self.shell.showtraceback()
536
536
537 def _run_cmd_line_code(self):
537 def _run_cmd_line_code(self):
538 if hasattr(self.master_config.Global, 'code_to_run'):
538 if hasattr(self.master_config.Global, 'code_to_run'):
539 line = self.master_config.Global.code_to_run
539 line = self.master_config.Global.code_to_run
540 try:
540 try:
541 self.log.info("Running code given at command line (-c): %s" % line)
541 self.log.info("Running code given at command line (-c): %s" % line)
542 self.shell.runlines(line)
542 self.shell.runlines(line)
543 except:
543 except:
544 self.log.warn("Error in executing line in user namespace: %s" % line)
544 self.log.warn("Error in executing line in user namespace: %s" % line)
545 self.shell.showtraceback()
545 self.shell.showtraceback()
546 return
546 return
547 # Like Python itself, ignore the second if the first of these is present
547 # Like Python itself, ignore the second if the first of these is present
548 try:
548 try:
549 fname = self.extra_args[0]
549 fname = self.extra_args[0]
550 except:
550 except:
551 pass
551 pass
552 else:
552 else:
553 try:
553 try:
554 self._exec_file(fname)
554 self._exec_file(fname)
555 except:
555 except:
556 self.log.warn("Error in executing file in user namespace: %s" % fname)
556 self.log.warn("Error in executing file in user namespace: %s" % fname)
557 self.shell.showtraceback()
557 self.shell.showtraceback()
558
558
559 def _configure_xmode(self):
559 def _configure_xmode(self):
560 # XXX - shouldn't this be read from the config? I'm still a little
560 # XXX - shouldn't this be read from the config? I'm still a little
561 # lost with all the details of handling the new config guys...
561 # lost with all the details of handling the new config guys...
562 self.shell.InteractiveTB.set_mode(mode=self.shell.xmode)
562 self.shell.InteractiveTB.set_mode(mode=self.shell.xmode)
563
563
564 def start_app(self):
564 def start_app(self):
565 if self.master_config.Global.interact:
565 if self.master_config.Global.interact:
566 self.log.debug("Starting IPython's mainloop...")
566 self.log.debug("Starting IPython's mainloop...")
567 self.shell.mainloop()
567 self.shell.mainloop()
568
568 else:
569 self.log.debug("IPython not interactive, start_app is no-op...")
569
570
570
571
571 def load_default_config(ipython_dir=None):
572 def load_default_config(ipython_dir=None):
572 """Load the default config file from the default ipython_dir.
573 """Load the default config file from the default ipython_dir.
573
574
574 This is useful for embedded shells.
575 This is useful for embedded shells.
575 """
576 """
576 if ipython_dir is None:
577 if ipython_dir is None:
577 ipython_dir = get_ipython_dir()
578 ipython_dir = get_ipython_dir()
578 cl = PyFileConfigLoader(default_config_file_name, ipython_dir)
579 cl = PyFileConfigLoader(default_config_file_name, ipython_dir)
579 config = cl.load_config()
580 config = cl.load_config()
580 return config
581 return config
581
582
582
583
583 def launch_new_instance():
584 def launch_new_instance():
584 """Create and run a full blown IPython instance"""
585 """Create and run a full blown IPython instance"""
585 app = IPythonApp()
586 app = IPythonApp()
586 app.start()
587 app.start()
587
General Comments 0
You need to be logged in to leave comments. Login now