##// END OF EJS Templates
Fix typo enconters->encounters
Jason Grout -
Show More
@@ -1,336 +1,336
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 componenets.
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 Authors:
12 12
13 13 * Brian Granger
14 14 * Fernando Perez
15 15 * Min RK
16 16
17 17 """
18 18
19 19 #-----------------------------------------------------------------------------
20 20 # Copyright (C) 2008-2011 The IPython Development Team
21 21 #
22 22 # Distributed under the terms of the BSD License. The full license is in
23 23 # the file COPYING, distributed as part of this software.
24 24 #-----------------------------------------------------------------------------
25 25
26 26 #-----------------------------------------------------------------------------
27 27 # Imports
28 28 #-----------------------------------------------------------------------------
29 29
30 30 import atexit
31 31 import glob
32 32 import logging
33 33 import os
34 34 import shutil
35 35 import sys
36 36
37 37 from IPython.config.application import Application, catch_config_error
38 38 from IPython.config.configurable import Configurable
39 39 from IPython.config.loader import Config, ConfigFileNotFound
40 40 from IPython.core import release, crashhandler
41 41 from IPython.core.profiledir import ProfileDir, ProfileDirError
42 42 from IPython.utils.path import get_ipython_dir, get_ipython_package_dir
43 43 from IPython.utils.traitlets import List, Unicode, Type, Bool, Dict
44 44 from IPython.utils import py3compat
45 45
46 46 #-----------------------------------------------------------------------------
47 47 # Classes and functions
48 48 #-----------------------------------------------------------------------------
49 49
50 50
51 51 #-----------------------------------------------------------------------------
52 52 # Base Application Class
53 53 #-----------------------------------------------------------------------------
54 54
55 55 # aliases and flags
56 56
57 57 base_aliases = {
58 58 'profile' : 'BaseIPythonApplication.profile',
59 59 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
60 60 'log-level' : 'Application.log_level',
61 61 }
62 62
63 63 base_flags = dict(
64 64 debug = ({'Application' : {'log_level' : logging.DEBUG}},
65 65 "set log level to logging.DEBUG (maximize logging output)"),
66 66 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
67 67 "set log level to logging.CRITICAL (minimize logging output)"),
68 68 init = ({'BaseIPythonApplication' : {
69 69 'copy_config_files' : True,
70 70 'auto_create' : True}
71 71 }, """Initialize profile with default config files. This is equivalent
72 72 to running `ipython profile create <profile>` prior to startup.
73 73 """)
74 74 )
75 75
76 76
77 77 class BaseIPythonApplication(Application):
78 78
79 79 name = Unicode(u'ipython')
80 80 description = Unicode(u'IPython: an enhanced interactive Python shell.')
81 81 version = Unicode(release.version)
82 82
83 83 aliases = Dict(base_aliases)
84 84 flags = Dict(base_flags)
85 85 classes = List([ProfileDir])
86 86
87 87 # Track whether the config_file has changed,
88 88 # because some logic happens only if we aren't using the default.
89 89 config_file_specified = Bool(False)
90 90
91 91 config_file_name = Unicode(u'ipython_config.py')
92 92 def _config_file_name_default(self):
93 93 return self.name.replace('-','_') + u'_config.py'
94 94 def _config_file_name_changed(self, name, old, new):
95 95 if new != old:
96 96 self.config_file_specified = True
97 97
98 98 # The directory that contains IPython's builtin profiles.
99 99 builtin_profile_dir = Unicode(
100 100 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
101 101 )
102 102
103 103 config_file_paths = List(Unicode)
104 104 def _config_file_paths_default(self):
105 105 return [os.getcwdu()]
106 106
107 107 profile = Unicode(u'default', config=True,
108 108 help="""The IPython profile to use."""
109 109 )
110 110
111 111 def _profile_changed(self, name, old, new):
112 112 self.builtin_profile_dir = os.path.join(
113 113 get_ipython_package_dir(), u'config', u'profile', new
114 114 )
115 115
116 116 ipython_dir = Unicode(get_ipython_dir(), config=True,
117 117 help="""
118 118 The name of the IPython directory. This directory is used for logging
119 119 configuration (through profiles), history storage, etc. The default
120 120 is usually $HOME/.ipython. This options can also be specified through
121 121 the environment variable IPYTHONDIR.
122 122 """
123 123 )
124 124
125 125 overwrite = Bool(False, config=True,
126 126 help="""Whether to overwrite existing config files when copying""")
127 127 auto_create = Bool(False, config=True,
128 128 help="""Whether to create profile dir if it doesn't exist""")
129 129
130 130 config_files = List(Unicode)
131 131 def _config_files_default(self):
132 132 return [u'ipython_config.py']
133 133
134 134 copy_config_files = Bool(False, config=True,
135 135 help="""Whether to install the default config files into the profile dir.
136 136 If a new profile is being created, and IPython contains config files for that
137 137 profile, then they will be staged into the new directory. Otherwise,
138 138 default config files will be automatically generated.
139 139 """)
140 140
141 141 verbose_crash = Bool(False, config=True,
142 help="""Create a massive crash report when IPython enconters what may be an
142 help="""Create a massive crash report when IPython encounters what may be an
143 143 internal error. The default is to append a short message to the
144 144 usual traceback""")
145 145
146 146 # The class to use as the crash handler.
147 147 crash_handler_class = Type(crashhandler.CrashHandler)
148 148
149 149 def __init__(self, **kwargs):
150 150 super(BaseIPythonApplication, self).__init__(**kwargs)
151 151 # ensure even default IPYTHONDIR exists
152 152 if not os.path.exists(self.ipython_dir):
153 153 self._ipython_dir_changed('ipython_dir', self.ipython_dir, self.ipython_dir)
154 154
155 155 #-------------------------------------------------------------------------
156 156 # Various stages of Application creation
157 157 #-------------------------------------------------------------------------
158 158
159 159 def init_crash_handler(self):
160 160 """Create a crash handler, typically setting sys.excepthook to it."""
161 161 self.crash_handler = self.crash_handler_class(self)
162 162 sys.excepthook = self.excepthook
163 163 def unset_crashhandler():
164 164 sys.excepthook = sys.__excepthook__
165 165 atexit.register(unset_crashhandler)
166 166
167 167 def excepthook(self, etype, evalue, tb):
168 168 """this is sys.excepthook after init_crashhandler
169 169
170 170 set self.verbose_crash=True to use our full crashhandler, instead of
171 171 a regular traceback with a short message (crash_handler_lite)
172 172 """
173 173
174 174 if self.verbose_crash:
175 175 return self.crash_handler(etype, evalue, tb)
176 176 else:
177 177 return crashhandler.crash_handler_lite(etype, evalue, tb)
178 178
179 179 def _ipython_dir_changed(self, name, old, new):
180 180 if old in sys.path:
181 181 sys.path.remove(old)
182 182 sys.path.append(os.path.abspath(new))
183 183 if not os.path.isdir(new):
184 184 os.makedirs(new, mode=0777)
185 185 readme = os.path.join(new, 'README')
186 186 if not os.path.exists(readme):
187 187 path = os.path.join(get_ipython_package_dir(), u'config', u'profile')
188 188 shutil.copy(os.path.join(path, 'README'), readme)
189 189 self.log.debug("IPYTHONDIR set to: %s" % new)
190 190
191 191 def load_config_file(self, suppress_errors=True):
192 192 """Load the config file.
193 193
194 194 By default, errors in loading config are handled, and a warning
195 195 printed on screen. For testing, the suppress_errors option is set
196 196 to False, so errors will make tests fail.
197 197 """
198 198 self.log.debug("Searching path %s for config files", self.config_file_paths)
199 199 base_config = 'ipython_config.py'
200 200 self.log.debug("Attempting to load config file: %s" %
201 201 base_config)
202 202 try:
203 203 Application.load_config_file(
204 204 self,
205 205 base_config,
206 206 path=self.config_file_paths
207 207 )
208 208 except ConfigFileNotFound:
209 209 # ignore errors loading parent
210 210 self.log.debug("Config file %s not found", base_config)
211 211 pass
212 212 if self.config_file_name == base_config:
213 213 # don't load secondary config
214 214 return
215 215 self.log.debug("Attempting to load config file: %s" %
216 216 self.config_file_name)
217 217 try:
218 218 Application.load_config_file(
219 219 self,
220 220 self.config_file_name,
221 221 path=self.config_file_paths
222 222 )
223 223 except ConfigFileNotFound:
224 224 # Only warn if the default config file was NOT being used.
225 225 if self.config_file_specified:
226 226 msg = self.log.warn
227 227 else:
228 228 msg = self.log.debug
229 229 msg("Config file not found, skipping: %s", self.config_file_name)
230 230 except:
231 231 # For testing purposes.
232 232 if not suppress_errors:
233 233 raise
234 234 self.log.warn("Error loading config file: %s" %
235 235 self.config_file_name, exc_info=True)
236 236
237 237 def init_profile_dir(self):
238 238 """initialize the profile dir"""
239 239 try:
240 240 # location explicitly specified:
241 241 location = self.config.ProfileDir.location
242 242 except AttributeError:
243 243 # location not specified, find by profile name
244 244 try:
245 245 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
246 246 except ProfileDirError:
247 247 # not found, maybe create it (always create default profile)
248 248 if self.auto_create or self.profile=='default':
249 249 try:
250 250 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
251 251 except ProfileDirError:
252 252 self.log.fatal("Could not create profile: %r"%self.profile)
253 253 self.exit(1)
254 254 else:
255 255 self.log.info("Created profile dir: %r"%p.location)
256 256 else:
257 257 self.log.fatal("Profile %r not found."%self.profile)
258 258 self.exit(1)
259 259 else:
260 260 self.log.info("Using existing profile dir: %r"%p.location)
261 261 else:
262 262 # location is fully specified
263 263 try:
264 264 p = ProfileDir.find_profile_dir(location, self.config)
265 265 except ProfileDirError:
266 266 # not found, maybe create it
267 267 if self.auto_create:
268 268 try:
269 269 p = ProfileDir.create_profile_dir(location, self.config)
270 270 except ProfileDirError:
271 271 self.log.fatal("Could not create profile directory: %r"%location)
272 272 self.exit(1)
273 273 else:
274 274 self.log.info("Creating new profile dir: %r"%location)
275 275 else:
276 276 self.log.fatal("Profile directory %r not found."%location)
277 277 self.exit(1)
278 278 else:
279 279 self.log.info("Using existing profile dir: %r"%location)
280 280
281 281 self.profile_dir = p
282 282 self.config_file_paths.append(p.location)
283 283
284 284 def init_config_files(self):
285 285 """[optionally] copy default config files into profile dir."""
286 286 # copy config files
287 287 path = self.builtin_profile_dir
288 288 if self.copy_config_files:
289 289 src = self.profile
290 290
291 291 cfg = self.config_file_name
292 292 if path and os.path.exists(os.path.join(path, cfg)):
293 293 self.log.warn("Staging %r from %s into %r [overwrite=%s]"%(
294 294 cfg, src, self.profile_dir.location, self.overwrite)
295 295 )
296 296 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
297 297 else:
298 298 self.stage_default_config_file()
299 299 else:
300 300 # Still stage *bundled* config files, but not generated ones
301 301 # This is necessary for `ipython profile=sympy` to load the profile
302 302 # on the first go
303 303 files = glob.glob(os.path.join(path, '*.py'))
304 304 for fullpath in files:
305 305 cfg = os.path.basename(fullpath)
306 306 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
307 307 # file was copied
308 308 self.log.warn("Staging bundled %s from %s into %r"%(
309 309 cfg, self.profile, self.profile_dir.location)
310 310 )
311 311
312 312
313 313 def stage_default_config_file(self):
314 314 """auto generate default config file, and stage it into the profile."""
315 315 s = self.generate_config_file()
316 316 fname = os.path.join(self.profile_dir.location, self.config_file_name)
317 317 if self.overwrite or not os.path.exists(fname):
318 318 self.log.warn("Generating default config file: %r"%(fname))
319 319 with open(fname, 'w') as f:
320 320 f.write(s)
321 321
322 322 @catch_config_error
323 323 def initialize(self, argv=None):
324 324 # don't hook up crash handler before parsing command-line
325 325 self.parse_command_line(argv)
326 326 self.init_crash_handler()
327 327 if self.subapp is not None:
328 328 # stop here if subapp is taking over
329 329 return
330 330 cl_config = self.config
331 331 self.init_profile_dir()
332 332 self.init_config_files()
333 333 self.load_config_file()
334 334 # enforce cl-opts override configfile opts:
335 335 self.update_config(cl_config)
336 336
General Comments 0
You need to be logged in to leave comments. Login now