##// END OF EJS Templates
Report if cwd does not exist and raise exception in BaseIPythonApplication...
Thomas Spura -
Show More
@@ -1,348 +1,342 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 147 def __init__(self, **kwargs):
148 148 super(BaseIPythonApplication, self).__init__(**kwargs)
149 149 # ensure current working directory exists
150 level_up = False
151 while True:
152 try:
153 directory = os.getcwdu()
154 except OSError:
155 # search level up until directory exists
156 os.chdir("..")
157 level_up = True
158 else:
159 if level_up:
160 self.log.warn("Current working directory doesn't exist.\nSetting to: %s"%(directory))
161 break
150 try:
151 directory = os.getcwdu()
152 except:
153 # raise exception
154 self.log.error("Current working directory doesn't exist.")
155 raise
162 156
163 157 # ensure even default IPYTHONDIR exists
164 158 if not os.path.exists(self.ipython_dir):
165 159 self._ipython_dir_changed('ipython_dir', self.ipython_dir, self.ipython_dir)
166 160
167 161 #-------------------------------------------------------------------------
168 162 # Various stages of Application creation
169 163 #-------------------------------------------------------------------------
170 164
171 165 def init_crash_handler(self):
172 166 """Create a crash handler, typically setting sys.excepthook to it."""
173 167 self.crash_handler = self.crash_handler_class(self)
174 168 sys.excepthook = self.excepthook
175 169 def unset_crashhandler():
176 170 sys.excepthook = sys.__excepthook__
177 171 atexit.register(unset_crashhandler)
178 172
179 173 def excepthook(self, etype, evalue, tb):
180 174 """this is sys.excepthook after init_crashhandler
181 175
182 176 set self.verbose_crash=True to use our full crashhandler, instead of
183 177 a regular traceback with a short message (crash_handler_lite)
184 178 """
185 179
186 180 if self.verbose_crash:
187 181 return self.crash_handler(etype, evalue, tb)
188 182 else:
189 183 return crashhandler.crash_handler_lite(etype, evalue, tb)
190 184
191 185 def _ipython_dir_changed(self, name, old, new):
192 186 if old in sys.path:
193 187 sys.path.remove(old)
194 188 sys.path.append(os.path.abspath(new))
195 189 if not os.path.isdir(new):
196 190 os.makedirs(new, mode=0o777)
197 191 readme = os.path.join(new, 'README')
198 192 if not os.path.exists(readme):
199 193 path = os.path.join(get_ipython_package_dir(), u'config', u'profile')
200 194 shutil.copy(os.path.join(path, 'README'), readme)
201 195 self.log.debug("IPYTHONDIR set to: %s" % new)
202 196
203 197 def load_config_file(self, suppress_errors=True):
204 198 """Load the config file.
205 199
206 200 By default, errors in loading config are handled, and a warning
207 201 printed on screen. For testing, the suppress_errors option is set
208 202 to False, so errors will make tests fail.
209 203 """
210 204 self.log.debug("Searching path %s for config files", self.config_file_paths)
211 205 base_config = 'ipython_config.py'
212 206 self.log.debug("Attempting to load config file: %s" %
213 207 base_config)
214 208 try:
215 209 Application.load_config_file(
216 210 self,
217 211 base_config,
218 212 path=self.config_file_paths
219 213 )
220 214 except ConfigFileNotFound:
221 215 # ignore errors loading parent
222 216 self.log.debug("Config file %s not found", base_config)
223 217 pass
224 218 if self.config_file_name == base_config:
225 219 # don't load secondary config
226 220 return
227 221 self.log.debug("Attempting to load config file: %s" %
228 222 self.config_file_name)
229 223 try:
230 224 Application.load_config_file(
231 225 self,
232 226 self.config_file_name,
233 227 path=self.config_file_paths
234 228 )
235 229 except ConfigFileNotFound:
236 230 # Only warn if the default config file was NOT being used.
237 231 if self.config_file_specified:
238 232 msg = self.log.warn
239 233 else:
240 234 msg = self.log.debug
241 235 msg("Config file not found, skipping: %s", self.config_file_name)
242 236 except:
243 237 # For testing purposes.
244 238 if not suppress_errors:
245 239 raise
246 240 self.log.warn("Error loading config file: %s" %
247 241 self.config_file_name, exc_info=True)
248 242
249 243 def init_profile_dir(self):
250 244 """initialize the profile dir"""
251 245 try:
252 246 # location explicitly specified:
253 247 location = self.config.ProfileDir.location
254 248 except AttributeError:
255 249 # location not specified, find by profile name
256 250 try:
257 251 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
258 252 except ProfileDirError:
259 253 # not found, maybe create it (always create default profile)
260 254 if self.auto_create or self.profile == 'default':
261 255 try:
262 256 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
263 257 except ProfileDirError:
264 258 self.log.fatal("Could not create profile: %r"%self.profile)
265 259 self.exit(1)
266 260 else:
267 261 self.log.info("Created profile dir: %r"%p.location)
268 262 else:
269 263 self.log.fatal("Profile %r not found."%self.profile)
270 264 self.exit(1)
271 265 else:
272 266 self.log.info("Using existing profile dir: %r"%p.location)
273 267 else:
274 268 # location is fully specified
275 269 try:
276 270 p = ProfileDir.find_profile_dir(location, self.config)
277 271 except ProfileDirError:
278 272 # not found, maybe create it
279 273 if self.auto_create:
280 274 try:
281 275 p = ProfileDir.create_profile_dir(location, self.config)
282 276 except ProfileDirError:
283 277 self.log.fatal("Could not create profile directory: %r"%location)
284 278 self.exit(1)
285 279 else:
286 280 self.log.info("Creating new profile dir: %r"%location)
287 281 else:
288 282 self.log.fatal("Profile directory %r not found."%location)
289 283 self.exit(1)
290 284 else:
291 285 self.log.info("Using existing profile dir: %r"%location)
292 286
293 287 self.profile_dir = p
294 288 self.config_file_paths.append(p.location)
295 289
296 290 def init_config_files(self):
297 291 """[optionally] copy default config files into profile dir."""
298 292 # copy config files
299 293 path = self.builtin_profile_dir
300 294 if self.copy_config_files:
301 295 src = self.profile
302 296
303 297 cfg = self.config_file_name
304 298 if path and os.path.exists(os.path.join(path, cfg)):
305 299 self.log.warn("Staging %r from %s into %r [overwrite=%s]"%(
306 300 cfg, src, self.profile_dir.location, self.overwrite)
307 301 )
308 302 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
309 303 else:
310 304 self.stage_default_config_file()
311 305 else:
312 306 # Still stage *bundled* config files, but not generated ones
313 307 # This is necessary for `ipython profile=sympy` to load the profile
314 308 # on the first go
315 309 files = glob.glob(os.path.join(path, '*.py'))
316 310 for fullpath in files:
317 311 cfg = os.path.basename(fullpath)
318 312 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
319 313 # file was copied
320 314 self.log.warn("Staging bundled %s from %s into %r"%(
321 315 cfg, self.profile, self.profile_dir.location)
322 316 )
323 317
324 318
325 319 def stage_default_config_file(self):
326 320 """auto generate default config file, and stage it into the profile."""
327 321 s = self.generate_config_file()
328 322 fname = os.path.join(self.profile_dir.location, self.config_file_name)
329 323 if self.overwrite or not os.path.exists(fname):
330 324 self.log.warn("Generating default config file: %r"%(fname))
331 325 with open(fname, 'w') as f:
332 326 f.write(s)
333 327
334 328 @catch_config_error
335 329 def initialize(self, argv=None):
336 330 # don't hook up crash handler before parsing command-line
337 331 self.parse_command_line(argv)
338 332 self.init_crash_handler()
339 333 if self.subapp is not None:
340 334 # stop here if subapp is taking over
341 335 return
342 336 cl_config = self.config
343 337 self.init_profile_dir()
344 338 self.init_config_files()
345 339 self.load_config_file()
346 340 # enforce cl-opts override configfile opts:
347 341 self.update_config(cl_config)
348 342
@@ -1,18 +1,25 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
14 import sys
15 import traceback
15 16
16 17 from IPython.parallel.apps.ipclusterapp import launch_new_instance
17 18
18 launch_new_instance()
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)
@@ -1,18 +1,25 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
14 import sys
15 import traceback
15 16
16 17 from IPython.parallel.apps.ipcontrollerapp import launch_new_instance
17 18
18 launch_new_instance()
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)
@@ -1,20 +1,25 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
14 import sys
15 import traceback
15 16
16 17 from IPython.parallel.apps.ipengineapp import launch_new_instance
17 18
18 launch_new_instance()
19
20
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)
@@ -1,20 +1,25 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
14 import sys
15 import traceback
15 16
16 17 from IPython.parallel.apps.iploggerapp import launch_new_instance
17 18
18 launch_new_instance()
19
20
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)
@@ -1,7 +1,15 b''
1 1 #!/usr/bin/env python
2 2 """Terminal-based IPython entry point.
3 3 """
4 import sys
5 import traceback
4 6
5 7 from IPython.frontend.terminal.ipapp import launch_new_instance
6 8
7 launch_new_instance()
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)
General Comments 0
You need to be logged in to leave comments. Login now