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