##// END OF EJS Templates
dont' swallow sys.exit
Matthias Bussonnier -
Show More
@@ -1,397 +1,397 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 An application for IPython.
3 An application for IPython.
4
4
5 All top-level applications should use the classes in this module for
5 All top-level applications should use the classes in this module for
6 handling configuration and creating configurables.
6 handling configuration and creating configurables.
7
7
8 The job of an :class:`Application` is to create the master configuration
8 The job of an :class:`Application` is to create the master configuration
9 object and then create the configurable objects, passing the config to them.
9 object and then create the configurable objects, passing the config to them.
10 """
10 """
11
11
12 # Copyright (c) IPython Development Team.
12 # Copyright (c) IPython Development Team.
13 # Distributed under the terms of the Modified BSD License.
13 # Distributed under the terms of the Modified BSD License.
14
14
15 import atexit
15 import atexit
16 import glob
16 import glob
17 import logging
17 import logging
18 import os
18 import os
19 import shutil
19 import shutil
20 import sys
20 import sys
21
21
22 from traitlets.config.application import Application, catch_config_error
22 from traitlets.config.application import Application, catch_config_error
23 from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader
23 from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader
24 from IPython.core import release, crashhandler
24 from IPython.core import release, crashhandler
25 from IPython.core.profiledir import ProfileDir, ProfileDirError
25 from IPython.core.profiledir import ProfileDir, ProfileDirError
26 from IPython.paths import get_ipython_dir, get_ipython_package_dir
26 from IPython.paths import get_ipython_dir, get_ipython_package_dir
27 from IPython.utils.path import ensure_dir_exists
27 from IPython.utils.path import ensure_dir_exists
28 from IPython.utils import py3compat
28 from IPython.utils import py3compat
29 from traitlets import List, Unicode, Type, Bool, Dict, Set, Instance, Undefined
29 from traitlets import List, Unicode, Type, Bool, Dict, Set, Instance, Undefined
30
30
31 if os.name == 'nt':
31 if os.name == 'nt':
32 programdata = os.environ.get('PROGRAMDATA', None)
32 programdata = os.environ.get('PROGRAMDATA', None)
33 if programdata:
33 if programdata:
34 SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
34 SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
35 else: # PROGRAMDATA is not defined by default on XP.
35 else: # PROGRAMDATA is not defined by default on XP.
36 SYSTEM_CONFIG_DIRS = []
36 SYSTEM_CONFIG_DIRS = []
37 else:
37 else:
38 SYSTEM_CONFIG_DIRS = [
38 SYSTEM_CONFIG_DIRS = [
39 "/usr/local/etc/ipython",
39 "/usr/local/etc/ipython",
40 "/etc/ipython",
40 "/etc/ipython",
41 ]
41 ]
42
42
43
43
44 # aliases and flags
44 # aliases and flags
45
45
46 base_aliases = {
46 base_aliases = {
47 'profile-dir' : 'ProfileDir.location',
47 'profile-dir' : 'ProfileDir.location',
48 'profile' : 'BaseIPythonApplication.profile',
48 'profile' : 'BaseIPythonApplication.profile',
49 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
49 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
50 'log-level' : 'Application.log_level',
50 'log-level' : 'Application.log_level',
51 'config' : 'BaseIPythonApplication.extra_config_file',
51 'config' : 'BaseIPythonApplication.extra_config_file',
52 }
52 }
53
53
54 base_flags = dict(
54 base_flags = dict(
55 debug = ({'Application' : {'log_level' : logging.DEBUG}},
55 debug = ({'Application' : {'log_level' : logging.DEBUG}},
56 "set log level to logging.DEBUG (maximize logging output)"),
56 "set log level to logging.DEBUG (maximize logging output)"),
57 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
57 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
58 "set log level to logging.CRITICAL (minimize logging output)"),
58 "set log level to logging.CRITICAL (minimize logging output)"),
59 init = ({'BaseIPythonApplication' : {
59 init = ({'BaseIPythonApplication' : {
60 'copy_config_files' : True,
60 'copy_config_files' : True,
61 'auto_create' : True}
61 'auto_create' : True}
62 }, """Initialize profile with default config files. This is equivalent
62 }, """Initialize profile with default config files. This is equivalent
63 to running `ipython profile create <profile>` prior to startup.
63 to running `ipython profile create <profile>` prior to startup.
64 """)
64 """)
65 )
65 )
66
66
67 class ProfileAwareConfigLoader(PyFileConfigLoader):
67 class ProfileAwareConfigLoader(PyFileConfigLoader):
68 """A Python file config loader that is aware of IPython profiles."""
68 """A Python file config loader that is aware of IPython profiles."""
69 def load_subconfig(self, fname, path=None, profile=None):
69 def load_subconfig(self, fname, path=None, profile=None):
70 if profile is not None:
70 if profile is not None:
71 try:
71 try:
72 profile_dir = ProfileDir.find_profile_dir_by_name(
72 profile_dir = ProfileDir.find_profile_dir_by_name(
73 get_ipython_dir(),
73 get_ipython_dir(),
74 profile,
74 profile,
75 )
75 )
76 except ProfileDirError:
76 except ProfileDirError:
77 return
77 return
78 path = profile_dir.location
78 path = profile_dir.location
79 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
79 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
80
80
81 class BaseIPythonApplication(Application):
81 class BaseIPythonApplication(Application):
82
82
83 name = Unicode(u'ipython')
83 name = Unicode(u'ipython')
84 description = Unicode(u'IPython: an enhanced interactive Python shell.')
84 description = Unicode(u'IPython: an enhanced interactive Python shell.')
85 version = Unicode(release.version)
85 version = Unicode(release.version)
86
86
87 aliases = Dict(base_aliases)
87 aliases = Dict(base_aliases)
88 flags = Dict(base_flags)
88 flags = Dict(base_flags)
89 classes = List([ProfileDir])
89 classes = List([ProfileDir])
90
90
91 # enable `load_subconfig('cfg.py', profile='name')`
91 # enable `load_subconfig('cfg.py', profile='name')`
92 python_config_loader_class = ProfileAwareConfigLoader
92 python_config_loader_class = ProfileAwareConfigLoader
93
93
94 # Track whether the config_file has changed,
94 # Track whether the config_file has changed,
95 # because some logic happens only if we aren't using the default.
95 # because some logic happens only if we aren't using the default.
96 config_file_specified = Set()
96 config_file_specified = Set()
97
97
98 config_file_name = Unicode()
98 config_file_name = Unicode()
99 def _config_file_name_default(self):
99 def _config_file_name_default(self):
100 return self.name.replace('-','_') + u'_config.py'
100 return self.name.replace('-','_') + u'_config.py'
101 def _config_file_name_changed(self, name, old, new):
101 def _config_file_name_changed(self, name, old, new):
102 if new != old:
102 if new != old:
103 self.config_file_specified.add(new)
103 self.config_file_specified.add(new)
104
104
105 # The directory that contains IPython's builtin profiles.
105 # The directory that contains IPython's builtin profiles.
106 builtin_profile_dir = Unicode(
106 builtin_profile_dir = Unicode(
107 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
107 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
108 )
108 )
109
109
110 config_file_paths = List(Unicode)
110 config_file_paths = List(Unicode)
111 def _config_file_paths_default(self):
111 def _config_file_paths_default(self):
112 return [py3compat.getcwd()]
112 return [py3compat.getcwd()]
113
113
114 extra_config_file = Unicode(config=True,
114 extra_config_file = Unicode(config=True,
115 help="""Path to an extra config file to load.
115 help="""Path to an extra config file to load.
116
116
117 If specified, load this config file in addition to any other IPython config.
117 If specified, load this config file in addition to any other IPython config.
118 """)
118 """)
119 def _extra_config_file_changed(self, name, old, new):
119 def _extra_config_file_changed(self, name, old, new):
120 try:
120 try:
121 self.config_files.remove(old)
121 self.config_files.remove(old)
122 except ValueError:
122 except ValueError:
123 pass
123 pass
124 self.config_file_specified.add(new)
124 self.config_file_specified.add(new)
125 self.config_files.append(new)
125 self.config_files.append(new)
126
126
127 profile = Unicode(u'default', config=True,
127 profile = Unicode(u'default', config=True,
128 help="""The IPython profile to use."""
128 help="""The IPython profile to use."""
129 )
129 )
130
130
131 def _profile_changed(self, name, old, new):
131 def _profile_changed(self, name, old, new):
132 self.builtin_profile_dir = os.path.join(
132 self.builtin_profile_dir = os.path.join(
133 get_ipython_package_dir(), u'config', u'profile', new
133 get_ipython_package_dir(), u'config', u'profile', new
134 )
134 )
135
135
136 ipython_dir = Unicode(config=True,
136 ipython_dir = Unicode(config=True,
137 help="""
137 help="""
138 The name of the IPython directory. This directory is used for logging
138 The name of the IPython directory. This directory is used for logging
139 configuration (through profiles), history storage, etc. The default
139 configuration (through profiles), history storage, etc. The default
140 is usually $HOME/.ipython. This option can also be specified through
140 is usually $HOME/.ipython. This option can also be specified through
141 the environment variable IPYTHONDIR.
141 the environment variable IPYTHONDIR.
142 """
142 """
143 )
143 )
144 def _ipython_dir_default(self):
144 def _ipython_dir_default(self):
145 d = get_ipython_dir()
145 d = get_ipython_dir()
146 self._ipython_dir_changed('ipython_dir', d, d)
146 self._ipython_dir_changed('ipython_dir', d, d)
147 return d
147 return d
148
148
149 _in_init_profile_dir = False
149 _in_init_profile_dir = False
150 profile_dir = Instance(ProfileDir, allow_none=True)
150 profile_dir = Instance(ProfileDir, allow_none=True)
151 def _profile_dir_default(self):
151 def _profile_dir_default(self):
152 # avoid recursion
152 # avoid recursion
153 if self._in_init_profile_dir:
153 if self._in_init_profile_dir:
154 return
154 return
155 # profile_dir requested early, force initialization
155 # profile_dir requested early, force initialization
156 self.init_profile_dir()
156 self.init_profile_dir()
157 return self.profile_dir
157 return self.profile_dir
158
158
159 overwrite = Bool(False, config=True,
159 overwrite = Bool(False, config=True,
160 help="""Whether to overwrite existing config files when copying""")
160 help="""Whether to overwrite existing config files when copying""")
161 auto_create = Bool(False, config=True,
161 auto_create = Bool(False, config=True,
162 help="""Whether to create profile dir if it doesn't exist""")
162 help="""Whether to create profile dir if it doesn't exist""")
163
163
164 config_files = List(Unicode)
164 config_files = List(Unicode)
165 def _config_files_default(self):
165 def _config_files_default(self):
166 return [self.config_file_name]
166 return [self.config_file_name]
167
167
168 copy_config_files = Bool(False, config=True,
168 copy_config_files = Bool(False, config=True,
169 help="""Whether to install the default config files into the profile dir.
169 help="""Whether to install the default config files into the profile dir.
170 If a new profile is being created, and IPython contains config files for that
170 If a new profile is being created, and IPython contains config files for that
171 profile, then they will be staged into the new directory. Otherwise,
171 profile, then they will be staged into the new directory. Otherwise,
172 default config files will be automatically generated.
172 default config files will be automatically generated.
173 """)
173 """)
174
174
175 verbose_crash = Bool(False, config=True,
175 verbose_crash = Bool(False, config=True,
176 help="""Create a massive crash report when IPython encounters what may be an
176 help="""Create a massive crash report when IPython encounters what may be an
177 internal error. The default is to append a short message to the
177 internal error. The default is to append a short message to the
178 usual traceback""")
178 usual traceback""")
179
179
180 # The class to use as the crash handler.
180 # The class to use as the crash handler.
181 crash_handler_class = Type(crashhandler.CrashHandler)
181 crash_handler_class = Type(crashhandler.CrashHandler)
182
182
183 @catch_config_error
183 @catch_config_error
184 def __init__(self, **kwargs):
184 def __init__(self, **kwargs):
185 super(BaseIPythonApplication, self).__init__(**kwargs)
185 super(BaseIPythonApplication, self).__init__(**kwargs)
186 # ensure current working directory exists
186 # ensure current working directory exists
187 try:
187 try:
188 directory = py3compat.getcwd()
188 directory = py3compat.getcwd()
189 except:
189 except:
190 # exit if cwd doesn't exist
190 # exit if cwd doesn't exist
191 self.log.error("Current working directory doesn't exist.")
191 self.log.error("Current working directory doesn't exist.")
192 self.exit(1)
192 self.exit(1)
193
193
194 #-------------------------------------------------------------------------
194 #-------------------------------------------------------------------------
195 # Various stages of Application creation
195 # Various stages of Application creation
196 #-------------------------------------------------------------------------
196 #-------------------------------------------------------------------------
197
197
198 def init_crash_handler(self):
198 def init_crash_handler(self):
199 """Create a crash handler, typically setting sys.excepthook to it."""
199 """Create a crash handler, typically setting sys.excepthook to it."""
200 self.crash_handler = self.crash_handler_class(self)
200 self.crash_handler = self.crash_handler_class(self)
201 sys.excepthook = self.excepthook
201 sys.excepthook = self.excepthook
202 def unset_crashhandler():
202 def unset_crashhandler():
203 sys.excepthook = sys.__excepthook__
203 sys.excepthook = sys.__excepthook__
204 atexit.register(unset_crashhandler)
204 atexit.register(unset_crashhandler)
205
205
206 def excepthook(self, etype, evalue, tb):
206 def excepthook(self, etype, evalue, tb):
207 """this is sys.excepthook after init_crashhandler
207 """this is sys.excepthook after init_crashhandler
208
208
209 set self.verbose_crash=True to use our full crashhandler, instead of
209 set self.verbose_crash=True to use our full crashhandler, instead of
210 a regular traceback with a short message (crash_handler_lite)
210 a regular traceback with a short message (crash_handler_lite)
211 """
211 """
212
212
213 if self.verbose_crash:
213 if self.verbose_crash:
214 return self.crash_handler(etype, evalue, tb)
214 return self.crash_handler(etype, evalue, tb)
215 else:
215 else:
216 return crashhandler.crash_handler_lite(etype, evalue, tb)
216 return crashhandler.crash_handler_lite(etype, evalue, tb)
217
217
218 def _ipython_dir_changed(self, name, old, new):
218 def _ipython_dir_changed(self, name, old, new):
219 if old is not Undefined:
219 if old is not Undefined:
220 str_old = py3compat.cast_bytes_py2(os.path.abspath(old),
220 str_old = py3compat.cast_bytes_py2(os.path.abspath(old),
221 sys.getfilesystemencoding()
221 sys.getfilesystemencoding()
222 )
222 )
223 if str_old in sys.path:
223 if str_old in sys.path:
224 sys.path.remove(str_old)
224 sys.path.remove(str_old)
225 str_path = py3compat.cast_bytes_py2(os.path.abspath(new),
225 str_path = py3compat.cast_bytes_py2(os.path.abspath(new),
226 sys.getfilesystemencoding()
226 sys.getfilesystemencoding()
227 )
227 )
228 sys.path.append(str_path)
228 sys.path.append(str_path)
229 ensure_dir_exists(new)
229 ensure_dir_exists(new)
230 readme = os.path.join(new, 'README')
230 readme = os.path.join(new, 'README')
231 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
231 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
232 if not os.path.exists(readme) and os.path.exists(readme_src):
232 if not os.path.exists(readme) and os.path.exists(readme_src):
233 shutil.copy(readme_src, readme)
233 shutil.copy(readme_src, readme)
234 for d in ('extensions', 'nbextensions'):
234 for d in ('extensions', 'nbextensions'):
235 path = os.path.join(new, d)
235 path = os.path.join(new, d)
236 try:
236 try:
237 ensure_dir_exists(path)
237 ensure_dir_exists(path)
238 except OSError:
238 except OSError:
239 # this will not be EEXIST
239 # this will not be EEXIST
240 self.log.error("couldn't create path %s: %s", path, e)
240 self.log.error("couldn't create path %s: %s", path, e)
241 self.log.debug("IPYTHONDIR set to: %s" % new)
241 self.log.debug("IPYTHONDIR set to: %s" % new)
242
242
243 def load_config_file(self, suppress_errors=True):
243 def load_config_file(self, suppress_errors=True):
244 """Load the config file.
244 """Load the config file.
245
245
246 By default, errors in loading config are handled, and a warning
246 By default, errors in loading config are handled, and a warning
247 printed on screen. For testing, the suppress_errors option is set
247 printed on screen. For testing, the suppress_errors option is set
248 to False, so errors will make tests fail.
248 to False, so errors will make tests fail.
249 """
249 """
250 self.log.debug("Searching path %s for config files", self.config_file_paths)
250 self.log.debug("Searching path %s for config files", self.config_file_paths)
251 base_config = 'ipython_config.py'
251 base_config = 'ipython_config.py'
252 self.log.debug("Attempting to load config file: %s" %
252 self.log.debug("Attempting to load config file: %s" %
253 base_config)
253 base_config)
254 try:
254 try:
255 Application.load_config_file(
255 Application.load_config_file(
256 self,
256 self,
257 base_config,
257 base_config,
258 path=self.config_file_paths
258 path=self.config_file_paths
259 )
259 )
260 except ConfigFileNotFound:
260 except ConfigFileNotFound:
261 # ignore errors loading parent
261 # ignore errors loading parent
262 self.log.debug("Config file %s not found", base_config)
262 self.log.debug("Config file %s not found", base_config)
263 pass
263 pass
264
264
265 for config_file_name in self.config_files:
265 for config_file_name in self.config_files:
266 if not config_file_name or config_file_name == base_config:
266 if not config_file_name or config_file_name == base_config:
267 continue
267 continue
268 self.log.debug("Attempting to load config file: %s" %
268 self.log.debug("Attempting to load config file: %s" %
269 self.config_file_name)
269 self.config_file_name)
270 try:
270 try:
271 Application.load_config_file(
271 Application.load_config_file(
272 self,
272 self,
273 config_file_name,
273 config_file_name,
274 path=self.config_file_paths
274 path=self.config_file_paths
275 )
275 )
276 except ConfigFileNotFound:
276 except ConfigFileNotFound:
277 # Only warn if the default config file was NOT being used.
277 # Only warn if the default config file was NOT being used.
278 if config_file_name in self.config_file_specified:
278 if config_file_name in self.config_file_specified:
279 msg = self.log.warn
279 msg = self.log.warn
280 else:
280 else:
281 msg = self.log.debug
281 msg = self.log.debug
282 msg("Config file not found, skipping: %s", config_file_name)
282 msg("Config file not found, skipping: %s", config_file_name)
283 except:
283 except Exception:
284 # For testing purposes.
284 # For testing purposes.
285 if not suppress_errors:
285 if not suppress_errors:
286 raise
286 raise
287 self.log.warn("Error loading config file: %s" %
287 self.log.warn("Error loading config file: %s" %
288 self.config_file_name, exc_info=True)
288 self.config_file_name, exc_info=True)
289
289
290 def init_profile_dir(self):
290 def init_profile_dir(self):
291 """initialize the profile dir"""
291 """initialize the profile dir"""
292 self._in_init_profile_dir = True
292 self._in_init_profile_dir = True
293 if self.profile_dir is not None:
293 if self.profile_dir is not None:
294 # already ran
294 # already ran
295 return
295 return
296 if 'ProfileDir.location' not in self.config:
296 if 'ProfileDir.location' not in self.config:
297 # location not specified, find by profile name
297 # location not specified, find by profile name
298 try:
298 try:
299 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
299 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
300 except ProfileDirError:
300 except ProfileDirError:
301 # not found, maybe create it (always create default profile)
301 # not found, maybe create it (always create default profile)
302 if self.auto_create or self.profile == 'default':
302 if self.auto_create or self.profile == 'default':
303 try:
303 try:
304 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
304 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
305 except ProfileDirError:
305 except ProfileDirError:
306 self.log.fatal("Could not create profile: %r"%self.profile)
306 self.log.fatal("Could not create profile: %r"%self.profile)
307 self.exit(1)
307 self.exit(1)
308 else:
308 else:
309 self.log.info("Created profile dir: %r"%p.location)
309 self.log.info("Created profile dir: %r"%p.location)
310 else:
310 else:
311 self.log.fatal("Profile %r not found."%self.profile)
311 self.log.fatal("Profile %r not found."%self.profile)
312 self.exit(1)
312 self.exit(1)
313 else:
313 else:
314 self.log.debug("Using existing profile dir: %r"%p.location)
314 self.log.debug("Using existing profile dir: %r"%p.location)
315 else:
315 else:
316 location = self.config.ProfileDir.location
316 location = self.config.ProfileDir.location
317 # location is fully specified
317 # location is fully specified
318 try:
318 try:
319 p = ProfileDir.find_profile_dir(location, self.config)
319 p = ProfileDir.find_profile_dir(location, self.config)
320 except ProfileDirError:
320 except ProfileDirError:
321 # not found, maybe create it
321 # not found, maybe create it
322 if self.auto_create:
322 if self.auto_create:
323 try:
323 try:
324 p = ProfileDir.create_profile_dir(location, self.config)
324 p = ProfileDir.create_profile_dir(location, self.config)
325 except ProfileDirError:
325 except ProfileDirError:
326 self.log.fatal("Could not create profile directory: %r"%location)
326 self.log.fatal("Could not create profile directory: %r"%location)
327 self.exit(1)
327 self.exit(1)
328 else:
328 else:
329 self.log.debug("Creating new profile dir: %r"%location)
329 self.log.debug("Creating new profile dir: %r"%location)
330 else:
330 else:
331 self.log.fatal("Profile directory %r not found."%location)
331 self.log.fatal("Profile directory %r not found."%location)
332 self.exit(1)
332 self.exit(1)
333 else:
333 else:
334 self.log.info("Using existing profile dir: %r"%location)
334 self.log.info("Using existing profile dir: %r"%location)
335 # if profile_dir is specified explicitly, set profile name
335 # if profile_dir is specified explicitly, set profile name
336 dir_name = os.path.basename(p.location)
336 dir_name = os.path.basename(p.location)
337 if dir_name.startswith('profile_'):
337 if dir_name.startswith('profile_'):
338 self.profile = dir_name[8:]
338 self.profile = dir_name[8:]
339
339
340 self.profile_dir = p
340 self.profile_dir = p
341 self.config_file_paths.append(p.location)
341 self.config_file_paths.append(p.location)
342 self._in_init_profile_dir = False
342 self._in_init_profile_dir = False
343
343
344 def init_config_files(self):
344 def init_config_files(self):
345 """[optionally] copy default config files into profile dir."""
345 """[optionally] copy default config files into profile dir."""
346 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
346 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
347 # copy config files
347 # copy config files
348 path = self.builtin_profile_dir
348 path = self.builtin_profile_dir
349 if self.copy_config_files:
349 if self.copy_config_files:
350 src = self.profile
350 src = self.profile
351
351
352 cfg = self.config_file_name
352 cfg = self.config_file_name
353 if path and os.path.exists(os.path.join(path, cfg)):
353 if path and os.path.exists(os.path.join(path, cfg)):
354 self.log.warn("Staging %r from %s into %r [overwrite=%s]"%(
354 self.log.warn("Staging %r from %s into %r [overwrite=%s]"%(
355 cfg, src, self.profile_dir.location, self.overwrite)
355 cfg, src, self.profile_dir.location, self.overwrite)
356 )
356 )
357 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
357 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
358 else:
358 else:
359 self.stage_default_config_file()
359 self.stage_default_config_file()
360 else:
360 else:
361 # Still stage *bundled* config files, but not generated ones
361 # Still stage *bundled* config files, but not generated ones
362 # This is necessary for `ipython profile=sympy` to load the profile
362 # This is necessary for `ipython profile=sympy` to load the profile
363 # on the first go
363 # on the first go
364 files = glob.glob(os.path.join(path, '*.py'))
364 files = glob.glob(os.path.join(path, '*.py'))
365 for fullpath in files:
365 for fullpath in files:
366 cfg = os.path.basename(fullpath)
366 cfg = os.path.basename(fullpath)
367 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
367 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
368 # file was copied
368 # file was copied
369 self.log.warn("Staging bundled %s from %s into %r"%(
369 self.log.warn("Staging bundled %s from %s into %r"%(
370 cfg, self.profile, self.profile_dir.location)
370 cfg, self.profile, self.profile_dir.location)
371 )
371 )
372
372
373
373
374 def stage_default_config_file(self):
374 def stage_default_config_file(self):
375 """auto generate default config file, and stage it into the profile."""
375 """auto generate default config file, and stage it into the profile."""
376 s = self.generate_config_file()
376 s = self.generate_config_file()
377 fname = os.path.join(self.profile_dir.location, self.config_file_name)
377 fname = os.path.join(self.profile_dir.location, self.config_file_name)
378 if self.overwrite or not os.path.exists(fname):
378 if self.overwrite or not os.path.exists(fname):
379 self.log.warn("Generating default config file: %r"%(fname))
379 self.log.warn("Generating default config file: %r"%(fname))
380 with open(fname, 'w') as f:
380 with open(fname, 'w') as f:
381 f.write(s)
381 f.write(s)
382
382
383 @catch_config_error
383 @catch_config_error
384 def initialize(self, argv=None):
384 def initialize(self, argv=None):
385 # don't hook up crash handler before parsing command-line
385 # don't hook up crash handler before parsing command-line
386 self.parse_command_line(argv)
386 self.parse_command_line(argv)
387 self.init_crash_handler()
387 self.init_crash_handler()
388 if self.subapp is not None:
388 if self.subapp is not None:
389 # stop here if subapp is taking over
389 # stop here if subapp is taking over
390 return
390 return
391 cl_config = self.config
391 cl_config = self.config
392 self.init_profile_dir()
392 self.init_profile_dir()
393 self.init_config_files()
393 self.init_config_files()
394 self.load_config_file()
394 self.load_config_file()
395 # enforce cl-opts override configfile opts:
395 # enforce cl-opts override configfile opts:
396 self.update_config(cl_config)
396 self.update_config(cl_config)
397
397
General Comments 0
You need to be logged in to leave comments. Login now