##// END OF EJS Templates
Ensure crash handler works even when app isn't fully configured yet....
Fernando Perez -
Show More
@@ -1,180 +1,179 b''
1 1 # encoding: utf-8
2 2 """sys.excepthook for IPython itself, leaves a detailed report on disk.
3 3
4 4 Authors:
5 5
6 6 * Fernando Perez
7 7 * Brian E. Granger
8 8 """
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
12 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 18 #-----------------------------------------------------------------------------
19 19 # Imports
20 20 #-----------------------------------------------------------------------------
21 21
22 22 import os
23 23 import sys
24 24 from pprint import pformat
25 25
26 26 from IPython.core import ultratb
27 27 from IPython.external.Itpl import itpl
28 28 from IPython.utils.sysinfo import sys_info
29 29
30 30 #-----------------------------------------------------------------------------
31 31 # Code
32 32 #-----------------------------------------------------------------------------
33 33
34 34 # Template for the user message.
35 35 _default_message_template = """\
36 36 Oops, $self.app_name crashed. We do our best to make it stable, but...
37 37
38 38 A crash report was automatically generated with the following information:
39 39 - A verbatim copy of the crash traceback.
40 40 - A copy of your input history during this session.
41 41 - Data on your current $self.app_name configuration.
42 42
43 43 It was left in the file named:
44 44 \t'$self.crash_report_fname'
45 45 If you can email this file to the developers, the information in it will help
46 46 them in understanding and correcting the problem.
47 47
48 48 You can mail it to: $self.contact_name at $self.contact_email
49 49 with the subject '$self.app_name Crash Report'.
50 50
51 51 If you want to do it now, the following command will work (under Unix):
52 52 mail -s '$self.app_name Crash Report' $self.contact_email < $self.crash_report_fname
53 53
54 54 To ensure accurate tracking of this issue, please file a report about it at:
55 55 $self.bug_tracker
56 56 """
57 57
58 58
59 59 class CrashHandler(object):
60 60 """Customizable crash handlers for IPython applications.
61 61
62 62 Instances of this class provide a :meth:`__call__` method which can be
63 63 used as a ``sys.excepthook``. The :meth:`__call__` signature is::
64 64
65 65 def __call__(self, etype, evalue, etb)
66 66 """
67 67
68 68 message_template = _default_message_template
69 69
70 70 def __init__(self, app, contact_name=None, contact_email=None,
71 71 bug_tracker=None, show_crash_traceback=True, call_pdb=False):
72 72 """Create a new crash handler
73 73
74 74 Parameters
75 75 ----------
76 76 app : Application
77 77 A running :class:`Application` instance, which will be queried at
78 78 crash time for internal information.
79 79
80 80 contact_name : str
81 81 A string with the name of the person to contact.
82 82
83 83 contact_email : str
84 84 A string with the email address of the contact.
85 85
86 86 bug_tracker : str
87 87 A string with the URL for your project's bug tracker.
88 88
89 89 show_crash_traceback : bool
90 90 If false, don't print the crash traceback on stderr, only generate
91 91 the on-disk report
92 92
93 93 Non-argument instance attributes:
94 94
95 95 These instances contain some non-argument attributes which allow for
96 96 further customization of the crash handler's behavior. Please see the
97 97 source for further details.
98 98 """
99 99 self.app = app
100 100 self.app_name = self.app.name
101 101 self.contact_name = contact_name
102 102 self.contact_email = contact_email
103 103 self.bug_tracker = bug_tracker
104 104 self.crash_report_fname = "Crash_report_%s.txt" % self.app_name
105 105 self.show_crash_traceback = show_crash_traceback
106 106 self.section_sep = '\n\n'+'*'*75+'\n\n'
107 107 self.call_pdb = call_pdb
108 108 #self.call_pdb = True # dbg
109 109
110 110 def __call__(self, etype, evalue, etb):
111 111 """Handle an exception, call for compatible with sys.excepthook"""
112 112
113 113 # Report tracebacks shouldn't use color in general (safer for users)
114 114 color_scheme = 'NoColor'
115 115
116 116 # Use this ONLY for developer debugging (keep commented out for release)
117 117 #color_scheme = 'Linux' # dbg
118
119 118 try:
120 119 rptdir = self.app.ipython_dir
121 120 except:
122 121 rptdir = os.getcwd()
123 if not os.path.isdir(rptdir):
122 if rptdir is None or not os.path.isdir(rptdir):
124 123 rptdir = os.getcwd()
125 124 report_name = os.path.join(rptdir,self.crash_report_fname)
126 125 # write the report filename into the instance dict so it can get
127 126 # properly expanded out in the user message template
128 127 self.crash_report_fname = report_name
129 128 TBhandler = ultratb.VerboseTB(
130 129 color_scheme=color_scheme,
131 130 long_header=1,
132 131 call_pdb=self.call_pdb,
133 132 )
134 133 if self.call_pdb:
135 134 TBhandler(etype,evalue,etb)
136 135 return
137 136 else:
138 137 traceback = TBhandler.text(etype,evalue,etb,context=31)
139 138
140 139 # print traceback to screen
141 140 if self.show_crash_traceback:
142 141 print >> sys.stderr, traceback
143 142
144 143 # and generate a complete report on disk
145 144 try:
146 145 report = open(report_name,'w')
147 146 except:
148 147 print >> sys.stderr, 'Could not create crash report on disk.'
149 148 return
150 149
151 150 # Inform user on stderr of what happened
152 151 msg = itpl('\n'+'*'*70+'\n'+self.message_template)
153 152 print >> sys.stderr, msg
154 153
155 154 # Construct report on disk
156 155 report.write(self.make_report(traceback))
157 156 report.close()
158 157 raw_input("Hit <Enter> to quit this message (your terminal may close):")
159 158
160 159 def make_report(self,traceback):
161 160 """Return a string containing a crash report."""
162 161
163 162 sec_sep = self.section_sep
164 163
165 164 report = ['*'*75+'\n\n'+'IPython post-mortem report\n\n']
166 165 rpt_add = report.append
167 166 rpt_add(sys_info())
168 167
169 168 try:
170 169 config = pformat(self.app.config)
171 170 rpt_add(sec_sep)
172 171 rpt_add('Application name: %s\n\n' % self.app_name)
173 172 rpt_add('Current user configuration structure:\n\n')
174 173 rpt_add(config)
175 174 except:
176 175 pass
177 176 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
178 177
179 178 return ''.join(report)
180 179
General Comments 0
You need to be logged in to leave comments. Login now