##// END OF EJS Templates
- Made the internal crash handler very customizable for end-user apps based...
fptest -
Show More
@@ -1,7 +1,7 b''
1 1 # -*- coding: utf-8 -*-
2 2 """sys.excepthook for IPython itself, leaves a detailed report on disk.
3 3
4 $Id: CrashHandler.py 1326 2006-05-25 02:07:11Z fperez $"""
4 $Id: CrashHandler.py 1828 2006-10-16 02:04:33Z fptest $"""
5 5
6 6 #*****************************************************************************
7 7 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
@@ -31,14 +31,90 b' from IPython.genutils import *'
31 31
32 32 #****************************************************************************
33 33 class CrashHandler:
34 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
34 """Customizable crash handlers for IPython-based systems.
35 35
36 def __init__(self,IP):
36 Instances of this class provide a __call__ method which can be used as a
37 sys.excepthook, i.e., the __call__ signature is:
38
39 def __call__(self,etype, evalue, etb)
40
41 """
42
43 def __init__(self,IP,app_name,contact_name,contact_email,
44 bug_tracker,crash_report_fname,
45 show_crash_traceback=True):
46 """New crash handler.
47
48 Inputs:
49
50 - IP: a running IPython instance, which will be queried at crash time
51 for internal information.
52
53 - app_name: a string containing the name of your application.
54
55 - contact_name: a string with the name of the person to contact.
56
57 - contact_email: a string with the email address of the contact.
58
59 - bug_tracker: a string with the URL for your project's bug tracker.
60
61 - crash_report_fname: a string with the filename for the crash report
62 to be saved in. These reports are left in the ipython user directory
63 as determined by the running IPython instance.
64
65 Optional inputs:
66
67 - show_crash_traceback(True): if false, don't print the crash
68 traceback on stderr, only generate the on-disk report
69
70
71 Non-argument instance attributes:
72
73 These instances contain some non-argument attributes which allow for
74 further customization of the crash handler's behavior. Please see the
75 source for further details.
76 """
77
78 # apply args into instance
37 79 self.IP = IP # IPython instance
38 self.bug_contact = Release.authors['Ville'][0]
39 self.mailto = Release.authors['Ville'][1]
80 self.app_name = app_name
81 self.contact_name = contact_name
82 self.contact_email = contact_email
83 self.bug_tracker = bug_tracker
84 self.crash_report_fname = crash_report_fname
85 self.show_crash_traceback = show_crash_traceback
86
87 # Hardcoded defaults, which can be overridden either by subclasses or
88 # at runtime for the instance.
89
90 # Template for the user message. Subclasses which completely override
91 # this, or user apps, can modify it to suit their tastes. It gets
92 # expanded using itpl, so calls of the kind $self.foo are valid.
93 self.user_message_template = """
94 Oops, $self.app_name crashed. We do our best to make it stable, but...
95
96 A crash report was automatically generated with the following information:
97 - A verbatim copy of the crash traceback.
98 - A copy of your input history during this session.
99 - Data on your current $self.app_name configuration.
100
101 It was left in the file named:
102 \t'$self.crash_report_fname'
103 If you can email this file to the developers, the information in it will help
104 them in understanding and correcting the problem.
105
106 You can mail it to: $self.contact_name at $self.contact_email
107 with the subject '$self.app_name Crash Report'.
108
109 If you want to do it now, the following command will work (under Unix):
110 mail -s '$self.app_name Crash Report' $self.contact_email < $self.crash_report_fname
111
112 To ensure accurate tracking of this issue, please file a report about it at:
113 $self.bug_tracker
114 """
40 115
41 116 def __call__(self,etype, evalue, etb):
117 """Handle an exception, call for compatible with sys.excepthook"""
42 118
43 119 # Report tracebacks shouldn't use color in general (safer for users)
44 120 color_scheme = 'NoColor'
@@ -52,60 +128,100 b' class CrashHandler:'
52 128 rptdir = os.getcwd()
53 129 if not os.path.isdir(rptdir):
54 130 rptdir = os.getcwd()
55 self.report_name = os.path.join(rptdir,'IPython_crash_report.txt')
56 self.TBhandler = ultraTB.VerboseTB(color_scheme=color_scheme,long_header=1)
57 traceback = self.TBhandler.text(etype,evalue,etb,context=31)
131 report_name = os.path.join(rptdir,self.crash_report_fname)
132 # write the report filename into the instance dict so it can get
133 # properly expanded out in the user message template
134 self.crash_report_fname = report_name
135 TBhandler = ultraTB.VerboseTB(color_scheme=color_scheme,
136 long_header=1)
137 traceback = TBhandler.text(etype,evalue,etb,context=31)
58 138
59 139 # print traceback to screen
60 print >> sys.stderr, traceback
140 if self.show_crash_traceback:
141 print >> sys.stderr, traceback
61 142
62 143 # and generate a complete report on disk
63 144 try:
64 report = open(self.report_name,'w')
145 report = open(report_name,'w')
65 146 except:
66 147 print >> sys.stderr, 'Could not create crash report on disk.'
67 148 return
68 149
69 msg = itpl('\n'+'*'*70+'\n'
70 """
71 Oops, IPython crashed. We do our best to make it stable, but...
150 # Inform user on stderr of what happened
151 msg = itpl('\n'+'*'*70+'\n'+self.user_message_template)
152 print >> sys.stderr, msg
72 153
73 A crash report was automatically generated with the following information:
74 - A verbatim copy of the traceback above this text.
75 - A copy of your input history during this session.
76 - Data on your current IPython configuration.
154 # Construct report on disk
155 report.write(self.make_report(traceback))
156 report.close()
77 157
78 It was left in the file named:
79 \t'$self.report_name'
80 If you can email this file to the developers, the information in it will help
81 them in understanding and correcting the problem.
158 def make_report(self,traceback):
159 """Return a string containing a crash report."""
82 160
83 You can mail it to $self.bug_contact at $self.mailto
84 with the subject 'IPython Crash Report'.
161 sec_sep = '\n\n'+'*'*75+'\n\n'
85 162
86 If you want to do it now, the following command will work (under Unix):
87 mail -s 'IPython Crash Report' $self.mailto < $self.report_name
163 report = []
164 rpt_add = report.append
165
166 rpt_add('*'*75+'\n\n'+'IPython post-mortem report\n\n')
167 rpt_add('IPython version: %s \n\n' % Release.version)
168 rpt_add('SVN revision : %s \n\n' % Release.revision)
169 rpt_add('Platform info : os.name -> %s, sys.platform -> %s' %
170 (os.name,sys.platform) )
171 rpt_add(sec_sep+'Current user configuration structure:\n\n')
172 rpt_add(pformat(self.IP.rc.dict()))
173 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
174 try:
175 rpt_add(sec_sep+"History of session input:")
176 for line in self.IP.user_ns['_ih']:
177 rpt_add(line)
178 rpt_add('\n*** Last line of input (may not be in above history):\n')
179 rpt_add(self.IP._last_input_line+'\n')
180 except:
181 pass
88 182
89 To ensure accurate tracking of this issue, please file a report about it at:
90 http://projects.scipy.org/ipython/ipython/report
91 """)
92 print >> sys.stderr, msg
183 return ''.join(report)
184
185 class IPythonCrashHandler(CrashHandler):
186 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
187
188 def __init__(self,IP):
189
190 # Set here which of the IPython authors should be listed as contact
191 AUTHOR_CONTACT = 'Ville'
192
193 # Set argument defaults
194 app_name = 'IPython'
195 bug_tracker = 'http://projects.scipy.org/ipython/ipython/report'
196 contact_name,contact_email = Release.authors[AUTHOR_CONTACT][:2]
197 crash_report_fname = 'IPython_crash_report.txt'
198 # Call parent constructor
199 CrashHandler.__init__(self,IP,app_name,contact_name,contact_email,
200 bug_tracker,crash_report_fname)
201
202 def make_report(self,traceback):
203 """Return a string containing a crash report."""
93 204
94 205 sec_sep = '\n\n'+'*'*75+'\n\n'
95 report.write('*'*75+'\n\n'+'IPython post-mortem report\n\n')
96 report.write('IPython version: %s \n\n' % Release.version)
97 report.write('SVN revision : %s \n\n' % Release.revision)
98 report.write('Platform info : os.name -> %s, sys.platform -> %s' %
206
207 report = []
208 rpt_add = report.append
209
210 rpt_add('*'*75+'\n\n'+'IPython post-mortem report\n\n')
211 rpt_add('IPython version: %s \n\n' % Release.version)
212 rpt_add('SVN revision : %s \n\n' % Release.revision)
213 rpt_add('Platform info : os.name -> %s, sys.platform -> %s' %
99 214 (os.name,sys.platform) )
100 report.write(sec_sep+'Current user configuration structure:\n\n')
101 report.write(pformat(self.IP.rc.dict()))
102 report.write(sec_sep+'Crash traceback:\n\n' + traceback)
215 rpt_add(sec_sep+'Current user configuration structure:\n\n')
216 rpt_add(pformat(self.IP.rc.dict()))
217 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
103 218 try:
104 report.write(sec_sep+"History of session input:")
219 rpt_add(sec_sep+"History of session input:")
105 220 for line in self.IP.user_ns['_ih']:
106 report.write(line)
107 report.write('\n*** Last line of input (may not be in above history):\n')
108 report.write(self.IP._last_input_line+'\n')
221 rpt_add(line)
222 rpt_add('\n*** Last line of input (may not be in above history):\n')
223 rpt_add(self.IP._last_input_line+'\n')
109 224 except:
110 225 pass
111 report.close()
226
227 return ''.join(report)
@@ -145,6 +145,8 b' class IPApi:'
145 145
146 146 self.user_ns = ip.user_ns
147 147
148 self.set_crash_handler = ip.set_crash_handler
149
148 150 # Session-specific data store, which can be used to store
149 151 # data that should persist through the ipython session.
150 152 self.meta = ip.meta
@@ -6,7 +6,7 b' Requires Python 2.3 or newer.'
6 6
7 7 This file contains all the classes and helper functions specific to IPython.
8 8
9 $Id: iplib.py 1822 2006-10-12 21:38:00Z vivainio $
9 $Id: iplib.py 1828 2006-10-16 02:04:33Z fptest $
10 10 """
11 11
12 12 #*****************************************************************************
@@ -543,16 +543,11 b' class InteractiveShell(object,Magic):'
543 543 # thread (such as in GUI code) propagate directly to sys.excepthook,
544 544 # and there's no point in printing crash dumps for every user exception.
545 545 if self.isthreaded:
546 sys.excepthook = ultraTB.FormattedTB()
546 ipCrashHandler = ultraTB.FormattedTB()
547 547 else:
548 548 from IPython import CrashHandler
549 sys.excepthook = CrashHandler.CrashHandler(self)
550
551 # The instance will store a pointer to this, so that runtime code
552 # (such as magics) can access it. This is because during the
553 # read-eval loop, it gets temporarily overwritten (to deal with GUI
554 # frameworks).
555 self.sys_excepthook = sys.excepthook
549 ipCrashHandler = CrashHandler.IPythonCrashHandler(self)
550 self.set_crash_handler(ipCrashHandler)
556 551
557 552 # and add any custom exception handlers the user may have specified
558 553 self.set_custom_exc(*custom_exceptions)
@@ -769,6 +764,22 b' class InteractiveShell(object,Magic):'
769 764
770 765 #setattr(self.hooks,name,new.instancemethod(hook,self,self.__class__))
771 766
767 def set_crash_handler(self,crashHandler):
768 """Set the IPython crash handler.
769
770 This must be a callable with a signature suitable for use as
771 sys.excepthook."""
772
773 # Install the given crash handler as the Python exception hook
774 sys.excepthook = crashHandler
775
776 # The instance will store a pointer to this, so that runtime code
777 # (such as magics) can access it. This is because during the
778 # read-eval loop, it gets temporarily overwritten (to deal with GUI
779 # frameworks).
780 self.sys_excepthook = sys.excepthook
781
782
772 783 def set_custom_exc(self,exc_tuple,handler):
773 784 """set_custom_exc(exc_tuple,handler)
774 785
@@ -1,3 +1,14 b''
1 2006-10-15 Fernando Perez <Fernando.Perez@colorado.edu>
2
3 * IPython/ipapi.py (IPApi.__init__): Added new entry to public
4 api: set_crash_handler(), to expose the ability to change the
5 internal crash handler.
6
7 * IPython/CrashHandler.py (CrashHandler.__init__): abstract out
8 the various parameters of the crash handler so that apps using
9 IPython as their engine can customize crash handling. Ipmlemented
10 at the request of SAGE.
11
1 12 2006-10-14 Ville Vainio <vivainio@gmail.com>
2 13
3 14 * Magic.py, ipython.el: applied first "safe" part of Rocky
General Comments 0
You need to be logged in to leave comments. Login now