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