##// END OF EJS Templates
Actually warn that `ipython <subcommand>` is deprecated....
Matthias Bussonnier -
Show More
@@ -1,397 +1,407 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 An application for IPython.
3 An application for IPython.
4
4
5 All top-level applications should use the classes in this module for
5 All top-level applications should use the classes in this module for
6 handling configuration and creating configurables.
6 handling configuration and creating configurables.
7
7
8 The job of an :class:`Application` is to create the master configuration
8 The job of an :class:`Application` is to create the master configuration
9 object and then create the configurable objects, passing the config to them.
9 object and then create the configurable objects, passing the config to them.
10 """
10 """
11
11
12 # Copyright (c) IPython Development Team.
12 # Copyright (c) IPython Development Team.
13 # Distributed under the terms of the Modified BSD License.
13 # Distributed under the terms of the Modified BSD License.
14
14
15 import atexit
15 import atexit
16 import glob
16 import glob
17 import logging
17 import logging
18 import os
18 import os
19 import shutil
19 import shutil
20 import sys
20 import sys
21
21
22 from traitlets.config.application import Application, catch_config_error
22 from traitlets.config.application import Application, catch_config_error
23 from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader
23 from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader
24 from IPython.core import release, crashhandler
24 from IPython.core import release, crashhandler
25 from IPython.core.profiledir import ProfileDir, ProfileDirError
25 from IPython.core.profiledir import ProfileDir, ProfileDirError
26 from IPython.paths import get_ipython_dir, get_ipython_package_dir
26 from IPython.paths import get_ipython_dir, get_ipython_package_dir
27 from IPython.utils.path import ensure_dir_exists
27 from IPython.utils.path import ensure_dir_exists
28 from IPython.utils import py3compat
28 from IPython.utils import py3compat
29 from traitlets import List, Unicode, Type, Bool, Dict, Set, Instance, Undefined
29 from traitlets import List, Unicode, Type, Bool, Dict, Set, Instance, Undefined
30
30
31 if os.name == 'nt':
31 if os.name == 'nt':
32 programdata = os.environ.get('PROGRAMDATA', None)
32 programdata = os.environ.get('PROGRAMDATA', None)
33 if programdata:
33 if programdata:
34 SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
34 SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
35 else: # PROGRAMDATA is not defined by default on XP.
35 else: # PROGRAMDATA is not defined by default on XP.
36 SYSTEM_CONFIG_DIRS = []
36 SYSTEM_CONFIG_DIRS = []
37 else:
37 else:
38 SYSTEM_CONFIG_DIRS = [
38 SYSTEM_CONFIG_DIRS = [
39 "/usr/local/etc/ipython",
39 "/usr/local/etc/ipython",
40 "/etc/ipython",
40 "/etc/ipython",
41 ]
41 ]
42
42
43
43
44 # aliases and flags
44 # aliases and flags
45
45
46 base_aliases = {
46 base_aliases = {
47 'profile-dir' : 'ProfileDir.location',
47 'profile-dir' : 'ProfileDir.location',
48 'profile' : 'BaseIPythonApplication.profile',
48 'profile' : 'BaseIPythonApplication.profile',
49 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
49 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
50 'log-level' : 'Application.log_level',
50 'log-level' : 'Application.log_level',
51 'config' : 'BaseIPythonApplication.extra_config_file',
51 'config' : 'BaseIPythonApplication.extra_config_file',
52 }
52 }
53
53
54 base_flags = dict(
54 base_flags = dict(
55 debug = ({'Application' : {'log_level' : logging.DEBUG}},
55 debug = ({'Application' : {'log_level' : logging.DEBUG}},
56 "set log level to logging.DEBUG (maximize logging output)"),
56 "set log level to logging.DEBUG (maximize logging output)"),
57 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
57 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
58 "set log level to logging.CRITICAL (minimize logging output)"),
58 "set log level to logging.CRITICAL (minimize logging output)"),
59 init = ({'BaseIPythonApplication' : {
59 init = ({'BaseIPythonApplication' : {
60 'copy_config_files' : True,
60 'copy_config_files' : True,
61 'auto_create' : True}
61 'auto_create' : True}
62 }, """Initialize profile with default config files. This is equivalent
62 }, """Initialize profile with default config files. This is equivalent
63 to running `ipython profile create <profile>` prior to startup.
63 to running `ipython profile create <profile>` prior to startup.
64 """)
64 """)
65 )
65 )
66
66
67 class ProfileAwareConfigLoader(PyFileConfigLoader):
67 class ProfileAwareConfigLoader(PyFileConfigLoader):
68 """A Python file config loader that is aware of IPython profiles."""
68 """A Python file config loader that is aware of IPython profiles."""
69 def load_subconfig(self, fname, path=None, profile=None):
69 def load_subconfig(self, fname, path=None, profile=None):
70 if profile is not None:
70 if profile is not None:
71 try:
71 try:
72 profile_dir = ProfileDir.find_profile_dir_by_name(
72 profile_dir = ProfileDir.find_profile_dir_by_name(
73 get_ipython_dir(),
73 get_ipython_dir(),
74 profile,
74 profile,
75 )
75 )
76 except ProfileDirError:
76 except ProfileDirError:
77 return
77 return
78 path = profile_dir.location
78 path = profile_dir.location
79 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
79 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
80
80
81 class BaseIPythonApplication(Application):
81 class BaseIPythonApplication(Application):
82
82
83 name = Unicode(u'ipython')
83 name = Unicode(u'ipython')
84 description = Unicode(u'IPython: an enhanced interactive Python shell.')
84 description = Unicode(u'IPython: an enhanced interactive Python shell.')
85 version = Unicode(release.version)
85 version = Unicode(release.version)
86
86
87 aliases = Dict(base_aliases)
87 aliases = Dict(base_aliases)
88 flags = Dict(base_flags)
88 flags = Dict(base_flags)
89 classes = List([ProfileDir])
89 classes = List([ProfileDir])
90
90
91 # enable `load_subconfig('cfg.py', profile='name')`
91 # enable `load_subconfig('cfg.py', profile='name')`
92 python_config_loader_class = ProfileAwareConfigLoader
92 python_config_loader_class = ProfileAwareConfigLoader
93
93
94 # Track whether the config_file has changed,
94 # Track whether the config_file has changed,
95 # because some logic happens only if we aren't using the default.
95 # because some logic happens only if we aren't using the default.
96 config_file_specified = Set()
96 config_file_specified = Set()
97
97
98 config_file_name = Unicode()
98 config_file_name = Unicode()
99 def _config_file_name_default(self):
99 def _config_file_name_default(self):
100 return self.name.replace('-','_') + u'_config.py'
100 return self.name.replace('-','_') + u'_config.py'
101 def _config_file_name_changed(self, name, old, new):
101 def _config_file_name_changed(self, name, old, new):
102 if new != old:
102 if new != old:
103 self.config_file_specified.add(new)
103 self.config_file_specified.add(new)
104
104
105 # The directory that contains IPython's builtin profiles.
105 # The directory that contains IPython's builtin profiles.
106 builtin_profile_dir = Unicode(
106 builtin_profile_dir = Unicode(
107 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
107 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
108 )
108 )
109
109
110 config_file_paths = List(Unicode())
110 config_file_paths = List(Unicode())
111 def _config_file_paths_default(self):
111 def _config_file_paths_default(self):
112 return [py3compat.getcwd()]
112 return [py3compat.getcwd()]
113
113
114 extra_config_file = Unicode(config=True,
114 extra_config_file = Unicode(config=True,
115 help="""Path to an extra config file to load.
115 help="""Path to an extra config file to load.
116
116
117 If specified, load this config file in addition to any other IPython config.
117 If specified, load this config file in addition to any other IPython config.
118 """)
118 """)
119 def _extra_config_file_changed(self, name, old, new):
119 def _extra_config_file_changed(self, name, old, new):
120 try:
120 try:
121 self.config_files.remove(old)
121 self.config_files.remove(old)
122 except ValueError:
122 except ValueError:
123 pass
123 pass
124 self.config_file_specified.add(new)
124 self.config_file_specified.add(new)
125 self.config_files.append(new)
125 self.config_files.append(new)
126
126
127 profile = Unicode(u'default', config=True,
127 profile = Unicode(u'default', config=True,
128 help="""The IPython profile to use."""
128 help="""The IPython profile to use."""
129 )
129 )
130
130
131 def _profile_changed(self, name, old, new):
131 def _profile_changed(self, name, old, new):
132 self.builtin_profile_dir = os.path.join(
132 self.builtin_profile_dir = os.path.join(
133 get_ipython_package_dir(), u'config', u'profile', new
133 get_ipython_package_dir(), u'config', u'profile', new
134 )
134 )
135
135
136 ipython_dir = Unicode(config=True,
136 ipython_dir = Unicode(config=True,
137 help="""
137 help="""
138 The name of the IPython directory. This directory is used for logging
138 The name of the IPython directory. This directory is used for logging
139 configuration (through profiles), history storage, etc. The default
139 configuration (through profiles), history storage, etc. The default
140 is usually $HOME/.ipython. This option can also be specified through
140 is usually $HOME/.ipython. This option can also be specified through
141 the environment variable IPYTHONDIR.
141 the environment variable IPYTHONDIR.
142 """
142 """
143 )
143 )
144 def _ipython_dir_default(self):
144 def _ipython_dir_default(self):
145 d = get_ipython_dir()
145 d = get_ipython_dir()
146 self._ipython_dir_changed('ipython_dir', d, d)
146 self._ipython_dir_changed('ipython_dir', d, d)
147 return d
147 return d
148
148
149 _in_init_profile_dir = False
149 _in_init_profile_dir = False
150 profile_dir = Instance(ProfileDir, allow_none=True)
150 profile_dir = Instance(ProfileDir, allow_none=True)
151 def _profile_dir_default(self):
151 def _profile_dir_default(self):
152 # avoid recursion
152 # avoid recursion
153 if self._in_init_profile_dir:
153 if self._in_init_profile_dir:
154 return
154 return
155 # profile_dir requested early, force initialization
155 # profile_dir requested early, force initialization
156 self.init_profile_dir()
156 self.init_profile_dir()
157 return self.profile_dir
157 return self.profile_dir
158
158
159 overwrite = Bool(False, config=True,
159 overwrite = Bool(False, config=True,
160 help="""Whether to overwrite existing config files when copying""")
160 help="""Whether to overwrite existing config files when copying""")
161 auto_create = Bool(False, config=True,
161 auto_create = Bool(False, config=True,
162 help="""Whether to create profile dir if it doesn't exist""")
162 help="""Whether to create profile dir if it doesn't exist""")
163
163
164 config_files = List(Unicode())
164 config_files = List(Unicode())
165 def _config_files_default(self):
165 def _config_files_default(self):
166 return [self.config_file_name]
166 return [self.config_file_name]
167
167
168 copy_config_files = Bool(False, config=True,
168 copy_config_files = Bool(False, config=True,
169 help="""Whether to install the default config files into the profile dir.
169 help="""Whether to install the default config files into the profile dir.
170 If a new profile is being created, and IPython contains config files for that
170 If a new profile is being created, and IPython contains config files for that
171 profile, then they will be staged into the new directory. Otherwise,
171 profile, then they will be staged into the new directory. Otherwise,
172 default config files will be automatically generated.
172 default config files will be automatically generated.
173 """)
173 """)
174
174
175 verbose_crash = Bool(False, config=True,
175 verbose_crash = Bool(False, config=True,
176 help="""Create a massive crash report when IPython encounters what may be an
176 help="""Create a massive crash report when IPython encounters what may be an
177 internal error. The default is to append a short message to the
177 internal error. The default is to append a short message to the
178 usual traceback""")
178 usual traceback""")
179
179
180 # The class to use as the crash handler.
180 # The class to use as the crash handler.
181 crash_handler_class = Type(crashhandler.CrashHandler)
181 crash_handler_class = Type(crashhandler.CrashHandler)
182
182
183 @catch_config_error
183 @catch_config_error
184 def __init__(self, **kwargs):
184 def __init__(self, **kwargs):
185 super(BaseIPythonApplication, self).__init__(**kwargs)
185 super(BaseIPythonApplication, self).__init__(**kwargs)
186 # ensure current working directory exists
186 # ensure current working directory exists
187 try:
187 try:
188 directory = py3compat.getcwd()
188 py3compat.getcwd()
189 except:
189 except:
190 # exit if cwd doesn't exist
190 # exit if cwd doesn't exist
191 self.log.error("Current working directory doesn't exist.")
191 self.log.error("Current working directory doesn't exist.")
192 self.exit(1)
192 self.exit(1)
193
193
194 #-------------------------------------------------------------------------
194 #-------------------------------------------------------------------------
195 # Various stages of Application creation
195 # Various stages of Application creation
196 #-------------------------------------------------------------------------
196 #-------------------------------------------------------------------------
197
197
198 def initialize_subcommand(self, subc, argv=None):
199 if subc in self.deprecated_subcommands:
200 import time
201 self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed "
202 "in future versions.".format(sub=subc))
203 self.log.warning("You likely want to use `jupyter {sub}`... continue "
204 "in 5 sec".format(sub=subc))
205 time.sleep(5)
206 return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv)
207
198 def init_crash_handler(self):
208 def init_crash_handler(self):
199 """Create a crash handler, typically setting sys.excepthook to it."""
209 """Create a crash handler, typically setting sys.excepthook to it."""
200 self.crash_handler = self.crash_handler_class(self)
210 self.crash_handler = self.crash_handler_class(self)
201 sys.excepthook = self.excepthook
211 sys.excepthook = self.excepthook
202 def unset_crashhandler():
212 def unset_crashhandler():
203 sys.excepthook = sys.__excepthook__
213 sys.excepthook = sys.__excepthook__
204 atexit.register(unset_crashhandler)
214 atexit.register(unset_crashhandler)
205
215
206 def excepthook(self, etype, evalue, tb):
216 def excepthook(self, etype, evalue, tb):
207 """this is sys.excepthook after init_crashhandler
217 """this is sys.excepthook after init_crashhandler
208
218
209 set self.verbose_crash=True to use our full crashhandler, instead of
219 set self.verbose_crash=True to use our full crashhandler, instead of
210 a regular traceback with a short message (crash_handler_lite)
220 a regular traceback with a short message (crash_handler_lite)
211 """
221 """
212
222
213 if self.verbose_crash:
223 if self.verbose_crash:
214 return self.crash_handler(etype, evalue, tb)
224 return self.crash_handler(etype, evalue, tb)
215 else:
225 else:
216 return crashhandler.crash_handler_lite(etype, evalue, tb)
226 return crashhandler.crash_handler_lite(etype, evalue, tb)
217
227
218 def _ipython_dir_changed(self, name, old, new):
228 def _ipython_dir_changed(self, name, old, new):
219 if old is not Undefined:
229 if old is not Undefined:
220 str_old = py3compat.cast_bytes_py2(os.path.abspath(old),
230 str_old = py3compat.cast_bytes_py2(os.path.abspath(old),
221 sys.getfilesystemencoding()
231 sys.getfilesystemencoding()
222 )
232 )
223 if str_old in sys.path:
233 if str_old in sys.path:
224 sys.path.remove(str_old)
234 sys.path.remove(str_old)
225 str_path = py3compat.cast_bytes_py2(os.path.abspath(new),
235 str_path = py3compat.cast_bytes_py2(os.path.abspath(new),
226 sys.getfilesystemencoding()
236 sys.getfilesystemencoding()
227 )
237 )
228 sys.path.append(str_path)
238 sys.path.append(str_path)
229 ensure_dir_exists(new)
239 ensure_dir_exists(new)
230 readme = os.path.join(new, 'README')
240 readme = os.path.join(new, 'README')
231 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
241 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
232 if not os.path.exists(readme) and os.path.exists(readme_src):
242 if not os.path.exists(readme) and os.path.exists(readme_src):
233 shutil.copy(readme_src, readme)
243 shutil.copy(readme_src, readme)
234 for d in ('extensions', 'nbextensions'):
244 for d in ('extensions', 'nbextensions'):
235 path = os.path.join(new, d)
245 path = os.path.join(new, d)
236 try:
246 try:
237 ensure_dir_exists(path)
247 ensure_dir_exists(path)
238 except OSError as e:
248 except OSError as e:
239 # this will not be EEXIST
249 # this will not be EEXIST
240 self.log.error("couldn't create path %s: %s", path, e)
250 self.log.error("couldn't create path %s: %s", path, e)
241 self.log.debug("IPYTHONDIR set to: %s" % new)
251 self.log.debug("IPYTHONDIR set to: %s" % new)
242
252
243 def load_config_file(self, suppress_errors=True):
253 def load_config_file(self, suppress_errors=True):
244 """Load the config file.
254 """Load the config file.
245
255
246 By default, errors in loading config are handled, and a warning
256 By default, errors in loading config are handled, and a warning
247 printed on screen. For testing, the suppress_errors option is set
257 printed on screen. For testing, the suppress_errors option is set
248 to False, so errors will make tests fail.
258 to False, so errors will make tests fail.
249 """
259 """
250 self.log.debug("Searching path %s for config files", self.config_file_paths)
260 self.log.debug("Searching path %s for config files", self.config_file_paths)
251 base_config = 'ipython_config.py'
261 base_config = 'ipython_config.py'
252 self.log.debug("Attempting to load config file: %s" %
262 self.log.debug("Attempting to load config file: %s" %
253 base_config)
263 base_config)
254 try:
264 try:
255 Application.load_config_file(
265 Application.load_config_file(
256 self,
266 self,
257 base_config,
267 base_config,
258 path=self.config_file_paths
268 path=self.config_file_paths
259 )
269 )
260 except ConfigFileNotFound:
270 except ConfigFileNotFound:
261 # ignore errors loading parent
271 # ignore errors loading parent
262 self.log.debug("Config file %s not found", base_config)
272 self.log.debug("Config file %s not found", base_config)
263 pass
273 pass
264
274
265 for config_file_name in self.config_files:
275 for config_file_name in self.config_files:
266 if not config_file_name or config_file_name == base_config:
276 if not config_file_name or config_file_name == base_config:
267 continue
277 continue
268 self.log.debug("Attempting to load config file: %s" %
278 self.log.debug("Attempting to load config file: %s" %
269 self.config_file_name)
279 self.config_file_name)
270 try:
280 try:
271 Application.load_config_file(
281 Application.load_config_file(
272 self,
282 self,
273 config_file_name,
283 config_file_name,
274 path=self.config_file_paths
284 path=self.config_file_paths
275 )
285 )
276 except ConfigFileNotFound:
286 except ConfigFileNotFound:
277 # Only warn if the default config file was NOT being used.
287 # Only warn if the default config file was NOT being used.
278 if config_file_name in self.config_file_specified:
288 if config_file_name in self.config_file_specified:
279 msg = self.log.warn
289 msg = self.log.warn
280 else:
290 else:
281 msg = self.log.debug
291 msg = self.log.debug
282 msg("Config file not found, skipping: %s", config_file_name)
292 msg("Config file not found, skipping: %s", config_file_name)
283 except Exception:
293 except Exception:
284 # For testing purposes.
294 # For testing purposes.
285 if not suppress_errors:
295 if not suppress_errors:
286 raise
296 raise
287 self.log.warn("Error loading config file: %s" %
297 self.log.warn("Error loading config file: %s" %
288 self.config_file_name, exc_info=True)
298 self.config_file_name, exc_info=True)
289
299
290 def init_profile_dir(self):
300 def init_profile_dir(self):
291 """initialize the profile dir"""
301 """initialize the profile dir"""
292 self._in_init_profile_dir = True
302 self._in_init_profile_dir = True
293 if self.profile_dir is not None:
303 if self.profile_dir is not None:
294 # already ran
304 # already ran
295 return
305 return
296 if 'ProfileDir.location' not in self.config:
306 if 'ProfileDir.location' not in self.config:
297 # location not specified, find by profile name
307 # location not specified, find by profile name
298 try:
308 try:
299 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
309 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
300 except ProfileDirError:
310 except ProfileDirError:
301 # not found, maybe create it (always create default profile)
311 # not found, maybe create it (always create default profile)
302 if self.auto_create or self.profile == 'default':
312 if self.auto_create or self.profile == 'default':
303 try:
313 try:
304 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
314 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
305 except ProfileDirError:
315 except ProfileDirError:
306 self.log.fatal("Could not create profile: %r"%self.profile)
316 self.log.fatal("Could not create profile: %r"%self.profile)
307 self.exit(1)
317 self.exit(1)
308 else:
318 else:
309 self.log.info("Created profile dir: %r"%p.location)
319 self.log.info("Created profile dir: %r"%p.location)
310 else:
320 else:
311 self.log.fatal("Profile %r not found."%self.profile)
321 self.log.fatal("Profile %r not found."%self.profile)
312 self.exit(1)
322 self.exit(1)
313 else:
323 else:
314 self.log.debug("Using existing profile dir: %r"%p.location)
324 self.log.debug("Using existing profile dir: %r"%p.location)
315 else:
325 else:
316 location = self.config.ProfileDir.location
326 location = self.config.ProfileDir.location
317 # location is fully specified
327 # location is fully specified
318 try:
328 try:
319 p = ProfileDir.find_profile_dir(location, self.config)
329 p = ProfileDir.find_profile_dir(location, self.config)
320 except ProfileDirError:
330 except ProfileDirError:
321 # not found, maybe create it
331 # not found, maybe create it
322 if self.auto_create:
332 if self.auto_create:
323 try:
333 try:
324 p = ProfileDir.create_profile_dir(location, self.config)
334 p = ProfileDir.create_profile_dir(location, self.config)
325 except ProfileDirError:
335 except ProfileDirError:
326 self.log.fatal("Could not create profile directory: %r"%location)
336 self.log.fatal("Could not create profile directory: %r"%location)
327 self.exit(1)
337 self.exit(1)
328 else:
338 else:
329 self.log.debug("Creating new profile dir: %r"%location)
339 self.log.debug("Creating new profile dir: %r"%location)
330 else:
340 else:
331 self.log.fatal("Profile directory %r not found."%location)
341 self.log.fatal("Profile directory %r not found."%location)
332 self.exit(1)
342 self.exit(1)
333 else:
343 else:
334 self.log.info("Using existing profile dir: %r"%location)
344 self.log.info("Using existing profile dir: %r"%location)
335 # if profile_dir is specified explicitly, set profile name
345 # if profile_dir is specified explicitly, set profile name
336 dir_name = os.path.basename(p.location)
346 dir_name = os.path.basename(p.location)
337 if dir_name.startswith('profile_'):
347 if dir_name.startswith('profile_'):
338 self.profile = dir_name[8:]
348 self.profile = dir_name[8:]
339
349
340 self.profile_dir = p
350 self.profile_dir = p
341 self.config_file_paths.append(p.location)
351 self.config_file_paths.append(p.location)
342 self._in_init_profile_dir = False
352 self._in_init_profile_dir = False
343
353
344 def init_config_files(self):
354 def init_config_files(self):
345 """[optionally] copy default config files into profile dir."""
355 """[optionally] copy default config files into profile dir."""
346 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
356 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
347 # copy config files
357 # copy config files
348 path = self.builtin_profile_dir
358 path = self.builtin_profile_dir
349 if self.copy_config_files:
359 if self.copy_config_files:
350 src = self.profile
360 src = self.profile
351
361
352 cfg = self.config_file_name
362 cfg = self.config_file_name
353 if path and os.path.exists(os.path.join(path, cfg)):
363 if path and os.path.exists(os.path.join(path, cfg)):
354 self.log.warn("Staging %r from %s into %r [overwrite=%s]"%(
364 self.log.warn("Staging %r from %s into %r [overwrite=%s]"%(
355 cfg, src, self.profile_dir.location, self.overwrite)
365 cfg, src, self.profile_dir.location, self.overwrite)
356 )
366 )
357 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
367 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
358 else:
368 else:
359 self.stage_default_config_file()
369 self.stage_default_config_file()
360 else:
370 else:
361 # Still stage *bundled* config files, but not generated ones
371 # Still stage *bundled* config files, but not generated ones
362 # This is necessary for `ipython profile=sympy` to load the profile
372 # This is necessary for `ipython profile=sympy` to load the profile
363 # on the first go
373 # on the first go
364 files = glob.glob(os.path.join(path, '*.py'))
374 files = glob.glob(os.path.join(path, '*.py'))
365 for fullpath in files:
375 for fullpath in files:
366 cfg = os.path.basename(fullpath)
376 cfg = os.path.basename(fullpath)
367 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
377 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
368 # file was copied
378 # file was copied
369 self.log.warn("Staging bundled %s from %s into %r"%(
379 self.log.warn("Staging bundled %s from %s into %r"%(
370 cfg, self.profile, self.profile_dir.location)
380 cfg, self.profile, self.profile_dir.location)
371 )
381 )
372
382
373
383
374 def stage_default_config_file(self):
384 def stage_default_config_file(self):
375 """auto generate default config file, and stage it into the profile."""
385 """auto generate default config file, and stage it into the profile."""
376 s = self.generate_config_file()
386 s = self.generate_config_file()
377 fname = os.path.join(self.profile_dir.location, self.config_file_name)
387 fname = os.path.join(self.profile_dir.location, self.config_file_name)
378 if self.overwrite or not os.path.exists(fname):
388 if self.overwrite or not os.path.exists(fname):
379 self.log.warn("Generating default config file: %r"%(fname))
389 self.log.warn("Generating default config file: %r"%(fname))
380 with open(fname, 'w') as f:
390 with open(fname, 'w') as f:
381 f.write(s)
391 f.write(s)
382
392
383 @catch_config_error
393 @catch_config_error
384 def initialize(self, argv=None):
394 def initialize(self, argv=None):
385 # don't hook up crash handler before parsing command-line
395 # don't hook up crash handler before parsing command-line
386 self.parse_command_line(argv)
396 self.parse_command_line(argv)
387 self.init_crash_handler()
397 self.init_crash_handler()
388 if self.subapp is not None:
398 if self.subapp is not None:
389 # stop here if subapp is taking over
399 # stop here if subapp is taking over
390 return
400 return
391 cl_config = self.config
401 cl_config = self.config
392 self.init_profile_dir()
402 self.init_profile_dir()
393 self.init_config_files()
403 self.init_config_files()
394 self.load_config_file()
404 self.load_config_file()
395 # enforce cl-opts override configfile opts:
405 # enforce cl-opts override configfile opts:
396 self.update_config(cl_config)
406 self.update_config(cl_config)
397
407
@@ -1,377 +1,369 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
7
8 # Copyright (c) IPython Development Team.
8 # Copyright (c) IPython Development Team.
9 # Distributed under the terms of the Modified BSD License.
9 # Distributed under the terms of the Modified BSD License.
10
10
11 from __future__ import absolute_import
11 from __future__ import absolute_import
12 from __future__ import print_function
12 from __future__ import print_function
13
13
14 import logging
14 import logging
15 import os
15 import os
16 import sys
16 import sys
17
17
18 from traitlets.config.loader import Config
18 from traitlets.config.loader import Config
19 from traitlets.config.application import boolean_flag, catch_config_error, Application
19 from traitlets.config.application import boolean_flag, catch_config_error, Application
20 from IPython.core import release
20 from IPython.core import release
21 from IPython.core import usage
21 from IPython.core import usage
22 from IPython.core.completer import IPCompleter
22 from IPython.core.completer import IPCompleter
23 from IPython.core.crashhandler import CrashHandler
23 from IPython.core.crashhandler import CrashHandler
24 from IPython.core.formatters import PlainTextFormatter
24 from IPython.core.formatters import PlainTextFormatter
25 from IPython.core.history import HistoryManager
25 from IPython.core.history import HistoryManager
26 from IPython.core.prompts import PromptManager
26 from IPython.core.prompts import PromptManager
27 from IPython.core.application import (
27 from IPython.core.application import (
28 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
28 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
29 )
29 )
30 from IPython.core.magics import ScriptMagics
30 from IPython.core.magics import ScriptMagics
31 from IPython.core.shellapp import (
31 from IPython.core.shellapp import (
32 InteractiveShellApp, shell_flags, shell_aliases
32 InteractiveShellApp, shell_flags, shell_aliases
33 )
33 )
34 from IPython.extensions.storemagic import StoreMagics
34 from IPython.extensions.storemagic import StoreMagics
35 from IPython.terminal.interactiveshell import TerminalInteractiveShell
35 from IPython.terminal.interactiveshell import TerminalInteractiveShell
36 from IPython.utils import warn
36 from IPython.utils import warn
37 from IPython.paths import get_ipython_dir
37 from IPython.paths import get_ipython_dir
38 from traitlets import (
38 from traitlets import (
39 Bool, List, Dict,
39 Bool, List, Dict,
40 )
40 )
41
41
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43 # Globals, utilities and helpers
43 # Globals, utilities and helpers
44 #-----------------------------------------------------------------------------
44 #-----------------------------------------------------------------------------
45
45
46 _examples = """
46 _examples = """
47 ipython --matplotlib # enable matplotlib integration
47 ipython --matplotlib # enable matplotlib integration
48 ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
48 ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
49
49
50 ipython --log-level=DEBUG # set logging to DEBUG
50 ipython --log-level=DEBUG # set logging to DEBUG
51 ipython --profile=foo # start with profile foo
51 ipython --profile=foo # start with profile foo
52
52
53 ipython qtconsole # start the qtconsole GUI application
54 ipython help qtconsole # show the help for the qtconsole subcmd
55
56 ipython console # start the terminal-based console application
57 ipython help console # show the help for the console subcmd
58
59 ipython notebook # start the IPython notebook
60 ipython help notebook # show the help for the notebook subcmd
61
62 ipython profile create foo # create profile foo w/ default config files
53 ipython profile create foo # create profile foo w/ default config files
63 ipython help profile # show the help for the profile subcmd
54 ipython help profile # show the help for the profile subcmd
64
55
65 ipython locate # print the path to the IPython directory
56 ipython locate # print the path to the IPython directory
66 ipython locate profile foo # print the path to the directory for profile `foo`
57 ipython locate profile foo # print the path to the directory for profile `foo`
67
68 ipython nbconvert # convert notebooks to/from other formats
69 """
58 """
70
59
71 #-----------------------------------------------------------------------------
60 #-----------------------------------------------------------------------------
72 # Crash handler for this application
61 # Crash handler for this application
73 #-----------------------------------------------------------------------------
62 #-----------------------------------------------------------------------------
74
63
75 class IPAppCrashHandler(CrashHandler):
64 class IPAppCrashHandler(CrashHandler):
76 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
65 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
77
66
78 def __init__(self, app):
67 def __init__(self, app):
79 contact_name = release.author
68 contact_name = release.author
80 contact_email = release.author_email
69 contact_email = release.author_email
81 bug_tracker = 'https://github.com/ipython/ipython/issues'
70 bug_tracker = 'https://github.com/ipython/ipython/issues'
82 super(IPAppCrashHandler,self).__init__(
71 super(IPAppCrashHandler,self).__init__(
83 app, contact_name, contact_email, bug_tracker
72 app, contact_name, contact_email, bug_tracker
84 )
73 )
85
74
86 def make_report(self,traceback):
75 def make_report(self,traceback):
87 """Return a string containing a crash report."""
76 """Return a string containing a crash report."""
88
77
89 sec_sep = self.section_sep
78 sec_sep = self.section_sep
90 # Start with parent report
79 # Start with parent report
91 report = [super(IPAppCrashHandler, self).make_report(traceback)]
80 report = [super(IPAppCrashHandler, self).make_report(traceback)]
92 # Add interactive-specific info we may have
81 # Add interactive-specific info we may have
93 rpt_add = report.append
82 rpt_add = report.append
94 try:
83 try:
95 rpt_add(sec_sep+"History of session input:")
84 rpt_add(sec_sep+"History of session input:")
96 for line in self.app.shell.user_ns['_ih']:
85 for line in self.app.shell.user_ns['_ih']:
97 rpt_add(line)
86 rpt_add(line)
98 rpt_add('\n*** Last line of input (may not be in above history):\n')
87 rpt_add('\n*** Last line of input (may not be in above history):\n')
99 rpt_add(self.app.shell._last_input_line+'\n')
88 rpt_add(self.app.shell._last_input_line+'\n')
100 except:
89 except:
101 pass
90 pass
102
91
103 return ''.join(report)
92 return ''.join(report)
104
93
105 #-----------------------------------------------------------------------------
94 #-----------------------------------------------------------------------------
106 # Aliases and Flags
95 # Aliases and Flags
107 #-----------------------------------------------------------------------------
96 #-----------------------------------------------------------------------------
108 flags = dict(base_flags)
97 flags = dict(base_flags)
109 flags.update(shell_flags)
98 flags.update(shell_flags)
110 frontend_flags = {}
99 frontend_flags = {}
111 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
100 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
112 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
101 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
113 'Turn on auto editing of files with syntax errors.',
102 'Turn on auto editing of files with syntax errors.',
114 'Turn off auto editing of files with syntax errors.'
103 'Turn off auto editing of files with syntax errors.'
115 )
104 )
116 addflag('banner', 'TerminalIPythonApp.display_banner',
105 addflag('banner', 'TerminalIPythonApp.display_banner',
117 "Display a banner upon starting IPython.",
106 "Display a banner upon starting IPython.",
118 "Don't display a banner upon starting IPython."
107 "Don't display a banner upon starting IPython."
119 )
108 )
120 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
109 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
121 """Set to confirm when you try to exit IPython with an EOF (Control-D
110 """Set to confirm when you try to exit IPython with an EOF (Control-D
122 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
111 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
123 you can force a direct exit without any confirmation.""",
112 you can force a direct exit without any confirmation.""",
124 "Don't prompt the user when exiting."
113 "Don't prompt the user when exiting."
125 )
114 )
126 addflag('term-title', 'TerminalInteractiveShell.term_title',
115 addflag('term-title', 'TerminalInteractiveShell.term_title',
127 "Enable auto setting the terminal title.",
116 "Enable auto setting the terminal title.",
128 "Disable auto setting the terminal title."
117 "Disable auto setting the terminal title."
129 )
118 )
130 classic_config = Config()
119 classic_config = Config()
131 classic_config.InteractiveShell.cache_size = 0
120 classic_config.InteractiveShell.cache_size = 0
132 classic_config.PlainTextFormatter.pprint = False
121 classic_config.PlainTextFormatter.pprint = False
133 classic_config.PromptManager.in_template = '>>> '
122 classic_config.PromptManager.in_template = '>>> '
134 classic_config.PromptManager.in2_template = '... '
123 classic_config.PromptManager.in2_template = '... '
135 classic_config.PromptManager.out_template = ''
124 classic_config.PromptManager.out_template = ''
136 classic_config.InteractiveShell.separate_in = ''
125 classic_config.InteractiveShell.separate_in = ''
137 classic_config.InteractiveShell.separate_out = ''
126 classic_config.InteractiveShell.separate_out = ''
138 classic_config.InteractiveShell.separate_out2 = ''
127 classic_config.InteractiveShell.separate_out2 = ''
139 classic_config.InteractiveShell.colors = 'NoColor'
128 classic_config.InteractiveShell.colors = 'NoColor'
140 classic_config.InteractiveShell.xmode = 'Plain'
129 classic_config.InteractiveShell.xmode = 'Plain'
141
130
142 frontend_flags['classic']=(
131 frontend_flags['classic']=(
143 classic_config,
132 classic_config,
144 "Gives IPython a similar feel to the classic Python prompt."
133 "Gives IPython a similar feel to the classic Python prompt."
145 )
134 )
146 # # log doesn't make so much sense this way anymore
135 # # log doesn't make so much sense this way anymore
147 # paa('--log','-l',
136 # paa('--log','-l',
148 # action='store_true', dest='InteractiveShell.logstart',
137 # action='store_true', dest='InteractiveShell.logstart',
149 # help="Start logging to the default log file (./ipython_log.py).")
138 # help="Start logging to the default log file (./ipython_log.py).")
150 #
139 #
151 # # quick is harder to implement
140 # # quick is harder to implement
152 frontend_flags['quick']=(
141 frontend_flags['quick']=(
153 {'TerminalIPythonApp' : {'quick' : True}},
142 {'TerminalIPythonApp' : {'quick' : True}},
154 "Enable quick startup with no config files."
143 "Enable quick startup with no config files."
155 )
144 )
156
145
157 frontend_flags['i'] = (
146 frontend_flags['i'] = (
158 {'TerminalIPythonApp' : {'force_interact' : True}},
147 {'TerminalIPythonApp' : {'force_interact' : True}},
159 """If running code from the command line, become interactive afterwards.
148 """If running code from the command line, become interactive afterwards.
160 It is often useful to follow this with `--` to treat remaining flags as
149 It is often useful to follow this with `--` to treat remaining flags as
161 script arguments.
150 script arguments.
162 """
151 """
163 )
152 )
164 flags.update(frontend_flags)
153 flags.update(frontend_flags)
165
154
166 aliases = dict(base_aliases)
155 aliases = dict(base_aliases)
167 aliases.update(shell_aliases)
156 aliases.update(shell_aliases)
168
157
169 #-----------------------------------------------------------------------------
158 #-----------------------------------------------------------------------------
170 # Main classes and functions
159 # Main classes and functions
171 #-----------------------------------------------------------------------------
160 #-----------------------------------------------------------------------------
172
161
173
162
174 class LocateIPythonApp(BaseIPythonApplication):
163 class LocateIPythonApp(BaseIPythonApplication):
175 description = """print the path to the IPython dir"""
164 description = """print the path to the IPython dir"""
176 subcommands = Dict(dict(
165 subcommands = Dict(dict(
177 profile=('IPython.core.profileapp.ProfileLocate',
166 profile=('IPython.core.profileapp.ProfileLocate',
178 "print the path to an IPython profile directory",
167 "print the path to an IPython profile directory",
179 ),
168 ),
180 ))
169 ))
181 def start(self):
170 def start(self):
182 if self.subapp is not None:
171 if self.subapp is not None:
183 return self.subapp.start()
172 return self.subapp.start()
184 else:
173 else:
185 print(self.ipython_dir)
174 print(self.ipython_dir)
186
175
187
176
188 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
177 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
189 name = u'ipython'
178 name = u'ipython'
190 description = usage.cl_usage
179 description = usage.cl_usage
191 crash_handler_class = IPAppCrashHandler
180 crash_handler_class = IPAppCrashHandler
192 examples = _examples
181 examples = _examples
193
182
194 flags = Dict(flags)
183 flags = Dict(flags)
195 aliases = Dict(aliases)
184 aliases = Dict(aliases)
196 classes = List()
185 classes = List()
197 def _classes_default(self):
186 def _classes_default(self):
198 """This has to be in a method, for TerminalIPythonApp to be available."""
187 """This has to be in a method, for TerminalIPythonApp to be available."""
199 return [
188 return [
200 InteractiveShellApp, # ShellApp comes before TerminalApp, because
189 InteractiveShellApp, # ShellApp comes before TerminalApp, because
201 self.__class__, # it will also affect subclasses (e.g. QtConsole)
190 self.__class__, # it will also affect subclasses (e.g. QtConsole)
202 TerminalInteractiveShell,
191 TerminalInteractiveShell,
203 PromptManager,
192 PromptManager,
204 HistoryManager,
193 HistoryManager,
205 ProfileDir,
194 ProfileDir,
206 PlainTextFormatter,
195 PlainTextFormatter,
207 IPCompleter,
196 IPCompleter,
208 ScriptMagics,
197 ScriptMagics,
209 StoreMagics,
198 StoreMagics,
210 ]
199 ]
211
200
212 subcommands = dict(
201 deprecated_subcommands = dict(
213 qtconsole=('qtconsole.qtconsoleapp.JupyterQtConsoleApp',
202 qtconsole=('qtconsole.qtconsoleapp.JupyterQtConsoleApp',
214 """DEPRECATD: Launch the Jupyter Qt Console."""
203 """DEPRECATD: Launch the Jupyter Qt Console."""
215 ),
204 ),
216 notebook=('notebook.notebookapp.NotebookApp',
205 notebook=('notebook.notebookapp.NotebookApp',
217 """DEPRECATED: Launch the Jupyter HTML Notebook Server."""
206 """DEPRECATED: Launch the Jupyter HTML Notebook Server."""
218 ),
207 ),
219 profile = ("IPython.core.profileapp.ProfileApp",
220 "Create and manage IPython profiles."
221 ),
222 kernel = ("ipykernel.kernelapp.IPKernelApp",
223 "Start a kernel without an attached frontend."
224 ),
225 console=('jupyter_console.app.ZMQTerminalIPythonApp',
208 console=('jupyter_console.app.ZMQTerminalIPythonApp',
226 """DEPRECATED: Launch the Jupyter terminal-based Console."""
209 """DEPRECATED: Launch the Jupyter terminal-based Console."""
227 ),
210 ),
228 locate=('IPython.terminal.ipapp.LocateIPythonApp',
229 LocateIPythonApp.description
230 ),
231 history=('IPython.core.historyapp.HistoryApp',
232 "Manage the IPython history database."
233 ),
234 nbconvert=('nbconvert.nbconvertapp.NbConvertApp',
211 nbconvert=('nbconvert.nbconvertapp.NbConvertApp',
235 "DEPRECATED: Convert notebooks to/from other formats."
212 "DEPRECATED: Convert notebooks to/from other formats."
236 ),
213 ),
237 trust=('nbformat.sign.TrustNotebookApp',
214 trust=('nbformat.sign.TrustNotebookApp',
238 "DEPRECATED: Sign notebooks to trust their potentially unsafe contents at load."
215 "DEPRECATED: Sign notebooks to trust their potentially unsafe contents at load."
239 ),
216 ),
240 kernelspec=('jupyter_client.kernelspecapp.KernelSpecApp',
217 kernelspec=('jupyter_client.kernelspecapp.KernelSpecApp',
241 "DEPRECATED: Manage Jupyter kernel specifications."
218 "DEPRECATED: Manage Jupyter kernel specifications."
242 ),
219 ),
243 )
220 )
244 subcommands['install-nbextension'] = (
221 subcommands = dict(
222 profile = ("IPython.core.profileapp.ProfileApp",
223 "Create and manage IPython profiles."
224 ),
225 kernel = ("ipykernel.kernelapp.IPKernelApp",
226 "Start a kernel without an attached frontend."
227 ),
228 locate=('IPython.terminal.ipapp.LocateIPythonApp',
229 LocateIPythonApp.description
230 ),
231 history=('IPython.core.historyapp.HistoryApp',
232 "Manage the IPython history database."
233 ),
234 )
235 deprecated_subcommands['install-nbextension'] = (
245 "notebook.nbextensions.InstallNBExtensionApp",
236 "notebook.nbextensions.InstallNBExtensionApp",
246 "DEPRECATED: Install Jupyter notebook extension files"
237 "DEPRECATED: Install Jupyter notebook extension files"
247 )
238 )
239 subcommands.update(deprecated_subcommands)
248
240
249 # *do* autocreate requested profile, but don't create the config file.
241 # *do* autocreate requested profile, but don't create the config file.
250 auto_create=Bool(True)
242 auto_create=Bool(True)
251 # configurables
243 # configurables
252 quick = Bool(False, config=True,
244 quick = Bool(False, config=True,
253 help="""Start IPython quickly by skipping the loading of config files."""
245 help="""Start IPython quickly by skipping the loading of config files."""
254 )
246 )
255 def _quick_changed(self, name, old, new):
247 def _quick_changed(self, name, old, new):
256 if new:
248 if new:
257 self.load_config_file = lambda *a, **kw: None
249 self.load_config_file = lambda *a, **kw: None
258
250
259 display_banner = Bool(True, config=True,
251 display_banner = Bool(True, config=True,
260 help="Whether to display a banner upon starting IPython."
252 help="Whether to display a banner upon starting IPython."
261 )
253 )
262
254
263 # if there is code of files to run from the cmd line, don't interact
255 # if there is code of files to run from the cmd line, don't interact
264 # unless the --i flag (App.force_interact) is true.
256 # unless the --i flag (App.force_interact) is true.
265 force_interact = Bool(False, config=True,
257 force_interact = Bool(False, config=True,
266 help="""If a command or file is given via the command-line,
258 help="""If a command or file is given via the command-line,
267 e.g. 'ipython foo.py', start an interactive shell after executing the
259 e.g. 'ipython foo.py', start an interactive shell after executing the
268 file or command."""
260 file or command."""
269 )
261 )
270 def _force_interact_changed(self, name, old, new):
262 def _force_interact_changed(self, name, old, new):
271 if new:
263 if new:
272 self.interact = True
264 self.interact = True
273
265
274 def _file_to_run_changed(self, name, old, new):
266 def _file_to_run_changed(self, name, old, new):
275 if new:
267 if new:
276 self.something_to_run = True
268 self.something_to_run = True
277 if new and not self.force_interact:
269 if new and not self.force_interact:
278 self.interact = False
270 self.interact = False
279 _code_to_run_changed = _file_to_run_changed
271 _code_to_run_changed = _file_to_run_changed
280 _module_to_run_changed = _file_to_run_changed
272 _module_to_run_changed = _file_to_run_changed
281
273
282 # internal, not-configurable
274 # internal, not-configurable
283 interact=Bool(True)
275 interact=Bool(True)
284 something_to_run=Bool(False)
276 something_to_run=Bool(False)
285
277
286 def parse_command_line(self, argv=None):
278 def parse_command_line(self, argv=None):
287 """override to allow old '-pylab' flag with deprecation warning"""
279 """override to allow old '-pylab' flag with deprecation warning"""
288
280
289 argv = sys.argv[1:] if argv is None else argv
281 argv = sys.argv[1:] if argv is None else argv
290
282
291 if '-pylab' in argv:
283 if '-pylab' in argv:
292 # deprecated `-pylab` given,
284 # deprecated `-pylab` given,
293 # warn and transform into current syntax
285 # warn and transform into current syntax
294 argv = argv[:] # copy, don't clobber
286 argv = argv[:] # copy, don't clobber
295 idx = argv.index('-pylab')
287 idx = argv.index('-pylab')
296 warn.warn("`-pylab` flag has been deprecated.\n"
288 warn.warn("`-pylab` flag has been deprecated.\n"
297 " Use `--matplotlib <backend>` and import pylab manually.")
289 " Use `--matplotlib <backend>` and import pylab manually.")
298 argv[idx] = '--pylab'
290 argv[idx] = '--pylab'
299
291
300 return super(TerminalIPythonApp, self).parse_command_line(argv)
292 return super(TerminalIPythonApp, self).parse_command_line(argv)
301
293
302 @catch_config_error
294 @catch_config_error
303 def initialize(self, argv=None):
295 def initialize(self, argv=None):
304 """Do actions after construct, but before starting the app."""
296 """Do actions after construct, but before starting the app."""
305 super(TerminalIPythonApp, self).initialize(argv)
297 super(TerminalIPythonApp, self).initialize(argv)
306 if self.subapp is not None:
298 if self.subapp is not None:
307 # don't bother initializing further, starting subapp
299 # don't bother initializing further, starting subapp
308 return
300 return
309 # print self.extra_args
301 # print self.extra_args
310 if self.extra_args and not self.something_to_run:
302 if self.extra_args and not self.something_to_run:
311 self.file_to_run = self.extra_args[0]
303 self.file_to_run = self.extra_args[0]
312 self.init_path()
304 self.init_path()
313 # create the shell
305 # create the shell
314 self.init_shell()
306 self.init_shell()
315 # and draw the banner
307 # and draw the banner
316 self.init_banner()
308 self.init_banner()
317 # Now a variety of things that happen after the banner is printed.
309 # Now a variety of things that happen after the banner is printed.
318 self.init_gui_pylab()
310 self.init_gui_pylab()
319 self.init_extensions()
311 self.init_extensions()
320 self.init_code()
312 self.init_code()
321
313
322 def init_shell(self):
314 def init_shell(self):
323 """initialize the InteractiveShell instance"""
315 """initialize the InteractiveShell instance"""
324 # Create an InteractiveShell instance.
316 # Create an InteractiveShell instance.
325 # shell.display_banner should always be False for the terminal
317 # shell.display_banner should always be False for the terminal
326 # based app, because we call shell.show_banner() by hand below
318 # based app, because we call shell.show_banner() by hand below
327 # so the banner shows *before* all extension loading stuff.
319 # so the banner shows *before* all extension loading stuff.
328 self.shell = TerminalInteractiveShell.instance(parent=self,
320 self.shell = TerminalInteractiveShell.instance(parent=self,
329 display_banner=False, profile_dir=self.profile_dir,
321 display_banner=False, profile_dir=self.profile_dir,
330 ipython_dir=self.ipython_dir, user_ns=self.user_ns)
322 ipython_dir=self.ipython_dir, user_ns=self.user_ns)
331 self.shell.configurables.append(self)
323 self.shell.configurables.append(self)
332
324
333 def init_banner(self):
325 def init_banner(self):
334 """optionally display the banner"""
326 """optionally display the banner"""
335 if self.display_banner and self.interact:
327 if self.display_banner and self.interact:
336 self.shell.show_banner()
328 self.shell.show_banner()
337 # Make sure there is a space below the banner.
329 # Make sure there is a space below the banner.
338 if self.log_level <= logging.INFO: print()
330 if self.log_level <= logging.INFO: print()
339
331
340 def _pylab_changed(self, name, old, new):
332 def _pylab_changed(self, name, old, new):
341 """Replace --pylab='inline' with --pylab='auto'"""
333 """Replace --pylab='inline' with --pylab='auto'"""
342 if new == 'inline':
334 if new == 'inline':
343 warn.warn("'inline' not available as pylab backend, "
335 warn.warn("'inline' not available as pylab backend, "
344 "using 'auto' instead.")
336 "using 'auto' instead.")
345 self.pylab = 'auto'
337 self.pylab = 'auto'
346
338
347 def start(self):
339 def start(self):
348 if self.subapp is not None:
340 if self.subapp is not None:
349 return self.subapp.start()
341 return self.subapp.start()
350 # perform any prexec steps:
342 # perform any prexec steps:
351 if self.interact:
343 if self.interact:
352 self.log.debug("Starting IPython's mainloop...")
344 self.log.debug("Starting IPython's mainloop...")
353 self.shell.mainloop()
345 self.shell.mainloop()
354 else:
346 else:
355 self.log.debug("IPython not interactive...")
347 self.log.debug("IPython not interactive...")
356
348
357 def load_default_config(ipython_dir=None):
349 def load_default_config(ipython_dir=None):
358 """Load the default config file from the default ipython_dir.
350 """Load the default config file from the default ipython_dir.
359
351
360 This is useful for embedded shells.
352 This is useful for embedded shells.
361 """
353 """
362 if ipython_dir is None:
354 if ipython_dir is None:
363 ipython_dir = get_ipython_dir()
355 ipython_dir = get_ipython_dir()
364
356
365 profile_dir = os.path.join(ipython_dir, 'profile_default')
357 profile_dir = os.path.join(ipython_dir, 'profile_default')
366
358
367 config = Config()
359 config = Config()
368 for cf in Application._load_config_files("ipython_config", path=profile_dir):
360 for cf in Application._load_config_files("ipython_config", path=profile_dir):
369 config.update(cf)
361 config.update(cf)
370
362
371 return config
363 return config
372
364
373 launch_new_instance = TerminalIPythonApp.launch_instance
365 launch_new_instance = TerminalIPythonApp.launch_instance
374
366
375
367
376 if __name__ == '__main__':
368 if __name__ == '__main__':
377 launch_new_instance()
369 launch_new_instance()
General Comments 0
You need to be logged in to leave comments. Login now