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