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