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