##// END OF EJS Templates
log.warn -> log.warning in application.py
Pierre Gerold -
Show More
@@ -1,410 +1,409 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 py3compat.getcwd()
188 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 initialize_subcommand(self, subc, argv=None):
198 def initialize_subcommand(self, subc, argv=None):
199 if subc in self.deprecated_subcommands:
199 if subc in self.deprecated_subcommands:
200 import time
200 import time
201 self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed "
201 self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed "
202 "in future versions.".format(sub=subc))
202 "in future versions.".format(sub=subc))
203 self.log.warning("You likely want to use `jupyter {sub}`... continue "
203 self.log.warning("You likely want to use `jupyter {sub}`... continue "
204 "in 5 sec. Press Ctrl-C to quit now.".format(sub=subc))
204 "in 5 sec. Press Ctrl-C to quit now.".format(sub=subc))
205 try:
205 try:
206 time.sleep(5)
206 time.sleep(5)
207 except KeyboardInterrupt:
207 except KeyboardInterrupt:
208 sys.exit(1)
208 sys.exit(1)
209 return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv)
209 return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv)
210
210
211 def init_crash_handler(self):
211 def init_crash_handler(self):
212 """Create a crash handler, typically setting sys.excepthook to it."""
212 """Create a crash handler, typically setting sys.excepthook to it."""
213 self.crash_handler = self.crash_handler_class(self)
213 self.crash_handler = self.crash_handler_class(self)
214 sys.excepthook = self.excepthook
214 sys.excepthook = self.excepthook
215 def unset_crashhandler():
215 def unset_crashhandler():
216 sys.excepthook = sys.__excepthook__
216 sys.excepthook = sys.__excepthook__
217 atexit.register(unset_crashhandler)
217 atexit.register(unset_crashhandler)
218
218
219 def excepthook(self, etype, evalue, tb):
219 def excepthook(self, etype, evalue, tb):
220 """this is sys.excepthook after init_crashhandler
220 """this is sys.excepthook after init_crashhandler
221
221
222 set self.verbose_crash=True to use our full crashhandler, instead of
222 set self.verbose_crash=True to use our full crashhandler, instead of
223 a regular traceback with a short message (crash_handler_lite)
223 a regular traceback with a short message (crash_handler_lite)
224 """
224 """
225
225
226 if self.verbose_crash:
226 if self.verbose_crash:
227 return self.crash_handler(etype, evalue, tb)
227 return self.crash_handler(etype, evalue, tb)
228 else:
228 else:
229 return crashhandler.crash_handler_lite(etype, evalue, tb)
229 return crashhandler.crash_handler_lite(etype, evalue, tb)
230
230
231 def _ipython_dir_changed(self, name, old, new):
231 def _ipython_dir_changed(self, name, old, new):
232 if old is not Undefined:
232 if old is not Undefined:
233 str_old = py3compat.cast_bytes_py2(os.path.abspath(old),
233 str_old = py3compat.cast_bytes_py2(os.path.abspath(old),
234 sys.getfilesystemencoding()
234 sys.getfilesystemencoding()
235 )
235 )
236 if str_old in sys.path:
236 if str_old in sys.path:
237 sys.path.remove(str_old)
237 sys.path.remove(str_old)
238 str_path = py3compat.cast_bytes_py2(os.path.abspath(new),
238 str_path = py3compat.cast_bytes_py2(os.path.abspath(new),
239 sys.getfilesystemencoding()
239 sys.getfilesystemencoding()
240 )
240 )
241 sys.path.append(str_path)
241 sys.path.append(str_path)
242 ensure_dir_exists(new)
242 ensure_dir_exists(new)
243 readme = os.path.join(new, 'README')
243 readme = os.path.join(new, 'README')
244 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
244 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
245 if not os.path.exists(readme) and os.path.exists(readme_src):
245 if not os.path.exists(readme) and os.path.exists(readme_src):
246 shutil.copy(readme_src, readme)
246 shutil.copy(readme_src, readme)
247 for d in ('extensions', 'nbextensions'):
247 for d in ('extensions', 'nbextensions'):
248 path = os.path.join(new, d)
248 path = os.path.join(new, d)
249 try:
249 try:
250 ensure_dir_exists(path)
250 ensure_dir_exists(path)
251 except OSError as e:
251 except OSError as e:
252 # this will not be EEXIST
252 # this will not be EEXIST
253 self.log.error("couldn't create path %s: %s", path, e)
253 self.log.error("couldn't create path %s: %s", path, e)
254 self.log.debug("IPYTHONDIR set to: %s" % new)
254 self.log.debug("IPYTHONDIR set to: %s" % new)
255
255
256 def load_config_file(self, suppress_errors=True):
256 def load_config_file(self, suppress_errors=True):
257 """Load the config file.
257 """Load the config file.
258
258
259 By default, errors in loading config are handled, and a warning
259 By default, errors in loading config are handled, and a warning
260 printed on screen. For testing, the suppress_errors option is set
260 printed on screen. For testing, the suppress_errors option is set
261 to False, so errors will make tests fail.
261 to False, so errors will make tests fail.
262 """
262 """
263 self.log.debug("Searching path %s for config files", self.config_file_paths)
263 self.log.debug("Searching path %s for config files", self.config_file_paths)
264 base_config = 'ipython_config.py'
264 base_config = 'ipython_config.py'
265 self.log.debug("Attempting to load config file: %s" %
265 self.log.debug("Attempting to load config file: %s" %
266 base_config)
266 base_config)
267 try:
267 try:
268 Application.load_config_file(
268 Application.load_config_file(
269 self,
269 self,
270 base_config,
270 base_config,
271 path=self.config_file_paths
271 path=self.config_file_paths
272 )
272 )
273 except ConfigFileNotFound:
273 except ConfigFileNotFound:
274 # ignore errors loading parent
274 # ignore errors loading parent
275 self.log.debug("Config file %s not found", base_config)
275 self.log.debug("Config file %s not found", base_config)
276 pass
276 pass
277
277
278 for config_file_name in self.config_files:
278 for config_file_name in self.config_files:
279 if not config_file_name or config_file_name == base_config:
279 if not config_file_name or config_file_name == base_config:
280 continue
280 continue
281 self.log.debug("Attempting to load config file: %s" %
281 self.log.debug("Attempting to load config file: %s" %
282 self.config_file_name)
282 self.config_file_name)
283 try:
283 try:
284 Application.load_config_file(
284 Application.load_config_file(
285 self,
285 self,
286 config_file_name,
286 config_file_name,
287 path=self.config_file_paths
287 path=self.config_file_paths
288 )
288 )
289 except ConfigFileNotFound:
289 except ConfigFileNotFound:
290 # Only warn if the default config file was NOT being used.
290 # Only warn if the default config file was NOT being used.
291 if config_file_name in self.config_file_specified:
291 if config_file_name in self.config_file_specified:
292 msg = self.log.warn
292 msg = self.log.warning
293 else:
293 else:
294 msg = self.log.debug
294 msg = self.log.debug
295 msg("Config file not found, skipping: %s", config_file_name)
295 msg("Config file not found, skipping: %s", config_file_name)
296 except Exception:
296 except Exception:
297 # For testing purposes.
297 # For testing purposes.
298 if not suppress_errors:
298 if not suppress_errors:
299 raise
299 raise
300 self.log.warn("Error loading config file: %s" %
300 self.log.warning("Error loading config file: %s" %
301 self.config_file_name, exc_info=True)
301 self.config_file_name, exc_info=True)
302
302
303 def init_profile_dir(self):
303 def init_profile_dir(self):
304 """initialize the profile dir"""
304 """initialize the profile dir"""
305 self._in_init_profile_dir = True
305 self._in_init_profile_dir = True
306 if self.profile_dir is not None:
306 if self.profile_dir is not None:
307 # already ran
307 # already ran
308 return
308 return
309 if 'ProfileDir.location' not in self.config:
309 if 'ProfileDir.location' not in self.config:
310 # location not specified, find by profile name
310 # location not specified, find by profile name
311 try:
311 try:
312 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
312 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
313 except ProfileDirError:
313 except ProfileDirError:
314 # not found, maybe create it (always create default profile)
314 # not found, maybe create it (always create default profile)
315 if self.auto_create or self.profile == 'default':
315 if self.auto_create or self.profile == 'default':
316 try:
316 try:
317 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
317 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
318 except ProfileDirError:
318 except ProfileDirError:
319 self.log.fatal("Could not create profile: %r"%self.profile)
319 self.log.fatal("Could not create profile: %r"%self.profile)
320 self.exit(1)
320 self.exit(1)
321 else:
321 else:
322 self.log.info("Created profile dir: %r"%p.location)
322 self.log.info("Created profile dir: %r"%p.location)
323 else:
323 else:
324 self.log.fatal("Profile %r not found."%self.profile)
324 self.log.fatal("Profile %r not found."%self.profile)
325 self.exit(1)
325 self.exit(1)
326 else:
326 else:
327 self.log.debug("Using existing profile dir: %r"%p.location)
327 self.log.debug("Using existing profile dir: %r"%p.location)
328 else:
328 else:
329 location = self.config.ProfileDir.location
329 location = self.config.ProfileDir.location
330 # location is fully specified
330 # location is fully specified
331 try:
331 try:
332 p = ProfileDir.find_profile_dir(location, self.config)
332 p = ProfileDir.find_profile_dir(location, self.config)
333 except ProfileDirError:
333 except ProfileDirError:
334 # not found, maybe create it
334 # not found, maybe create it
335 if self.auto_create:
335 if self.auto_create:
336 try:
336 try:
337 p = ProfileDir.create_profile_dir(location, self.config)
337 p = ProfileDir.create_profile_dir(location, self.config)
338 except ProfileDirError:
338 except ProfileDirError:
339 self.log.fatal("Could not create profile directory: %r"%location)
339 self.log.fatal("Could not create profile directory: %r"%location)
340 self.exit(1)
340 self.exit(1)
341 else:
341 else:
342 self.log.debug("Creating new profile dir: %r"%location)
342 self.log.debug("Creating new profile dir: %r"%location)
343 else:
343 else:
344 self.log.fatal("Profile directory %r not found."%location)
344 self.log.fatal("Profile directory %r not found."%location)
345 self.exit(1)
345 self.exit(1)
346 else:
346 else:
347 self.log.info("Using existing profile dir: %r"%location)
347 self.log.info("Using existing profile dir: %r"%location)
348 # if profile_dir is specified explicitly, set profile name
348 # if profile_dir is specified explicitly, set profile name
349 dir_name = os.path.basename(p.location)
349 dir_name = os.path.basename(p.location)
350 if dir_name.startswith('profile_'):
350 if dir_name.startswith('profile_'):
351 self.profile = dir_name[8:]
351 self.profile = dir_name[8:]
352
352
353 self.profile_dir = p
353 self.profile_dir = p
354 self.config_file_paths.append(p.location)
354 self.config_file_paths.append(p.location)
355 self._in_init_profile_dir = False
355 self._in_init_profile_dir = False
356
356
357 def init_config_files(self):
357 def init_config_files(self):
358 """[optionally] copy default config files into profile dir."""
358 """[optionally] copy default config files into profile dir."""
359 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
359 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
360 # copy config files
360 # copy config files
361 path = self.builtin_profile_dir
361 path = self.builtin_profile_dir
362 if self.copy_config_files:
362 if self.copy_config_files:
363 src = self.profile
363 src = self.profile
364
364
365 cfg = self.config_file_name
365 cfg = self.config_file_name
366 if path and os.path.exists(os.path.join(path, cfg)):
366 if path and os.path.exists(os.path.join(path, cfg)):
367 self.log.warn("Staging %r from %s into %r [overwrite=%s]"%(
367 self.log.warning("Staging %r from %s into %r [overwrite=%s]"%(
368 cfg, src, self.profile_dir.location, self.overwrite)
368 cfg, src, self.profile_dir.location, self.overwrite)
369 )
369 )
370 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
370 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
371 else:
371 else:
372 self.stage_default_config_file()
372 self.stage_default_config_file()
373 else:
373 else:
374 # Still stage *bundled* config files, but not generated ones
374 # Still stage *bundled* config files, but not generated ones
375 # This is necessary for `ipython profile=sympy` to load the profile
375 # This is necessary for `ipython profile=sympy` to load the profile
376 # on the first go
376 # on the first go
377 files = glob.glob(os.path.join(path, '*.py'))
377 files = glob.glob(os.path.join(path, '*.py'))
378 for fullpath in files:
378 for fullpath in files:
379 cfg = os.path.basename(fullpath)
379 cfg = os.path.basename(fullpath)
380 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
380 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
381 # file was copied
381 # file was copied
382 self.log.warn("Staging bundled %s from %s into %r"%(
382 self.log.warning("Staging bundled %s from %s into %r"%(
383 cfg, self.profile, self.profile_dir.location)
383 cfg, self.profile, self.profile_dir.location)
384 )
384 )
385
385
386
386
387 def stage_default_config_file(self):
387 def stage_default_config_file(self):
388 """auto generate default config file, and stage it into the profile."""
388 """auto generate default config file, and stage it into the profile."""
389 s = self.generate_config_file()
389 s = self.generate_config_file()
390 fname = os.path.join(self.profile_dir.location, self.config_file_name)
390 fname = os.path.join(self.profile_dir.location, self.config_file_name)
391 if self.overwrite or not os.path.exists(fname):
391 if self.overwrite or not os.path.exists(fname):
392 self.log.warn("Generating default config file: %r"%(fname))
392 self.log.warning("Generating default config file: %r"%(fname))
393 with open(fname, 'w') as f:
393 with open(fname, 'w') as f:
394 f.write(s)
394 f.write(s)
395
395
396 @catch_config_error
396 @catch_config_error
397 def initialize(self, argv=None):
397 def initialize(self, argv=None):
398 # don't hook up crash handler before parsing command-line
398 # don't hook up crash handler before parsing command-line
399 self.parse_command_line(argv)
399 self.parse_command_line(argv)
400 self.init_crash_handler()
400 self.init_crash_handler()
401 if self.subapp is not None:
401 if self.subapp is not None:
402 # stop here if subapp is taking over
402 # stop here if subapp is taking over
403 return
403 return
404 cl_config = self.config
404 cl_config = self.config
405 self.init_profile_dir()
405 self.init_profile_dir()
406 self.init_config_files()
406 self.init_config_files()
407 self.load_config_file()
407 self.load_config_file()
408 # enforce cl-opts override configfile opts:
408 # enforce cl-opts override configfile opts:
409 self.update_config(cl_config)
409 self.update_config(cl_config)
410
General Comments 0
You need to be logged in to leave comments. Login now