Show More
@@ -119,14 +119,13 b' class Application(object):' | |||
|
119 | 119 | argv = None |
|
120 | 120 | #: extra arguments computed by the command-line loader |
|
121 | 121 | extra_args = None |
|
122 | #: The class to use as the crash handler. | |
|
123 | crash_handler_class = crashhandler.CrashHandler | |
|
122 | 124 | |
|
123 | 125 | # Private attributes |
|
124 | 126 | _exiting = False |
|
125 | 127 | _initialized = False |
|
126 | 128 | |
|
127 | # Class choices for things that will be instantiated at runtime. | |
|
128 | _CrashHandler = crashhandler.CrashHandler | |
|
129 | ||
|
130 | 129 | def __init__(self, argv=None): |
|
131 | 130 | self.argv = sys.argv[1:] if argv is None else argv |
|
132 | 131 | self.init_logger() |
@@ -217,7 +216,7 b' class Application(object):' | |||
|
217 | 216 | |
|
218 | 217 | def create_crash_handler(self): |
|
219 | 218 | """Create a crash handler, typically setting sys.excepthook to it.""" |
|
220 |
self.crash_handler = self. |
|
|
219 | self.crash_handler = self.crash_handler_class(self) | |
|
221 | 220 | sys.excepthook = self.crash_handler |
|
222 | 221 | |
|
223 | 222 | def create_default_config(self): |
@@ -430,15 +429,6 b' class Application(object):' | |||
|
430 | 429 | # Utility methods |
|
431 | 430 | #------------------------------------------------------------------------- |
|
432 | 431 | |
|
433 | def abort(self): | |
|
434 | """Abort the starting of the application.""" | |
|
435 | if self._exiting: | |
|
436 | pass | |
|
437 | else: | |
|
438 | self.log.critical("Aborting application: %s" % self.name, exc_info=True) | |
|
439 | self._exiting = True | |
|
440 | sys.exit(1) | |
|
441 | ||
|
442 | 432 | def exit(self, exit_status=0): |
|
443 | 433 | if self._exiting: |
|
444 | 434 | pass |
@@ -447,17 +437,13 b' class Application(object):' | |||
|
447 | 437 | self._exiting = True |
|
448 | 438 | sys.exit(exit_status) |
|
449 | 439 | |
|
450 |
def attempt(self, func |
|
|
440 | def attempt(self, func): | |
|
451 | 441 | try: |
|
452 | 442 | func() |
|
453 | 443 | except SystemExit: |
|
454 | 444 | raise |
|
455 | 445 | except: |
|
456 | if action == 'abort': | |
|
457 | self.log.critical("Aborting application: %s" % self.name, | |
|
458 | exc_info=True) | |
|
459 | self.abort() | |
|
460 | raise | |
|
461 | elif action == 'exit': | |
|
462 | self.exit(0) | |
|
446 | self.log.critical("Aborting application: %s" % self.name, | |
|
447 | exc_info=True) | |
|
448 | self.exit(0) | |
|
463 | 449 |
@@ -1,124 +1,113 b'' | |||
|
1 |
# |
|
|
1 | # encoding: utf-8 | |
|
2 | 2 | """sys.excepthook for IPython itself, leaves a detailed report on disk. |
|
3 | 3 | |
|
4 | Authors: | |
|
4 | 5 | |
|
5 | Authors | |
|
6 | ------- | |
|
7 | - Fernando Perez <Fernando.Perez@berkeley.edu> | |
|
6 | * Fernando Perez | |
|
7 | * Brian E. Granger | |
|
8 | 8 | """ |
|
9 | 9 | |
|
10 | #***************************************************************************** | |
|
11 | # Copyright (C) 2008-2009 The IPython Development Team | |
|
12 | # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu> | |
|
10 | #----------------------------------------------------------------------------- | |
|
11 | # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu> | |
|
12 | # Copyright (C) 2008-2010 The IPython Development Team | |
|
13 | 13 | # |
|
14 | 14 | # Distributed under the terms of the BSD License. The full license is in |
|
15 | 15 | # the file COPYING, distributed as part of this software. |
|
16 | #***************************************************************************** | |
|
16 | #----------------------------------------------------------------------------- | |
|
17 | 17 | |
|
18 | #**************************************************************************** | |
|
19 | # Required modules | |
|
18 | #----------------------------------------------------------------------------- | |
|
19 | # Imports | |
|
20 | #----------------------------------------------------------------------------- | |
|
20 | 21 | |
|
21 | # From the standard library | |
|
22 | 22 | import os |
|
23 | 23 | import sys |
|
24 | 24 | from pprint import pformat |
|
25 | 25 | |
|
26 | # Our own | |
|
27 | from IPython.core import release | |
|
28 | 26 | from IPython.core import ultratb |
|
27 | from IPython.external.Itpl import itpl | |
|
29 | 28 | from IPython.utils.sysinfo import sys_info |
|
30 | 29 | |
|
31 | from IPython.external.Itpl import itpl | |
|
30 | #----------------------------------------------------------------------------- | |
|
31 | # Code | |
|
32 | #----------------------------------------------------------------------------- | |
|
32 | 33 | |
|
33 | #**************************************************************************** | |
|
34 | # Template for the user message. | |
|
35 | _default_message_template = """\ | |
|
36 | Oops, $self.app_name crashed. We do our best to make it stable, but... | |
|
34 | 37 | |
|
35 | class CrashHandler(object): | |
|
36 | """Customizable crash handlers for IPython-based systems. | |
|
38 | A crash report was automatically generated with the following information: | |
|
39 | - A verbatim copy of the crash traceback. | |
|
40 | - A copy of your input history during this session. | |
|
41 | - Data on your current $self.app_name configuration. | |
|
37 | 42 | |
|
38 | Instances of this class provide a __call__ method which can be used as a | |
|
39 | sys.excepthook, i.e., the __call__ signature is: | |
|
43 | It was left in the file named: | |
|
44 | \t'$self.crash_report_fname' | |
|
45 | If you can email this file to the developers, the information in it will help | |
|
46 | them in understanding and correcting the problem. | |
|
40 | 47 | |
|
41 | def __call__(self,etype, evalue, etb) | |
|
48 | You can mail it to: $self.contact_name at $self.contact_email | |
|
49 | with the subject '$self.app_name Crash Report'. | |
|
42 | 50 | |
|
43 | """ | |
|
51 | If you want to do it now, the following command will work (under Unix): | |
|
52 | mail -s '$self.app_name Crash Report' $self.contact_email < $self.crash_report_fname | |
|
53 | ||
|
54 | To ensure accurate tracking of this issue, please file a report about it at: | |
|
55 | $self.bug_tracker | |
|
56 | """ | |
|
44 | 57 | |
|
45 | def __init__(self,app, app_name, contact_name=None, contact_email=None, | |
|
46 | bug_tracker=None, crash_report_fname='CrashReport.txt', | |
|
47 | show_crash_traceback=True, call_pdb=False): | |
|
48 | """New crash handler. | |
|
49 | 58 | |
|
50 | Inputs: | |
|
59 | class CrashHandler(object): | |
|
60 | """Customizable crash handlers for IPython applications. | |
|
51 | 61 | |
|
52 | - app: a running application instance, which will be queried at crash | |
|
53 | time for internal information. | |
|
62 | Instances of this class provide a :meth:`__call__` method which can be | |
|
63 | used as a ``sys.excepthook``. The :meth:`__call__` signature is:: | |
|
54 | 64 | |
|
55 | - app_name: a string containing the name of your application. | |
|
65 | def __call__(self, etype, evalue, etb) | |
|
66 | """ | |
|
56 | 67 | |
|
57 | - contact_name: a string with the name of the person to contact. | |
|
68 | message_template = _default_message_template | |
|
58 | 69 | |
|
59 | - contact_email: a string with the email address of the contact. | |
|
70 | def __init__(self, app, contact_name=None, contact_email=None, | |
|
71 | bug_tracker=None, show_crash_traceback=True, call_pdb=False): | |
|
72 | """Create a new crash handler | |
|
60 | 73 | |
|
61 | - bug_tracker: a string with the URL for your project's bug tracker. | |
|
74 | Parameters | |
|
75 | ---------- | |
|
76 | app : Application | |
|
77 | A running :class:`Application` instance, which will be queried at | |
|
78 | crash time for internal information. | |
|
62 | 79 | |
|
63 | - crash_report_fname: a string with the filename for the crash report | |
|
64 | to be saved in. These reports are left in the ipython user directory | |
|
65 | as determined by the running IPython instance. | |
|
80 | contact_name : str | |
|
81 | A string with the name of the person to contact. | |
|
66 | 82 | |
|
67 | Optional inputs: | |
|
68 | ||
|
69 | - show_crash_traceback(True): if false, don't print the crash | |
|
70 | traceback on stderr, only generate the on-disk report | |
|
83 | contact_email : str | |
|
84 | A string with the email address of the contact. | |
|
71 | 85 | |
|
86 | bug_tracker : str | |
|
87 | A string with the URL for your project's bug tracker. | |
|
88 | ||
|
89 | show_crash_traceback : bool | |
|
90 | If false, don't print the crash traceback on stderr, only generate | |
|
91 | the on-disk report | |
|
72 | 92 | |
|
73 | 93 | Non-argument instance attributes: |
|
74 | 94 | |
|
75 |
These instances contain some non-argument attributes which allow for |
|
|
76 |
further customization of the crash handler's behavior. |
|
|
95 | These instances contain some non-argument attributes which allow for | |
|
96 | further customization of the crash handler's behavior. Please see the | |
|
77 | 97 | source for further details. |
|
78 | 98 | """ |
|
79 | ||
|
80 | # apply args into instance | |
|
81 | 99 | self.app = app |
|
82 |
self.app_name = |
|
|
100 | self.app_name = self.app.name | |
|
83 | 101 | self.contact_name = contact_name |
|
84 | 102 | self.contact_email = contact_email |
|
85 | 103 | self.bug_tracker = bug_tracker |
|
86 |
self.crash_report_fname = |
|
|
104 | self.crash_report_fname = "Crash_report_%s.txt" % self.app_name | |
|
87 | 105 | self.show_crash_traceback = show_crash_traceback |
|
88 | 106 | self.section_sep = '\n\n'+'*'*75+'\n\n' |
|
89 | 107 | self.call_pdb = call_pdb |
|
90 | 108 | #self.call_pdb = True # dbg |
|
91 | ||
|
92 | # Hardcoded defaults, which can be overridden either by subclasses or | |
|
93 | # at runtime for the instance. | |
|
94 | ||
|
95 | # Template for the user message. Subclasses which completely override | |
|
96 | # this, or user apps, can modify it to suit their tastes. It gets | |
|
97 | # expanded using itpl, so calls of the kind $self.foo are valid. | |
|
98 | self.user_message_template = """ | |
|
99 | Oops, $self.app_name crashed. We do our best to make it stable, but... | |
|
100 | ||
|
101 | A crash report was automatically generated with the following information: | |
|
102 | - A verbatim copy of the crash traceback. | |
|
103 | - A copy of your input history during this session. | |
|
104 | - Data on your current $self.app_name configuration. | |
|
105 | ||
|
106 | It was left in the file named: | |
|
107 | \t'$self.crash_report_fname' | |
|
108 | If you can email this file to the developers, the information in it will help | |
|
109 | them in understanding and correcting the problem. | |
|
110 | ||
|
111 | You can mail it to: $self.contact_name at $self.contact_email | |
|
112 | with the subject '$self.app_name Crash Report'. | |
|
113 | ||
|
114 | If you want to do it now, the following command will work (under Unix): | |
|
115 | mail -s '$self.app_name Crash Report' $self.contact_email < $self.crash_report_fname | |
|
116 | ||
|
117 | To ensure accurate tracking of this issue, please file a report about it at: | |
|
118 | $self.bug_tracker | |
|
119 | """ | |
|
120 | 109 | |
|
121 | def __call__(self,etype, evalue, etb): | |
|
110 | def __call__(self, etype, evalue, etb): | |
|
122 | 111 | """Handle an exception, call for compatible with sys.excepthook""" |
|
123 | 112 | |
|
124 | 113 | # Report tracebacks shouldn't use color in general (safer for users) |
@@ -137,10 +126,11 b' $self.bug_tracker' | |||
|
137 | 126 | # write the report filename into the instance dict so it can get |
|
138 | 127 | # properly expanded out in the user message template |
|
139 | 128 | self.crash_report_fname = report_name |
|
140 |
TBhandler = ultratb.VerboseTB( |
|
|
141 | long_header=1, | |
|
142 | call_pdb=self.call_pdb, | |
|
143 | ) | |
|
129 | TBhandler = ultratb.VerboseTB( | |
|
130 | color_scheme=color_scheme, | |
|
131 | long_header=1, | |
|
132 | call_pdb=self.call_pdb, | |
|
133 | ) | |
|
144 | 134 | if self.call_pdb: |
|
145 | 135 | TBhandler(etype,evalue,etb) |
|
146 | 136 | return |
@@ -159,7 +149,7 b' $self.bug_tracker' | |||
|
159 | 149 | return |
|
160 | 150 | |
|
161 | 151 | # Inform user on stderr of what happened |
|
162 |
msg = itpl('\n'+'*'*70+'\n'+self. |
|
|
152 | msg = itpl('\n'+'*'*70+'\n'+self.message_template) | |
|
163 | 153 | print >> sys.stderr, msg |
|
164 | 154 | |
|
165 | 155 | # Construct report on disk |
@@ -178,7 +168,9 b' $self.bug_tracker' | |||
|
178 | 168 | |
|
179 | 169 | try: |
|
180 | 170 | config = pformat(self.app.config) |
|
181 | rpt_add(sec_sep+'Current user configuration structure:\n\n') | |
|
171 | rpt_add(sec_sep) | |
|
172 | rpt_add('Application name: %s\n\n' % self.app_name) | |
|
173 | rpt_add('Current user configuration structure:\n\n') | |
|
182 | 174 | rpt_add(config) |
|
183 | 175 | except: |
|
184 | 176 | pass |
@@ -186,39 +178,3 b' $self.bug_tracker' | |||
|
186 | 178 | |
|
187 | 179 | return ''.join(report) |
|
188 | 180 | |
|
189 | ||
|
190 | class IPythonCrashHandler(CrashHandler): | |
|
191 | """sys.excepthook for IPython itself, leaves a detailed report on disk.""" | |
|
192 | ||
|
193 | def __init__(self, app, app_name='IPython'): | |
|
194 | ||
|
195 | # Set here which of the IPython authors should be listed as contact | |
|
196 | AUTHOR_CONTACT = 'Fernando' | |
|
197 | ||
|
198 | # Set argument defaults | |
|
199 | bug_tracker = 'https://bugs.launchpad.net/ipython/+filebug' | |
|
200 | contact_name,contact_email = release.authors[AUTHOR_CONTACT][:2] | |
|
201 | crash_report_fname = 'IPython_crash_report.txt' | |
|
202 | # Call parent constructor | |
|
203 | CrashHandler.__init__(self,app,app_name,contact_name,contact_email, | |
|
204 | bug_tracker,crash_report_fname) | |
|
205 | ||
|
206 | def make_report(self,traceback): | |
|
207 | """Return a string containing a crash report.""" | |
|
208 | ||
|
209 | sec_sep = self.section_sep | |
|
210 | # Start with parent report | |
|
211 | report = [super(IPythonCrashHandler, self).make_report(traceback)] | |
|
212 | # Add interactive-specific info we may have | |
|
213 | rpt_add = report.append | |
|
214 | try: | |
|
215 | rpt_add(sec_sep+"History of session input:") | |
|
216 | for line in self.app.shell.user_ns['_ih']: | |
|
217 | rpt_add(line) | |
|
218 | rpt_add('\n*** Last line of input (may not be in above history):\n') | |
|
219 | rpt_add(self.app.shell._last_input_line+'\n') | |
|
220 | except: | |
|
221 | pass | |
|
222 | ||
|
223 | return ''.join(report) | |
|
224 |
@@ -21,13 +21,15 b' Authors' | |||
|
21 | 21 | #----------------------------------------------------------------------------- |
|
22 | 22 | # Imports |
|
23 | 23 | #----------------------------------------------------------------------------- |
|
24 | ||
|
24 | 25 | from __future__ import absolute_import |
|
25 | 26 | |
|
26 | 27 | import logging |
|
27 | 28 | import os |
|
28 | 29 | import sys |
|
29 | 30 | |
|
30 |
from IPython.core import |
|
|
31 | from IPython.core import release | |
|
32 | from IPython.core.crashhandler import CrashHandler | |
|
31 | 33 | from IPython.core.application import Application, BaseAppConfigLoader |
|
32 | 34 | from IPython.core.iplib import InteractiveShell |
|
33 | 35 | from IPython.config.loader import ( |
@@ -317,6 +319,67 b' class IPAppConfigLoader(BaseAppConfigLoader):' | |||
|
317 | 319 | |
|
318 | 320 | |
|
319 | 321 | #----------------------------------------------------------------------------- |
|
322 | # Crash handler for this application | |
|
323 | #----------------------------------------------------------------------------- | |
|
324 | ||
|
325 | ||
|
326 | _message_template = """\ | |
|
327 | Oops, $self.app_name crashed. We do our best to make it stable, but... | |
|
328 | ||
|
329 | A crash report was automatically generated with the following information: | |
|
330 | - A verbatim copy of the crash traceback. | |
|
331 | - A copy of your input history during this session. | |
|
332 | - Data on your current $self.app_name configuration. | |
|
333 | ||
|
334 | It was left in the file named: | |
|
335 | \t'$self.crash_report_fname' | |
|
336 | If you can email this file to the developers, the information in it will help | |
|
337 | them in understanding and correcting the problem. | |
|
338 | ||
|
339 | You can mail it to: $self.contact_name at $self.contact_email | |
|
340 | with the subject '$self.app_name Crash Report'. | |
|
341 | ||
|
342 | If you want to do it now, the following command will work (under Unix): | |
|
343 | mail -s '$self.app_name Crash Report' $self.contact_email < $self.crash_report_fname | |
|
344 | ||
|
345 | To ensure accurate tracking of this issue, please file a report about it at: | |
|
346 | $self.bug_tracker | |
|
347 | """ | |
|
348 | ||
|
349 | class IPAppCrashHandler(CrashHandler): | |
|
350 | """sys.excepthook for IPython itself, leaves a detailed report on disk.""" | |
|
351 | ||
|
352 | message_template = _message_template | |
|
353 | ||
|
354 | def __init__(self, app): | |
|
355 | contact_name = release.authors['Fernando'][0] | |
|
356 | contact_email = release.authors['Fernando'][1] | |
|
357 | bug_tracker = 'https://bugs.launchpad.net/ipython/+filebug' | |
|
358 | super(IPAppCrashHandler,self).__init__( | |
|
359 | app, contact_name, contact_email, bug_tracker | |
|
360 | ) | |
|
361 | ||
|
362 | def make_report(self,traceback): | |
|
363 | """Return a string containing a crash report.""" | |
|
364 | ||
|
365 | sec_sep = self.section_sep | |
|
366 | # Start with parent report | |
|
367 | report = [super(IPAppCrashHandler, self).make_report(traceback)] | |
|
368 | # Add interactive-specific info we may have | |
|
369 | rpt_add = report.append | |
|
370 | try: | |
|
371 | rpt_add(sec_sep+"History of session input:") | |
|
372 | for line in self.app.shell.user_ns['_ih']: | |
|
373 | rpt_add(line) | |
|
374 | rpt_add('\n*** Last line of input (may not be in above history):\n') | |
|
375 | rpt_add(self.app.shell._last_input_line+'\n') | |
|
376 | except: | |
|
377 | pass | |
|
378 | ||
|
379 | return ''.join(report) | |
|
380 | ||
|
381 | ||
|
382 | #----------------------------------------------------------------------------- | |
|
320 | 383 | # Main classes and functions |
|
321 | 384 | #----------------------------------------------------------------------------- |
|
322 | 385 | |
@@ -327,9 +390,7 b' class IPythonApp(Application):' | |||
|
327 | 390 | usage = usage.cl_usage |
|
328 | 391 | command_line_loader = IPAppConfigLoader |
|
329 | 392 | config_file_name = default_config_file_name |
|
330 | ||
|
331 | # Private and configuration attributes | |
|
332 | _CrashHandler = crashhandler.IPythonCrashHandler | |
|
393 | crash_handler_class = IPAppCrashHandler | |
|
333 | 394 | |
|
334 | 395 | def create_default_config(self): |
|
335 | 396 | super(IPythonApp, self).create_default_config() |
@@ -27,6 +27,8 b' from twisted.python import log' | |||
|
27 | 27 | from IPython.config.loader import PyFileConfigLoader |
|
28 | 28 | from IPython.core.application import Application, BaseAppConfigLoader |
|
29 | 29 | from IPython.core.component import Component |
|
30 | from IPython.core.crashhandler import CrashHandler | |
|
31 | from IPython.core import release | |
|
30 | 32 | from IPython.utils.path import ( |
|
31 | 33 | get_ipython_package_dir, |
|
32 | 34 | expand_path |
@@ -290,6 +292,47 b' class ClusterDirConfigLoader(BaseAppConfigLoader):' | |||
|
290 | 292 | |
|
291 | 293 | |
|
292 | 294 | #----------------------------------------------------------------------------- |
|
295 | # Crash handler for this application | |
|
296 | #----------------------------------------------------------------------------- | |
|
297 | ||
|
298 | ||
|
299 | _message_template = """\ | |
|
300 | Oops, $self.app_name crashed. We do our best to make it stable, but... | |
|
301 | ||
|
302 | A crash report was automatically generated with the following information: | |
|
303 | - A verbatim copy of the crash traceback. | |
|
304 | - Data on your current $self.app_name configuration. | |
|
305 | ||
|
306 | It was left in the file named: | |
|
307 | \t'$self.crash_report_fname' | |
|
308 | If you can email this file to the developers, the information in it will help | |
|
309 | them in understanding and correcting the problem. | |
|
310 | ||
|
311 | You can mail it to: $self.contact_name at $self.contact_email | |
|
312 | with the subject '$self.app_name Crash Report'. | |
|
313 | ||
|
314 | If you want to do it now, the following command will work (under Unix): | |
|
315 | mail -s '$self.app_name Crash Report' $self.contact_email < $self.crash_report_fname | |
|
316 | ||
|
317 | To ensure accurate tracking of this issue, please file a report about it at: | |
|
318 | $self.bug_tracker | |
|
319 | """ | |
|
320 | ||
|
321 | class ClusterDirCrashHandler(CrashHandler): | |
|
322 | """sys.excepthook for IPython itself, leaves a detailed report on disk.""" | |
|
323 | ||
|
324 | message_template = _message_template | |
|
325 | ||
|
326 | def __init__(self, app): | |
|
327 | contact_name = release.authors['Brian'][0] | |
|
328 | contact_email = release.authors['Brian'][1] | |
|
329 | bug_tracker = 'https://bugs.launchpad.net/ipython/+filebug' | |
|
330 | super(ClusterDirCrashHandler,self).__init__( | |
|
331 | app, contact_name, contact_email, bug_tracker | |
|
332 | ) | |
|
333 | ||
|
334 | ||
|
335 | #----------------------------------------------------------------------------- | |
|
293 | 336 | # Main application |
|
294 | 337 | #----------------------------------------------------------------------------- |
|
295 | 338 | |
@@ -313,6 +356,7 b' class ApplicationWithClusterDir(Application):' | |||
|
313 | 356 | """ |
|
314 | 357 | |
|
315 | 358 | command_line_loader = ClusterDirConfigLoader |
|
359 | crash_handler_class = ClusterDirCrashHandler | |
|
316 | 360 | auto_create_cluster_dir = True |
|
317 | 361 | |
|
318 | 362 | def create_default_config(self): |
General Comments 0
You need to be logged in to leave comments.
Login now