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