##// END OF EJS Templates
remove also a bunch of %-format
Matthias Bussonnier -
Show More
@@ -1,488 +1,488 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 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 pathlib import Path
22 from pathlib import Path
23
23
24 from traitlets.config.application import Application, catch_config_error
24 from traitlets.config.application import Application, catch_config_error
25 from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader
25 from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader
26 from IPython.core import release, crashhandler
26 from IPython.core import release, crashhandler
27 from IPython.core.profiledir import ProfileDir, ProfileDirError
27 from IPython.core.profiledir import ProfileDir, ProfileDirError
28 from IPython.paths import get_ipython_dir, get_ipython_package_dir
28 from IPython.paths import get_ipython_dir, get_ipython_package_dir
29 from IPython.utils.path import ensure_dir_exists
29 from IPython.utils.path import ensure_dir_exists
30 from traitlets import (
30 from traitlets import (
31 List, Unicode, Type, Bool, Set, Instance, Undefined,
31 List, Unicode, Type, Bool, Set, Instance, Undefined,
32 default, observe,
32 default, observe,
33 )
33 )
34
34
35 if os.name == "nt":
35 if os.name == "nt":
36 programdata = os.environ.get("PROGRAMDATA", None)
36 programdata = os.environ.get("PROGRAMDATA", None)
37 if programdata is not None:
37 if programdata is not None:
38 SYSTEM_CONFIG_DIRS = [str(Path(programdata) / "ipython")]
38 SYSTEM_CONFIG_DIRS = [str(Path(programdata) / "ipython")]
39 else: # PROGRAMDATA is not defined by default on XP.
39 else: # PROGRAMDATA is not defined by default on XP.
40 SYSTEM_CONFIG_DIRS = []
40 SYSTEM_CONFIG_DIRS = []
41 else:
41 else:
42 SYSTEM_CONFIG_DIRS = [
42 SYSTEM_CONFIG_DIRS = [
43 "/usr/local/etc/ipython",
43 "/usr/local/etc/ipython",
44 "/etc/ipython",
44 "/etc/ipython",
45 ]
45 ]
46
46
47
47
48 ENV_CONFIG_DIRS = []
48 ENV_CONFIG_DIRS = []
49 _env_config_dir = os.path.join(sys.prefix, 'etc', 'ipython')
49 _env_config_dir = os.path.join(sys.prefix, 'etc', 'ipython')
50 if _env_config_dir not in SYSTEM_CONFIG_DIRS:
50 if _env_config_dir not in SYSTEM_CONFIG_DIRS:
51 # only add ENV_CONFIG if sys.prefix is not already included
51 # only add ENV_CONFIG if sys.prefix is not already included
52 ENV_CONFIG_DIRS.append(_env_config_dir)
52 ENV_CONFIG_DIRS.append(_env_config_dir)
53
53
54
54
55 _envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS')
55 _envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS')
56 if _envvar in {None, ''}:
56 if _envvar in {None, ''}:
57 IPYTHON_SUPPRESS_CONFIG_ERRORS = None
57 IPYTHON_SUPPRESS_CONFIG_ERRORS = None
58 else:
58 else:
59 if _envvar.lower() in {'1','true'}:
59 if _envvar.lower() in {'1','true'}:
60 IPYTHON_SUPPRESS_CONFIG_ERRORS = True
60 IPYTHON_SUPPRESS_CONFIG_ERRORS = True
61 elif _envvar.lower() in {'0','false'} :
61 elif _envvar.lower() in {'0','false'} :
62 IPYTHON_SUPPRESS_CONFIG_ERRORS = False
62 IPYTHON_SUPPRESS_CONFIG_ERRORS = False
63 else:
63 else:
64 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 sys.exit("Unsupported value for environment variable: 'IPYTHON_SUPPRESS_CONFIG_ERRORS' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar )
65
65
66 # aliases and flags
66 # aliases and flags
67
67
68 base_aliases = {}
68 base_aliases = {}
69 if isinstance(Application.aliases, dict):
69 if isinstance(Application.aliases, dict):
70 # traitlets 5
70 # traitlets 5
71 base_aliases.update(Application.aliases)
71 base_aliases.update(Application.aliases)
72 base_aliases.update(
72 base_aliases.update(
73 {
73 {
74 "profile-dir": "ProfileDir.location",
74 "profile-dir": "ProfileDir.location",
75 "profile": "BaseIPythonApplication.profile",
75 "profile": "BaseIPythonApplication.profile",
76 "ipython-dir": "BaseIPythonApplication.ipython_dir",
76 "ipython-dir": "BaseIPythonApplication.ipython_dir",
77 "log-level": "Application.log_level",
77 "log-level": "Application.log_level",
78 "config": "BaseIPythonApplication.extra_config_file",
78 "config": "BaseIPythonApplication.extra_config_file",
79 }
79 }
80 )
80 )
81
81
82 base_flags = dict()
82 base_flags = dict()
83 if isinstance(Application.flags, dict):
83 if isinstance(Application.flags, dict):
84 # traitlets 5
84 # traitlets 5
85 base_flags.update(Application.flags)
85 base_flags.update(Application.flags)
86 base_flags.update(
86 base_flags.update(
87 dict(
87 dict(
88 debug=(
88 debug=(
89 {"Application": {"log_level": logging.DEBUG}},
89 {"Application": {"log_level": logging.DEBUG}},
90 "set log level to logging.DEBUG (maximize logging output)",
90 "set log level to logging.DEBUG (maximize logging output)",
91 ),
91 ),
92 quiet=(
92 quiet=(
93 {"Application": {"log_level": logging.CRITICAL}},
93 {"Application": {"log_level": logging.CRITICAL}},
94 "set log level to logging.CRITICAL (minimize logging output)",
94 "set log level to logging.CRITICAL (minimize logging output)",
95 ),
95 ),
96 init=(
96 init=(
97 {
97 {
98 "BaseIPythonApplication": {
98 "BaseIPythonApplication": {
99 "copy_config_files": True,
99 "copy_config_files": True,
100 "auto_create": True,
100 "auto_create": True,
101 }
101 }
102 },
102 },
103 """Initialize profile with default config files. This is equivalent
103 """Initialize profile with default config files. This is equivalent
104 to running `ipython profile create <profile>` prior to startup.
104 to running `ipython profile create <profile>` prior to startup.
105 """,
105 """,
106 ),
106 ),
107 )
107 )
108 )
108 )
109
109
110
110
111 class ProfileAwareConfigLoader(PyFileConfigLoader):
111 class ProfileAwareConfigLoader(PyFileConfigLoader):
112 """A Python file config loader that is aware of IPython profiles."""
112 """A Python file config loader that is aware of IPython profiles."""
113 def load_subconfig(self, fname, path=None, profile=None):
113 def load_subconfig(self, fname, path=None, profile=None):
114 if profile is not None:
114 if profile is not None:
115 try:
115 try:
116 profile_dir = ProfileDir.find_profile_dir_by_name(
116 profile_dir = ProfileDir.find_profile_dir_by_name(
117 get_ipython_dir(),
117 get_ipython_dir(),
118 profile,
118 profile,
119 )
119 )
120 except ProfileDirError:
120 except ProfileDirError:
121 return
121 return
122 path = profile_dir.location
122 path = profile_dir.location
123 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
123 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
124
124
125 class BaseIPythonApplication(Application):
125 class BaseIPythonApplication(Application):
126 name = "ipython"
126 name = "ipython"
127 description = "IPython: an enhanced interactive Python shell."
127 description = "IPython: an enhanced interactive Python shell."
128 version = Unicode(release.version)
128 version = Unicode(release.version)
129
129
130 aliases = base_aliases
130 aliases = base_aliases
131 flags = base_flags
131 flags = base_flags
132 classes = List([ProfileDir])
132 classes = List([ProfileDir])
133
133
134 # enable `load_subconfig('cfg.py', profile='name')`
134 # enable `load_subconfig('cfg.py', profile='name')`
135 python_config_loader_class = ProfileAwareConfigLoader
135 python_config_loader_class = ProfileAwareConfigLoader
136
136
137 # Track whether the config_file has changed,
137 # Track whether the config_file has changed,
138 # because some logic happens only if we aren't using the default.
138 # because some logic happens only if we aren't using the default.
139 config_file_specified = Set()
139 config_file_specified = Set()
140
140
141 config_file_name = Unicode()
141 config_file_name = Unicode()
142 @default('config_file_name')
142 @default('config_file_name')
143 def _config_file_name_default(self):
143 def _config_file_name_default(self):
144 return self.name.replace('-','_') + u'_config.py'
144 return self.name.replace('-','_') + u'_config.py'
145 @observe('config_file_name')
145 @observe('config_file_name')
146 def _config_file_name_changed(self, change):
146 def _config_file_name_changed(self, change):
147 if change['new'] != change['old']:
147 if change['new'] != change['old']:
148 self.config_file_specified.add(change['new'])
148 self.config_file_specified.add(change['new'])
149
149
150 # The directory that contains IPython's builtin profiles.
150 # The directory that contains IPython's builtin profiles.
151 builtin_profile_dir = Unicode(
151 builtin_profile_dir = Unicode(
152 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
152 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
153 )
153 )
154
154
155 config_file_paths = List(Unicode())
155 config_file_paths = List(Unicode())
156 @default('config_file_paths')
156 @default('config_file_paths')
157 def _config_file_paths_default(self):
157 def _config_file_paths_default(self):
158 return []
158 return []
159
159
160 extra_config_file = Unicode(
160 extra_config_file = Unicode(
161 help="""Path to an extra config file to load.
161 help="""Path to an extra config file to load.
162
162
163 If specified, load this config file in addition to any other IPython config.
163 If specified, load this config file in addition to any other IPython config.
164 """).tag(config=True)
164 """).tag(config=True)
165 @observe('extra_config_file')
165 @observe('extra_config_file')
166 def _extra_config_file_changed(self, change):
166 def _extra_config_file_changed(self, change):
167 old = change['old']
167 old = change['old']
168 new = change['new']
168 new = change['new']
169 try:
169 try:
170 self.config_files.remove(old)
170 self.config_files.remove(old)
171 except ValueError:
171 except ValueError:
172 pass
172 pass
173 self.config_file_specified.add(new)
173 self.config_file_specified.add(new)
174 self.config_files.append(new)
174 self.config_files.append(new)
175
175
176 profile = Unicode(u'default',
176 profile = Unicode(u'default',
177 help="""The IPython profile to use."""
177 help="""The IPython profile to use."""
178 ).tag(config=True)
178 ).tag(config=True)
179
179
180 @observe('profile')
180 @observe('profile')
181 def _profile_changed(self, change):
181 def _profile_changed(self, change):
182 self.builtin_profile_dir = os.path.join(
182 self.builtin_profile_dir = os.path.join(
183 get_ipython_package_dir(), u'config', u'profile', change['new']
183 get_ipython_package_dir(), u'config', u'profile', change['new']
184 )
184 )
185
185
186 add_ipython_dir_to_sys_path = Bool(
186 add_ipython_dir_to_sys_path = Bool(
187 False,
187 False,
188 """Should the IPython profile directory be added to sys path ?
188 """Should the IPython profile directory be added to sys path ?
189
189
190 This option was non-existing before IPython 8.0, and ipython_dir was added to
190 This option was non-existing before IPython 8.0, and ipython_dir was added to
191 sys path to allow import of extensions present there. This was historical
191 sys path to allow import of extensions present there. This was historical
192 baggage from when pip did not exist. This now default to false,
192 baggage from when pip did not exist. This now default to false,
193 but can be set to true for legacy reasons.
193 but can be set to true for legacy reasons.
194 """,
194 """,
195 ).tag(config=True)
195 ).tag(config=True)
196
196
197 ipython_dir = Unicode(
197 ipython_dir = Unicode(
198 help="""
198 help="""
199 The name of the IPython directory. This directory is used for logging
199 The name of the IPython directory. This directory is used for logging
200 configuration (through profiles), history storage, etc. The default
200 configuration (through profiles), history storage, etc. The default
201 is usually $HOME/.ipython. This option can also be specified through
201 is usually $HOME/.ipython. This option can also be specified through
202 the environment variable IPYTHONDIR.
202 the environment variable IPYTHONDIR.
203 """
203 """
204 ).tag(config=True)
204 ).tag(config=True)
205 @default('ipython_dir')
205 @default('ipython_dir')
206 def _ipython_dir_default(self):
206 def _ipython_dir_default(self):
207 d = get_ipython_dir()
207 d = get_ipython_dir()
208 self._ipython_dir_changed({
208 self._ipython_dir_changed({
209 'name': 'ipython_dir',
209 'name': 'ipython_dir',
210 'old': d,
210 'old': d,
211 'new': d,
211 'new': d,
212 })
212 })
213 return d
213 return d
214
214
215 _in_init_profile_dir = False
215 _in_init_profile_dir = False
216 profile_dir = Instance(ProfileDir, allow_none=True)
216 profile_dir = Instance(ProfileDir, allow_none=True)
217 @default('profile_dir')
217 @default('profile_dir')
218 def _profile_dir_default(self):
218 def _profile_dir_default(self):
219 # avoid recursion
219 # avoid recursion
220 if self._in_init_profile_dir:
220 if self._in_init_profile_dir:
221 return
221 return
222 # profile_dir requested early, force initialization
222 # profile_dir requested early, force initialization
223 self.init_profile_dir()
223 self.init_profile_dir()
224 return self.profile_dir
224 return self.profile_dir
225
225
226 overwrite = Bool(False,
226 overwrite = Bool(False,
227 help="""Whether to overwrite existing config files when copying"""
227 help="""Whether to overwrite existing config files when copying"""
228 ).tag(config=True)
228 ).tag(config=True)
229 auto_create = Bool(False,
229 auto_create = Bool(False,
230 help="""Whether to create profile dir if it doesn't exist"""
230 help="""Whether to create profile dir if it doesn't exist"""
231 ).tag(config=True)
231 ).tag(config=True)
232
232
233 config_files = List(Unicode())
233 config_files = List(Unicode())
234 @default('config_files')
234 @default('config_files')
235 def _config_files_default(self):
235 def _config_files_default(self):
236 return [self.config_file_name]
236 return [self.config_file_name]
237
237
238 copy_config_files = Bool(False,
238 copy_config_files = Bool(False,
239 help="""Whether to install the default config files into the profile dir.
239 help="""Whether to install the default config files into the profile dir.
240 If a new profile is being created, and IPython contains config files for that
240 If a new profile is being created, and IPython contains config files for that
241 profile, then they will be staged into the new directory. Otherwise,
241 profile, then they will be staged into the new directory. Otherwise,
242 default config files will be automatically generated.
242 default config files will be automatically generated.
243 """).tag(config=True)
243 """).tag(config=True)
244
244
245 verbose_crash = Bool(False,
245 verbose_crash = Bool(False,
246 help="""Create a massive crash report when IPython encounters what may be an
246 help="""Create a massive crash report when IPython encounters what may be an
247 internal error. The default is to append a short message to the
247 internal error. The default is to append a short message to the
248 usual traceback""").tag(config=True)
248 usual traceback""").tag(config=True)
249
249
250 # The class to use as the crash handler.
250 # The class to use as the crash handler.
251 crash_handler_class = Type(crashhandler.CrashHandler)
251 crash_handler_class = Type(crashhandler.CrashHandler)
252
252
253 @catch_config_error
253 @catch_config_error
254 def __init__(self, **kwargs):
254 def __init__(self, **kwargs):
255 super(BaseIPythonApplication, self).__init__(**kwargs)
255 super(BaseIPythonApplication, self).__init__(**kwargs)
256 # ensure current working directory exists
256 # ensure current working directory exists
257 try:
257 try:
258 os.getcwd()
258 os.getcwd()
259 except:
259 except:
260 # exit if cwd doesn't exist
260 # exit if cwd doesn't exist
261 self.log.error("Current working directory doesn't exist.")
261 self.log.error("Current working directory doesn't exist.")
262 self.exit(1)
262 self.exit(1)
263
263
264 #-------------------------------------------------------------------------
264 #-------------------------------------------------------------------------
265 # Various stages of Application creation
265 # Various stages of Application creation
266 #-------------------------------------------------------------------------
266 #-------------------------------------------------------------------------
267
267
268 def init_crash_handler(self):
268 def init_crash_handler(self):
269 """Create a crash handler, typically setting sys.excepthook to it."""
269 """Create a crash handler, typically setting sys.excepthook to it."""
270 self.crash_handler = self.crash_handler_class(self)
270 self.crash_handler = self.crash_handler_class(self)
271 sys.excepthook = self.excepthook
271 sys.excepthook = self.excepthook
272 def unset_crashhandler():
272 def unset_crashhandler():
273 sys.excepthook = sys.__excepthook__
273 sys.excepthook = sys.__excepthook__
274 atexit.register(unset_crashhandler)
274 atexit.register(unset_crashhandler)
275
275
276 def excepthook(self, etype, evalue, tb):
276 def excepthook(self, etype, evalue, tb):
277 """this is sys.excepthook after init_crashhandler
277 """this is sys.excepthook after init_crashhandler
278
278
279 set self.verbose_crash=True to use our full crashhandler, instead of
279 set self.verbose_crash=True to use our full crashhandler, instead of
280 a regular traceback with a short message (crash_handler_lite)
280 a regular traceback with a short message (crash_handler_lite)
281 """
281 """
282
282
283 if self.verbose_crash:
283 if self.verbose_crash:
284 return self.crash_handler(etype, evalue, tb)
284 return self.crash_handler(etype, evalue, tb)
285 else:
285 else:
286 return crashhandler.crash_handler_lite(etype, evalue, tb)
286 return crashhandler.crash_handler_lite(etype, evalue, tb)
287
287
288 @observe('ipython_dir')
288 @observe('ipython_dir')
289 def _ipython_dir_changed(self, change):
289 def _ipython_dir_changed(self, change):
290 old = change['old']
290 old = change['old']
291 new = change['new']
291 new = change['new']
292 if old is not Undefined:
292 if old is not Undefined:
293 str_old = os.path.abspath(old)
293 str_old = os.path.abspath(old)
294 if str_old in sys.path:
294 if str_old in sys.path:
295 sys.path.remove(str_old)
295 sys.path.remove(str_old)
296 if self.add_ipython_dir_to_sys_path:
296 if self.add_ipython_dir_to_sys_path:
297 str_path = os.path.abspath(new)
297 str_path = os.path.abspath(new)
298 sys.path.append(str_path)
298 sys.path.append(str_path)
299 ensure_dir_exists(new)
299 ensure_dir_exists(new)
300 readme = os.path.join(new, "README")
300 readme = os.path.join(new, "README")
301 readme_src = os.path.join(
301 readme_src = os.path.join(
302 get_ipython_package_dir(), "config", "profile", "README"
302 get_ipython_package_dir(), "config", "profile", "README"
303 )
303 )
304 if not os.path.exists(readme) and os.path.exists(readme_src):
304 if not os.path.exists(readme) and os.path.exists(readme_src):
305 shutil.copy(readme_src, readme)
305 shutil.copy(readme_src, readme)
306 for d in ("extensions", "nbextensions"):
306 for d in ("extensions", "nbextensions"):
307 path = os.path.join(new, d)
307 path = os.path.join(new, d)
308 try:
308 try:
309 ensure_dir_exists(path)
309 ensure_dir_exists(path)
310 except OSError as e:
310 except OSError as e:
311 # this will not be EEXIST
311 # this will not be EEXIST
312 self.log.error("couldn't create path %s: %s", path, e)
312 self.log.error("couldn't create path %s: %s", path, e)
313 self.log.debug("IPYTHONDIR set to: %s" % new)
313 self.log.debug("IPYTHONDIR set to: %s", new)
314
314
315 def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
315 def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
316 """Load the config file.
316 """Load the config file.
317
317
318 By default, errors in loading config are handled, and a warning
318 By default, errors in loading config are handled, and a warning
319 printed on screen. For testing, the suppress_errors option is set
319 printed on screen. For testing, the suppress_errors option is set
320 to False, so errors will make tests fail.
320 to False, so errors will make tests fail.
321
321
322 `suppress_errors` default value is to be `None` in which case the
322 `suppress_errors` default value is to be `None` in which case the
323 behavior default to the one of `traitlets.Application`.
323 behavior default to the one of `traitlets.Application`.
324
324
325 The default value can be set :
325 The default value can be set :
326 - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive).
326 - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive).
327 - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive).
327 - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive).
328 - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset.
328 - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset.
329
329
330 Any other value are invalid, and will make IPython exit with a non-zero return code.
330 Any other value are invalid, and will make IPython exit with a non-zero return code.
331 """
331 """
332
332
333
333
334 self.log.debug("Searching path %s for config files", self.config_file_paths)
334 self.log.debug("Searching path %s for config files", self.config_file_paths)
335 base_config = 'ipython_config.py'
335 base_config = 'ipython_config.py'
336 self.log.debug("Attempting to load config file: %s" %
336 self.log.debug("Attempting to load config file: %s" %
337 base_config)
337 base_config)
338 try:
338 try:
339 if suppress_errors is not None:
339 if suppress_errors is not None:
340 old_value = Application.raise_config_file_errors
340 old_value = Application.raise_config_file_errors
341 Application.raise_config_file_errors = not suppress_errors;
341 Application.raise_config_file_errors = not suppress_errors;
342 Application.load_config_file(
342 Application.load_config_file(
343 self,
343 self,
344 base_config,
344 base_config,
345 path=self.config_file_paths
345 path=self.config_file_paths
346 )
346 )
347 except ConfigFileNotFound:
347 except ConfigFileNotFound:
348 # ignore errors loading parent
348 # ignore errors loading parent
349 self.log.debug("Config file %s not found", base_config)
349 self.log.debug("Config file %s not found", base_config)
350 pass
350 pass
351 if suppress_errors is not None:
351 if suppress_errors is not None:
352 Application.raise_config_file_errors = old_value
352 Application.raise_config_file_errors = old_value
353
353
354 for config_file_name in self.config_files:
354 for config_file_name in self.config_files:
355 if not config_file_name or config_file_name == base_config:
355 if not config_file_name or config_file_name == base_config:
356 continue
356 continue
357 self.log.debug("Attempting to load config file: %s" %
357 self.log.debug("Attempting to load config file: %s" %
358 self.config_file_name)
358 self.config_file_name)
359 try:
359 try:
360 Application.load_config_file(
360 Application.load_config_file(
361 self,
361 self,
362 config_file_name,
362 config_file_name,
363 path=self.config_file_paths
363 path=self.config_file_paths
364 )
364 )
365 except ConfigFileNotFound:
365 except ConfigFileNotFound:
366 # Only warn if the default config file was NOT being used.
366 # Only warn if the default config file was NOT being used.
367 if config_file_name in self.config_file_specified:
367 if config_file_name in self.config_file_specified:
368 msg = self.log.warning
368 msg = self.log.warning
369 else:
369 else:
370 msg = self.log.debug
370 msg = self.log.debug
371 msg("Config file not found, skipping: %s", config_file_name)
371 msg("Config file not found, skipping: %s", config_file_name)
372 except Exception:
372 except Exception:
373 # For testing purposes.
373 # For testing purposes.
374 if not suppress_errors:
374 if not suppress_errors:
375 raise
375 raise
376 self.log.warning("Error loading config file: %s" %
376 self.log.warning("Error loading config file: %s" %
377 self.config_file_name, exc_info=True)
377 self.config_file_name, exc_info=True)
378
378
379 def init_profile_dir(self):
379 def init_profile_dir(self):
380 """initialize the profile dir"""
380 """initialize the profile dir"""
381 self._in_init_profile_dir = True
381 self._in_init_profile_dir = True
382 if self.profile_dir is not None:
382 if self.profile_dir is not None:
383 # already ran
383 # already ran
384 return
384 return
385 if 'ProfileDir.location' not in self.config:
385 if 'ProfileDir.location' not in self.config:
386 # location not specified, find by profile name
386 # location not specified, find by profile name
387 try:
387 try:
388 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
388 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
389 except ProfileDirError:
389 except ProfileDirError:
390 # not found, maybe create it (always create default profile)
390 # not found, maybe create it (always create default profile)
391 if self.auto_create or self.profile == 'default':
391 if self.auto_create or self.profile == 'default':
392 try:
392 try:
393 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
393 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
394 except ProfileDirError:
394 except ProfileDirError:
395 self.log.fatal("Could not create profile: %r"%self.profile)
395 self.log.fatal("Could not create profile: %r"%self.profile)
396 self.exit(1)
396 self.exit(1)
397 else:
397 else:
398 self.log.info("Created profile dir: %r"%p.location)
398 self.log.info("Created profile dir: %r"%p.location)
399 else:
399 else:
400 self.log.fatal("Profile %r not found."%self.profile)
400 self.log.fatal("Profile %r not found."%self.profile)
401 self.exit(1)
401 self.exit(1)
402 else:
402 else:
403 self.log.debug("Using existing profile dir: %r", p.location)
403 self.log.debug("Using existing profile dir: %r", p.location)
404 else:
404 else:
405 location = self.config.ProfileDir.location
405 location = self.config.ProfileDir.location
406 # location is fully specified
406 # location is fully specified
407 try:
407 try:
408 p = ProfileDir.find_profile_dir(location, self.config)
408 p = ProfileDir.find_profile_dir(location, self.config)
409 except ProfileDirError:
409 except ProfileDirError:
410 # not found, maybe create it
410 # not found, maybe create it
411 if self.auto_create:
411 if self.auto_create:
412 try:
412 try:
413 p = ProfileDir.create_profile_dir(location, self.config)
413 p = ProfileDir.create_profile_dir(location, self.config)
414 except ProfileDirError:
414 except ProfileDirError:
415 self.log.fatal("Could not create profile directory: %r"%location)
415 self.log.fatal("Could not create profile directory: %r"%location)
416 self.exit(1)
416 self.exit(1)
417 else:
417 else:
418 self.log.debug("Creating new profile dir: %r"%location)
418 self.log.debug("Creating new profile dir: %r"%location)
419 else:
419 else:
420 self.log.fatal("Profile directory %r not found."%location)
420 self.log.fatal("Profile directory %r not found."%location)
421 self.exit(1)
421 self.exit(1)
422 else:
422 else:
423 self.log.debug("Using existing profile dir: %r", p.location)
423 self.log.debug("Using existing profile dir: %r", p.location)
424 # if profile_dir is specified explicitly, set profile name
424 # if profile_dir is specified explicitly, set profile name
425 dir_name = os.path.basename(p.location)
425 dir_name = os.path.basename(p.location)
426 if dir_name.startswith('profile_'):
426 if dir_name.startswith('profile_'):
427 self.profile = dir_name[8:]
427 self.profile = dir_name[8:]
428
428
429 self.profile_dir = p
429 self.profile_dir = p
430 self.config_file_paths.append(p.location)
430 self.config_file_paths.append(p.location)
431 self._in_init_profile_dir = False
431 self._in_init_profile_dir = False
432
432
433 def init_config_files(self):
433 def init_config_files(self):
434 """[optionally] copy default config files into profile dir."""
434 """[optionally] copy default config files into profile dir."""
435 self.config_file_paths.extend(ENV_CONFIG_DIRS)
435 self.config_file_paths.extend(ENV_CONFIG_DIRS)
436 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
436 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
437 # copy config files
437 # copy config files
438 path = Path(self.builtin_profile_dir)
438 path = Path(self.builtin_profile_dir)
439 if self.copy_config_files:
439 if self.copy_config_files:
440 src = self.profile
440 src = self.profile
441
441
442 cfg = self.config_file_name
442 cfg = self.config_file_name
443 if path and (path / cfg).exists():
443 if path and (path / cfg).exists():
444 self.log.warning(
444 self.log.warning(
445 "Staging %r from %s into %r [overwrite=%s]"
445 "Staging %r from %s into %r [overwrite=%s]"
446 % (cfg, src, self.profile_dir.location, self.overwrite)
446 % (cfg, src, self.profile_dir.location, self.overwrite)
447 )
447 )
448 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
448 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
449 else:
449 else:
450 self.stage_default_config_file()
450 self.stage_default_config_file()
451 else:
451 else:
452 # Still stage *bundled* config files, but not generated ones
452 # Still stage *bundled* config files, but not generated ones
453 # This is necessary for `ipython profile=sympy` to load the profile
453 # This is necessary for `ipython profile=sympy` to load the profile
454 # on the first go
454 # on the first go
455 files = path.glob("*.py")
455 files = path.glob("*.py")
456 for fullpath in files:
456 for fullpath in files:
457 cfg = fullpath.name
457 cfg = fullpath.name
458 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
458 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
459 # file was copied
459 # file was copied
460 self.log.warning("Staging bundled %s from %s into %r"%(
460 self.log.warning("Staging bundled %s from %s into %r"%(
461 cfg, self.profile, self.profile_dir.location)
461 cfg, self.profile, self.profile_dir.location)
462 )
462 )
463
463
464
464
465 def stage_default_config_file(self):
465 def stage_default_config_file(self):
466 """auto generate default config file, and stage it into the profile."""
466 """auto generate default config file, and stage it into the profile."""
467 s = self.generate_config_file()
467 s = self.generate_config_file()
468 config_file = Path(self.profile_dir.location) / self.config_file_name
468 config_file = Path(self.profile_dir.location) / self.config_file_name
469 if self.overwrite or not config_file.exists():
469 if self.overwrite or not config_file.exists():
470 self.log.warning("Generating default config file: %r" % (config_file))
470 self.log.warning("Generating default config file: %r", (config_file))
471 config_file.write_text(s, encoding="utf-8")
471 config_file.write_text(s, encoding="utf-8")
472
472
473 @catch_config_error
473 @catch_config_error
474 def initialize(self, argv=None):
474 def initialize(self, argv=None):
475 # don't hook up crash handler before parsing command-line
475 # don't hook up crash handler before parsing command-line
476 self.parse_command_line(argv)
476 self.parse_command_line(argv)
477 self.init_crash_handler()
477 self.init_crash_handler()
478 if self.subapp is not None:
478 if self.subapp is not None:
479 # stop here if subapp is taking over
479 # stop here if subapp is taking over
480 return
480 return
481 # save a copy of CLI config to re-load after config files
481 # save a copy of CLI config to re-load after config files
482 # so that it has highest priority
482 # so that it has highest priority
483 cl_config = deepcopy(self.config)
483 cl_config = deepcopy(self.config)
484 self.init_profile_dir()
484 self.init_profile_dir()
485 self.init_config_files()
485 self.init_config_files()
486 self.load_config_file()
486 self.load_config_file()
487 # enforce cl-opts override configfile opts:
487 # enforce cl-opts override configfile opts:
488 self.update_config(cl_config)
488 self.update_config(cl_config)
@@ -1,451 +1,451 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 A mixin for :class:`~IPython.core.application.Application` classes that
3 A mixin for :class:`~IPython.core.application.Application` classes that
4 launch InteractiveShell instances, load extensions, etc.
4 launch InteractiveShell instances, load extensions, etc.
5 """
5 """
6
6
7 # Copyright (c) IPython Development Team.
7 # Copyright (c) IPython Development Team.
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9
9
10 import glob
10 import glob
11 from itertools import chain
11 from itertools import chain
12 import os
12 import os
13 import sys
13 import sys
14
14
15 from traitlets.config.application import boolean_flag
15 from traitlets.config.application import boolean_flag
16 from traitlets.config.configurable import Configurable
16 from traitlets.config.configurable import Configurable
17 from traitlets.config.loader import Config
17 from traitlets.config.loader import Config
18 from IPython.core.application import SYSTEM_CONFIG_DIRS, ENV_CONFIG_DIRS
18 from IPython.core.application import SYSTEM_CONFIG_DIRS, ENV_CONFIG_DIRS
19 from IPython.core import pylabtools
19 from IPython.core import pylabtools
20 from IPython.utils.contexts import preserve_keys
20 from IPython.utils.contexts import preserve_keys
21 from IPython.utils.path import filefind
21 from IPython.utils.path import filefind
22 from traitlets import (
22 from traitlets import (
23 Unicode, Instance, List, Bool, CaselessStrEnum, observe,
23 Unicode, Instance, List, Bool, CaselessStrEnum, observe,
24 DottedObjectName,
24 DottedObjectName,
25 )
25 )
26 from IPython.terminal import pt_inputhooks
26 from IPython.terminal import pt_inputhooks
27
27
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29 # Aliases and Flags
29 # Aliases and Flags
30 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
31
31
32 gui_keys = tuple(sorted(pt_inputhooks.backends) + sorted(pt_inputhooks.aliases))
32 gui_keys = tuple(sorted(pt_inputhooks.backends) + sorted(pt_inputhooks.aliases))
33
33
34 backend_keys = sorted(pylabtools.backends.keys())
34 backend_keys = sorted(pylabtools.backends.keys())
35 backend_keys.insert(0, 'auto')
35 backend_keys.insert(0, 'auto')
36
36
37 shell_flags = {}
37 shell_flags = {}
38
38
39 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
39 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
40 addflag('autoindent', 'InteractiveShell.autoindent',
40 addflag('autoindent', 'InteractiveShell.autoindent',
41 'Turn on autoindenting.', 'Turn off autoindenting.'
41 'Turn on autoindenting.', 'Turn off autoindenting.'
42 )
42 )
43 addflag('automagic', 'InteractiveShell.automagic',
43 addflag('automagic', 'InteractiveShell.automagic',
44 """Turn on the auto calling of magic commands. Type %%magic at the
44 """Turn on the auto calling of magic commands. Type %%magic at the
45 IPython prompt for more information.""",
45 IPython prompt for more information.""",
46 'Turn off the auto calling of magic commands.'
46 'Turn off the auto calling of magic commands.'
47 )
47 )
48 addflag('pdb', 'InteractiveShell.pdb',
48 addflag('pdb', 'InteractiveShell.pdb',
49 "Enable auto calling the pdb debugger after every exception.",
49 "Enable auto calling the pdb debugger after every exception.",
50 "Disable auto calling the pdb debugger after every exception."
50 "Disable auto calling the pdb debugger after every exception."
51 )
51 )
52 addflag('pprint', 'PlainTextFormatter.pprint',
52 addflag('pprint', 'PlainTextFormatter.pprint',
53 "Enable auto pretty printing of results.",
53 "Enable auto pretty printing of results.",
54 "Disable auto pretty printing of results."
54 "Disable auto pretty printing of results."
55 )
55 )
56 addflag('color-info', 'InteractiveShell.color_info',
56 addflag('color-info', 'InteractiveShell.color_info',
57 """IPython can display information about objects via a set of functions,
57 """IPython can display information about objects via a set of functions,
58 and optionally can use colors for this, syntax highlighting
58 and optionally can use colors for this, syntax highlighting
59 source code and various other elements. This is on by default, but can cause
59 source code and various other elements. This is on by default, but can cause
60 problems with some pagers. If you see such problems, you can disable the
60 problems with some pagers. If you see such problems, you can disable the
61 colours.""",
61 colours.""",
62 "Disable using colors for info related things."
62 "Disable using colors for info related things."
63 )
63 )
64 addflag('ignore-cwd', 'InteractiveShellApp.ignore_cwd',
64 addflag('ignore-cwd', 'InteractiveShellApp.ignore_cwd',
65 "Exclude the current working directory from sys.path",
65 "Exclude the current working directory from sys.path",
66 "Include the current working directory in sys.path",
66 "Include the current working directory in sys.path",
67 )
67 )
68 nosep_config = Config()
68 nosep_config = Config()
69 nosep_config.InteractiveShell.separate_in = ''
69 nosep_config.InteractiveShell.separate_in = ''
70 nosep_config.InteractiveShell.separate_out = ''
70 nosep_config.InteractiveShell.separate_out = ''
71 nosep_config.InteractiveShell.separate_out2 = ''
71 nosep_config.InteractiveShell.separate_out2 = ''
72
72
73 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
73 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
74 shell_flags['pylab'] = (
74 shell_flags['pylab'] = (
75 {'InteractiveShellApp' : {'pylab' : 'auto'}},
75 {'InteractiveShellApp' : {'pylab' : 'auto'}},
76 """Pre-load matplotlib and numpy for interactive use with
76 """Pre-load matplotlib and numpy for interactive use with
77 the default matplotlib backend."""
77 the default matplotlib backend."""
78 )
78 )
79 shell_flags['matplotlib'] = (
79 shell_flags['matplotlib'] = (
80 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
80 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
81 """Configure matplotlib for interactive use with
81 """Configure matplotlib for interactive use with
82 the default matplotlib backend."""
82 the default matplotlib backend."""
83 )
83 )
84
84
85 # it's possible we don't want short aliases for *all* of these:
85 # it's possible we don't want short aliases for *all* of these:
86 shell_aliases = dict(
86 shell_aliases = dict(
87 autocall='InteractiveShell.autocall',
87 autocall='InteractiveShell.autocall',
88 colors='InteractiveShell.colors',
88 colors='InteractiveShell.colors',
89 logfile='InteractiveShell.logfile',
89 logfile='InteractiveShell.logfile',
90 logappend='InteractiveShell.logappend',
90 logappend='InteractiveShell.logappend',
91 c='InteractiveShellApp.code_to_run',
91 c='InteractiveShellApp.code_to_run',
92 m='InteractiveShellApp.module_to_run',
92 m='InteractiveShellApp.module_to_run',
93 ext="InteractiveShellApp.extra_extensions",
93 ext="InteractiveShellApp.extra_extensions",
94 gui='InteractiveShellApp.gui',
94 gui='InteractiveShellApp.gui',
95 pylab='InteractiveShellApp.pylab',
95 pylab='InteractiveShellApp.pylab',
96 matplotlib='InteractiveShellApp.matplotlib',
96 matplotlib='InteractiveShellApp.matplotlib',
97 )
97 )
98 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
98 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
99
99
100 #-----------------------------------------------------------------------------
100 #-----------------------------------------------------------------------------
101 # Main classes and functions
101 # Main classes and functions
102 #-----------------------------------------------------------------------------
102 #-----------------------------------------------------------------------------
103
103
104 class InteractiveShellApp(Configurable):
104 class InteractiveShellApp(Configurable):
105 """A Mixin for applications that start InteractiveShell instances.
105 """A Mixin for applications that start InteractiveShell instances.
106
106
107 Provides configurables for loading extensions and executing files
107 Provides configurables for loading extensions and executing files
108 as part of configuring a Shell environment.
108 as part of configuring a Shell environment.
109
109
110 The following methods should be called by the :meth:`initialize` method
110 The following methods should be called by the :meth:`initialize` method
111 of the subclass:
111 of the subclass:
112
112
113 - :meth:`init_path`
113 - :meth:`init_path`
114 - :meth:`init_shell` (to be implemented by the subclass)
114 - :meth:`init_shell` (to be implemented by the subclass)
115 - :meth:`init_gui_pylab`
115 - :meth:`init_gui_pylab`
116 - :meth:`init_extensions`
116 - :meth:`init_extensions`
117 - :meth:`init_code`
117 - :meth:`init_code`
118 """
118 """
119 extensions = List(Unicode(),
119 extensions = List(Unicode(),
120 help="A list of dotted module names of IPython extensions to load."
120 help="A list of dotted module names of IPython extensions to load."
121 ).tag(config=True)
121 ).tag(config=True)
122
122
123 extra_extensions = List(
123 extra_extensions = List(
124 DottedObjectName(),
124 DottedObjectName(),
125 help="""
125 help="""
126 Dotted module name(s) of one or more IPython extensions to load.
126 Dotted module name(s) of one or more IPython extensions to load.
127
127
128 For specifying extra extensions to load on the command-line.
128 For specifying extra extensions to load on the command-line.
129
129
130 .. versionadded:: 7.10
130 .. versionadded:: 7.10
131 """,
131 """,
132 ).tag(config=True)
132 ).tag(config=True)
133
133
134 reraise_ipython_extension_failures = Bool(False,
134 reraise_ipython_extension_failures = Bool(False,
135 help="Reraise exceptions encountered loading IPython extensions?",
135 help="Reraise exceptions encountered loading IPython extensions?",
136 ).tag(config=True)
136 ).tag(config=True)
137
137
138 # Extensions that are always loaded (not configurable)
138 # Extensions that are always loaded (not configurable)
139 default_extensions = List(Unicode(), [u'storemagic']).tag(config=False)
139 default_extensions = List(Unicode(), [u'storemagic']).tag(config=False)
140
140
141 hide_initial_ns = Bool(True,
141 hide_initial_ns = Bool(True,
142 help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
142 help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
143 be hidden from tools like %who?"""
143 be hidden from tools like %who?"""
144 ).tag(config=True)
144 ).tag(config=True)
145
145
146 exec_files = List(Unicode(),
146 exec_files = List(Unicode(),
147 help="""List of files to run at IPython startup."""
147 help="""List of files to run at IPython startup."""
148 ).tag(config=True)
148 ).tag(config=True)
149 exec_PYTHONSTARTUP = Bool(True,
149 exec_PYTHONSTARTUP = Bool(True,
150 help="""Run the file referenced by the PYTHONSTARTUP environment
150 help="""Run the file referenced by the PYTHONSTARTUP environment
151 variable at IPython startup."""
151 variable at IPython startup."""
152 ).tag(config=True)
152 ).tag(config=True)
153 file_to_run = Unicode('',
153 file_to_run = Unicode('',
154 help="""A file to be run""").tag(config=True)
154 help="""A file to be run""").tag(config=True)
155
155
156 exec_lines = List(Unicode(),
156 exec_lines = List(Unicode(),
157 help="""lines of code to run at IPython startup."""
157 help="""lines of code to run at IPython startup."""
158 ).tag(config=True)
158 ).tag(config=True)
159 code_to_run = Unicode('',
159 code_to_run = Unicode('',
160 help="Execute the given command string."
160 help="Execute the given command string."
161 ).tag(config=True)
161 ).tag(config=True)
162 module_to_run = Unicode('',
162 module_to_run = Unicode('',
163 help="Run the module as a script."
163 help="Run the module as a script."
164 ).tag(config=True)
164 ).tag(config=True)
165 gui = CaselessStrEnum(gui_keys, allow_none=True,
165 gui = CaselessStrEnum(gui_keys, allow_none=True,
166 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
166 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
167 ).tag(config=True)
167 ).tag(config=True)
168 matplotlib = CaselessStrEnum(backend_keys, allow_none=True,
168 matplotlib = CaselessStrEnum(backend_keys, allow_none=True,
169 help="""Configure matplotlib for interactive use with
169 help="""Configure matplotlib for interactive use with
170 the default matplotlib backend."""
170 the default matplotlib backend."""
171 ).tag(config=True)
171 ).tag(config=True)
172 pylab = CaselessStrEnum(backend_keys, allow_none=True,
172 pylab = CaselessStrEnum(backend_keys, allow_none=True,
173 help="""Pre-load matplotlib and numpy for interactive use,
173 help="""Pre-load matplotlib and numpy for interactive use,
174 selecting a particular matplotlib backend and loop integration.
174 selecting a particular matplotlib backend and loop integration.
175 """
175 """
176 ).tag(config=True)
176 ).tag(config=True)
177 pylab_import_all = Bool(True,
177 pylab_import_all = Bool(True,
178 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
178 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
179 and an ``import *`` is done from numpy and pylab, when using pylab mode.
179 and an ``import *`` is done from numpy and pylab, when using pylab mode.
180
180
181 When False, pylab mode should not import any names into the user namespace.
181 When False, pylab mode should not import any names into the user namespace.
182 """
182 """
183 ).tag(config=True)
183 ).tag(config=True)
184 ignore_cwd = Bool(
184 ignore_cwd = Bool(
185 False,
185 False,
186 help="""If True, IPython will not add the current working directory to sys.path.
186 help="""If True, IPython will not add the current working directory to sys.path.
187 When False, the current working directory is added to sys.path, allowing imports
187 When False, the current working directory is added to sys.path, allowing imports
188 of modules defined in the current directory."""
188 of modules defined in the current directory."""
189 ).tag(config=True)
189 ).tag(config=True)
190 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
190 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
191 allow_none=True)
191 allow_none=True)
192 # whether interact-loop should start
192 # whether interact-loop should start
193 interact = Bool(True)
193 interact = Bool(True)
194
194
195 user_ns = Instance(dict, args=None, allow_none=True)
195 user_ns = Instance(dict, args=None, allow_none=True)
196 @observe('user_ns')
196 @observe('user_ns')
197 def _user_ns_changed(self, change):
197 def _user_ns_changed(self, change):
198 if self.shell is not None:
198 if self.shell is not None:
199 self.shell.user_ns = change['new']
199 self.shell.user_ns = change['new']
200 self.shell.init_user_ns()
200 self.shell.init_user_ns()
201
201
202 def init_path(self):
202 def init_path(self):
203 """Add current working directory, '', to sys.path
203 """Add current working directory, '', to sys.path
204
204
205 Unlike Python's default, we insert before the first `site-packages`
205 Unlike Python's default, we insert before the first `site-packages`
206 or `dist-packages` directory,
206 or `dist-packages` directory,
207 so that it is after the standard library.
207 so that it is after the standard library.
208
208
209 .. versionchanged:: 7.2
209 .. versionchanged:: 7.2
210 Try to insert after the standard library, instead of first.
210 Try to insert after the standard library, instead of first.
211 .. versionchanged:: 8.0
211 .. versionchanged:: 8.0
212 Allow optionally not including the current directory in sys.path
212 Allow optionally not including the current directory in sys.path
213 """
213 """
214 if '' in sys.path or self.ignore_cwd:
214 if '' in sys.path or self.ignore_cwd:
215 return
215 return
216 for idx, path in enumerate(sys.path):
216 for idx, path in enumerate(sys.path):
217 parent, last_part = os.path.split(path)
217 parent, last_part = os.path.split(path)
218 if last_part in {'site-packages', 'dist-packages'}:
218 if last_part in {'site-packages', 'dist-packages'}:
219 break
219 break
220 else:
220 else:
221 # no site-packages or dist-packages found (?!)
221 # no site-packages or dist-packages found (?!)
222 # back to original behavior of inserting at the front
222 # back to original behavior of inserting at the front
223 idx = 0
223 idx = 0
224 sys.path.insert(idx, '')
224 sys.path.insert(idx, '')
225
225
226 def init_shell(self):
226 def init_shell(self):
227 raise NotImplementedError("Override in subclasses")
227 raise NotImplementedError("Override in subclasses")
228
228
229 def init_gui_pylab(self):
229 def init_gui_pylab(self):
230 """Enable GUI event loop integration, taking pylab into account."""
230 """Enable GUI event loop integration, taking pylab into account."""
231 enable = False
231 enable = False
232 shell = self.shell
232 shell = self.shell
233 if self.pylab:
233 if self.pylab:
234 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
234 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
235 key = self.pylab
235 key = self.pylab
236 elif self.matplotlib:
236 elif self.matplotlib:
237 enable = shell.enable_matplotlib
237 enable = shell.enable_matplotlib
238 key = self.matplotlib
238 key = self.matplotlib
239 elif self.gui:
239 elif self.gui:
240 enable = shell.enable_gui
240 enable = shell.enable_gui
241 key = self.gui
241 key = self.gui
242
242
243 if not enable:
243 if not enable:
244 return
244 return
245
245
246 try:
246 try:
247 r = enable(key)
247 r = enable(key)
248 except ImportError:
248 except ImportError:
249 self.log.warning("Eventloop or matplotlib integration failed. Is matplotlib installed?")
249 self.log.warning("Eventloop or matplotlib integration failed. Is matplotlib installed?")
250 self.shell.showtraceback()
250 self.shell.showtraceback()
251 return
251 return
252 except Exception:
252 except Exception:
253 self.log.warning("GUI event loop or pylab initialization failed")
253 self.log.warning("GUI event loop or pylab initialization failed")
254 self.shell.showtraceback()
254 self.shell.showtraceback()
255 return
255 return
256
256
257 if isinstance(r, tuple):
257 if isinstance(r, tuple):
258 gui, backend = r[:2]
258 gui, backend = r[:2]
259 self.log.info("Enabling GUI event loop integration, "
259 self.log.info("Enabling GUI event loop integration, "
260 "eventloop=%s, matplotlib=%s", gui, backend)
260 "eventloop=%s, matplotlib=%s", gui, backend)
261 if key == "auto":
261 if key == "auto":
262 print("Using matplotlib backend: %s" % backend)
262 print("Using matplotlib backend: %s" % backend)
263 else:
263 else:
264 gui = r
264 gui = r
265 self.log.info("Enabling GUI event loop integration, "
265 self.log.info("Enabling GUI event loop integration, "
266 "eventloop=%s", gui)
266 "eventloop=%s", gui)
267
267
268 def init_extensions(self):
268 def init_extensions(self):
269 """Load all IPython extensions in IPythonApp.extensions.
269 """Load all IPython extensions in IPythonApp.extensions.
270
270
271 This uses the :meth:`ExtensionManager.load_extensions` to load all
271 This uses the :meth:`ExtensionManager.load_extensions` to load all
272 the extensions listed in ``self.extensions``.
272 the extensions listed in ``self.extensions``.
273 """
273 """
274 try:
274 try:
275 self.log.debug("Loading IPython extensions...")
275 self.log.debug("Loading IPython extensions...")
276 extensions = (
276 extensions = (
277 self.default_extensions + self.extensions + self.extra_extensions
277 self.default_extensions + self.extensions + self.extra_extensions
278 )
278 )
279 for ext in extensions:
279 for ext in extensions:
280 try:
280 try:
281 self.log.info("Loading IPython extension: %s" % ext)
281 self.log.info("Loading IPython extension: %s", ext)
282 self.shell.extension_manager.load_extension(ext)
282 self.shell.extension_manager.load_extension(ext)
283 except:
283 except:
284 if self.reraise_ipython_extension_failures:
284 if self.reraise_ipython_extension_failures:
285 raise
285 raise
286 msg = ("Error in loading extension: {ext}\n"
286 msg = ("Error in loading extension: {ext}\n"
287 "Check your config files in {location}".format(
287 "Check your config files in {location}".format(
288 ext=ext,
288 ext=ext,
289 location=self.profile_dir.location
289 location=self.profile_dir.location
290 ))
290 ))
291 self.log.warning(msg, exc_info=True)
291 self.log.warning(msg, exc_info=True)
292 except:
292 except:
293 if self.reraise_ipython_extension_failures:
293 if self.reraise_ipython_extension_failures:
294 raise
294 raise
295 self.log.warning("Unknown error in loading extensions:", exc_info=True)
295 self.log.warning("Unknown error in loading extensions:", exc_info=True)
296
296
297 def init_code(self):
297 def init_code(self):
298 """run the pre-flight code, specified via exec_lines"""
298 """run the pre-flight code, specified via exec_lines"""
299 self._run_startup_files()
299 self._run_startup_files()
300 self._run_exec_lines()
300 self._run_exec_lines()
301 self._run_exec_files()
301 self._run_exec_files()
302
302
303 # Hide variables defined here from %who etc.
303 # Hide variables defined here from %who etc.
304 if self.hide_initial_ns:
304 if self.hide_initial_ns:
305 self.shell.user_ns_hidden.update(self.shell.user_ns)
305 self.shell.user_ns_hidden.update(self.shell.user_ns)
306
306
307 # command-line execution (ipython -i script.py, ipython -m module)
307 # command-line execution (ipython -i script.py, ipython -m module)
308 # should *not* be excluded from %whos
308 # should *not* be excluded from %whos
309 self._run_cmd_line_code()
309 self._run_cmd_line_code()
310 self._run_module()
310 self._run_module()
311
311
312 # flush output, so itwon't be attached to the first cell
312 # flush output, so itwon't be attached to the first cell
313 sys.stdout.flush()
313 sys.stdout.flush()
314 sys.stderr.flush()
314 sys.stderr.flush()
315 self.shell._sys_modules_keys = set(sys.modules.keys())
315 self.shell._sys_modules_keys = set(sys.modules.keys())
316
316
317 def _run_exec_lines(self):
317 def _run_exec_lines(self):
318 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
318 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
319 if not self.exec_lines:
319 if not self.exec_lines:
320 return
320 return
321 try:
321 try:
322 self.log.debug("Running code from IPythonApp.exec_lines...")
322 self.log.debug("Running code from IPythonApp.exec_lines...")
323 for line in self.exec_lines:
323 for line in self.exec_lines:
324 try:
324 try:
325 self.log.info("Running code in user namespace: %s" %
325 self.log.info("Running code in user namespace: %s" %
326 line)
326 line)
327 self.shell.run_cell(line, store_history=False)
327 self.shell.run_cell(line, store_history=False)
328 except:
328 except:
329 self.log.warning("Error in executing line in user "
329 self.log.warning("Error in executing line in user "
330 "namespace: %s" % line)
330 "namespace: %s" % line)
331 self.shell.showtraceback()
331 self.shell.showtraceback()
332 except:
332 except:
333 self.log.warning("Unknown error in handling IPythonApp.exec_lines:")
333 self.log.warning("Unknown error in handling IPythonApp.exec_lines:")
334 self.shell.showtraceback()
334 self.shell.showtraceback()
335
335
336 def _exec_file(self, fname, shell_futures=False):
336 def _exec_file(self, fname, shell_futures=False):
337 try:
337 try:
338 full_filename = filefind(fname, [u'.', self.ipython_dir])
338 full_filename = filefind(fname, [u'.', self.ipython_dir])
339 except IOError:
339 except IOError:
340 self.log.warning("File not found: %r"%fname)
340 self.log.warning("File not found: %r"%fname)
341 return
341 return
342 # Make sure that the running script gets a proper sys.argv as if it
342 # Make sure that the running script gets a proper sys.argv as if it
343 # were run from a system shell.
343 # were run from a system shell.
344 save_argv = sys.argv
344 save_argv = sys.argv
345 sys.argv = [full_filename] + self.extra_args[1:]
345 sys.argv = [full_filename] + self.extra_args[1:]
346 try:
346 try:
347 if os.path.isfile(full_filename):
347 if os.path.isfile(full_filename):
348 self.log.info("Running file in user namespace: %s" %
348 self.log.info("Running file in user namespace: %s" %
349 full_filename)
349 full_filename)
350 # Ensure that __file__ is always defined to match Python
350 # Ensure that __file__ is always defined to match Python
351 # behavior.
351 # behavior.
352 with preserve_keys(self.shell.user_ns, '__file__'):
352 with preserve_keys(self.shell.user_ns, '__file__'):
353 self.shell.user_ns['__file__'] = fname
353 self.shell.user_ns['__file__'] = fname
354 if full_filename.endswith('.ipy') or full_filename.endswith('.ipynb'):
354 if full_filename.endswith('.ipy') or full_filename.endswith('.ipynb'):
355 self.shell.safe_execfile_ipy(full_filename,
355 self.shell.safe_execfile_ipy(full_filename,
356 shell_futures=shell_futures)
356 shell_futures=shell_futures)
357 else:
357 else:
358 # default to python, even without extension
358 # default to python, even without extension
359 self.shell.safe_execfile(full_filename,
359 self.shell.safe_execfile(full_filename,
360 self.shell.user_ns,
360 self.shell.user_ns,
361 shell_futures=shell_futures,
361 shell_futures=shell_futures,
362 raise_exceptions=True)
362 raise_exceptions=True)
363 finally:
363 finally:
364 sys.argv = save_argv
364 sys.argv = save_argv
365
365
366 def _run_startup_files(self):
366 def _run_startup_files(self):
367 """Run files from profile startup directory"""
367 """Run files from profile startup directory"""
368 startup_dirs = [self.profile_dir.startup_dir] + [
368 startup_dirs = [self.profile_dir.startup_dir] + [
369 os.path.join(p, 'startup') for p in chain(ENV_CONFIG_DIRS, SYSTEM_CONFIG_DIRS)
369 os.path.join(p, 'startup') for p in chain(ENV_CONFIG_DIRS, SYSTEM_CONFIG_DIRS)
370 ]
370 ]
371 startup_files = []
371 startup_files = []
372
372
373 if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
373 if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
374 not (self.file_to_run or self.code_to_run or self.module_to_run):
374 not (self.file_to_run or self.code_to_run or self.module_to_run):
375 python_startup = os.environ['PYTHONSTARTUP']
375 python_startup = os.environ['PYTHONSTARTUP']
376 self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
376 self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
377 try:
377 try:
378 self._exec_file(python_startup)
378 self._exec_file(python_startup)
379 except:
379 except:
380 self.log.warning("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
380 self.log.warning("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
381 self.shell.showtraceback()
381 self.shell.showtraceback()
382 for startup_dir in startup_dirs[::-1]:
382 for startup_dir in startup_dirs[::-1]:
383 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
383 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
384 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
384 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
385 if not startup_files:
385 if not startup_files:
386 return
386 return
387
387
388 self.log.debug("Running startup files from %s...", startup_dir)
388 self.log.debug("Running startup files from %s...", startup_dir)
389 try:
389 try:
390 for fname in sorted(startup_files):
390 for fname in sorted(startup_files):
391 self._exec_file(fname)
391 self._exec_file(fname)
392 except:
392 except:
393 self.log.warning("Unknown error in handling startup files:")
393 self.log.warning("Unknown error in handling startup files:")
394 self.shell.showtraceback()
394 self.shell.showtraceback()
395
395
396 def _run_exec_files(self):
396 def _run_exec_files(self):
397 """Run files from IPythonApp.exec_files"""
397 """Run files from IPythonApp.exec_files"""
398 if not self.exec_files:
398 if not self.exec_files:
399 return
399 return
400
400
401 self.log.debug("Running files in IPythonApp.exec_files...")
401 self.log.debug("Running files in IPythonApp.exec_files...")
402 try:
402 try:
403 for fname in self.exec_files:
403 for fname in self.exec_files:
404 self._exec_file(fname)
404 self._exec_file(fname)
405 except:
405 except:
406 self.log.warning("Unknown error in handling IPythonApp.exec_files:")
406 self.log.warning("Unknown error in handling IPythonApp.exec_files:")
407 self.shell.showtraceback()
407 self.shell.showtraceback()
408
408
409 def _run_cmd_line_code(self):
409 def _run_cmd_line_code(self):
410 """Run code or file specified at the command-line"""
410 """Run code or file specified at the command-line"""
411 if self.code_to_run:
411 if self.code_to_run:
412 line = self.code_to_run
412 line = self.code_to_run
413 try:
413 try:
414 self.log.info("Running code given at command line (c=): %s" %
414 self.log.info("Running code given at command line (c=): %s" %
415 line)
415 line)
416 self.shell.run_cell(line, store_history=False)
416 self.shell.run_cell(line, store_history=False)
417 except:
417 except:
418 self.log.warning("Error in executing line in user namespace: %s" %
418 self.log.warning("Error in executing line in user namespace: %s" %
419 line)
419 line)
420 self.shell.showtraceback()
420 self.shell.showtraceback()
421 if not self.interact:
421 if not self.interact:
422 self.exit(1)
422 self.exit(1)
423
423
424 # Like Python itself, ignore the second if the first of these is present
424 # Like Python itself, ignore the second if the first of these is present
425 elif self.file_to_run:
425 elif self.file_to_run:
426 fname = self.file_to_run
426 fname = self.file_to_run
427 if os.path.isdir(fname):
427 if os.path.isdir(fname):
428 fname = os.path.join(fname, "__main__.py")
428 fname = os.path.join(fname, "__main__.py")
429 if not os.path.exists(fname):
429 if not os.path.exists(fname):
430 self.log.warning("File '%s' doesn't exist", fname)
430 self.log.warning("File '%s' doesn't exist", fname)
431 if not self.interact:
431 if not self.interact:
432 self.exit(2)
432 self.exit(2)
433 try:
433 try:
434 self._exec_file(fname, shell_futures=True)
434 self._exec_file(fname, shell_futures=True)
435 except:
435 except:
436 self.shell.showtraceback(tb_offset=4)
436 self.shell.showtraceback(tb_offset=4)
437 if not self.interact:
437 if not self.interact:
438 self.exit(1)
438 self.exit(1)
439
439
440 def _run_module(self):
440 def _run_module(self):
441 """Run module specified at the command-line."""
441 """Run module specified at the command-line."""
442 if self.module_to_run:
442 if self.module_to_run:
443 # Make sure that the module gets a proper sys.argv as if it were
443 # Make sure that the module gets a proper sys.argv as if it were
444 # run using `python -m`.
444 # run using `python -m`.
445 save_argv = sys.argv
445 save_argv = sys.argv
446 sys.argv = [sys.executable] + self.extra_args
446 sys.argv = [sys.executable] + self.extra_args
447 try:
447 try:
448 self.shell.safe_run_module(self.module_to_run,
448 self.shell.safe_run_module(self.module_to_run,
449 self.shell.user_ns)
449 self.shell.user_ns)
450 finally:
450 finally:
451 sys.argv = save_argv
451 sys.argv = save_argv
General Comments 0
You need to be logged in to leave comments. Login now