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