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