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