##// END OF EJS Templates
Make crash handler tell users to email more detail...
Samuel Lelièvre -
Show More
@@ -1,225 +1,225 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-2011 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 import traceback
25 25 from pprint import pformat
26 26
27 27 from IPython.core import ultratb
28 28 from IPython.core.release import author_email
29 29 from IPython.utils.sysinfo import sys_info
30 30 from IPython.utils.py3compat import input
31 31
32 32 #-----------------------------------------------------------------------------
33 33 # Code
34 34 #-----------------------------------------------------------------------------
35 35
36 36 # Template for the user message.
37 37 _default_message_template = """\
38 38 Oops, {app_name} crashed. We do our best to make it stable, but...
39 39
40 40 A crash report was automatically generated with the following information:
41 41 - A verbatim copy of the crash traceback.
42 42 - A copy of your input history during this session.
43 43 - Data on your current {app_name} configuration.
44 44
45 45 It was left in the file named:
46 46 \t'{crash_report_fname}'
47 47 If you can email this file to the developers, the information in it will help
48 48 them in understanding and correcting the problem.
49 49
50 50 You can mail it to: {contact_name} at {contact_email}
51 51 with the subject '{app_name} Crash Report'.
52 52
53 53 If you want to do it now, the following command will work (under Unix):
54 54 mail -s '{app_name} Crash Report' {contact_email} < {crash_report_fname}
55 55
56 Please also include in your email:
57 - information about your operating system: is it Linux, macOS, Windows, other,
58 and which version, for example Ubuntu 16.04, macOS 10.13.2, Windows 10 Pro,
59 is it 32-bit or 64-bit, ...
60 - information on how you installed {app_name}: from binary, compiled from source,
61 via Docker, on a virtual machine...
62 - information on how to reproduce the crash: what exact sequence of instructions
63 can one input to get the same crash? Ideally, find a minimal yet complete
64 sequence of instructions that yields the crash.
56 In your email, please also include information about:
57 - The operating system under which the crash happened: Linux, macOS, Windows,
58 other, and which exact version (for example: Ubuntu 16.04.3, macOS 10.13.2,
59 Windows 10 Pro), and whether it is 32-bit or 64-bit;
60 - How {app_name} was installed: using pip or conda, from GitHub, as part of
61 a Docker container, or other, providing more detail if possible;
62 - How to reproduce the crash: what exact sequence of instructions can one
63 input to get the same crash? Ideally, find a minimal yet complete sequence
64 of instructions that yields the crash.
65 65
66 66 To ensure accurate tracking of this issue, please file a report about it at:
67 67 {bug_tracker}
68 68 """
69 69
70 70 _lite_message_template = """
71 71 If you suspect this is an IPython bug, please report it at:
72 72 https://github.com/ipython/ipython/issues
73 73 or send an email to the mailing list at {email}
74 74
75 75 You can print a more detailed traceback right now with "%tb", or use "%debug"
76 76 to interactively debug it.
77 77
78 78 Extra-detailed tracebacks for bug-reporting purposes can be enabled via:
79 79 {config}Application.verbose_crash=True
80 80 """
81 81
82 82
83 83 class CrashHandler(object):
84 84 """Customizable crash handlers for IPython applications.
85 85
86 86 Instances of this class provide a :meth:`__call__` method which can be
87 87 used as a ``sys.excepthook``. The :meth:`__call__` signature is::
88 88
89 89 def __call__(self, etype, evalue, etb)
90 90 """
91 91
92 92 message_template = _default_message_template
93 93 section_sep = '\n\n'+'*'*75+'\n\n'
94 94
95 95 def __init__(self, app, contact_name=None, contact_email=None,
96 96 bug_tracker=None, show_crash_traceback=True, call_pdb=False):
97 97 """Create a new crash handler
98 98
99 99 Parameters
100 100 ----------
101 101 app : Application
102 102 A running :class:`Application` instance, which will be queried at
103 103 crash time for internal information.
104 104
105 105 contact_name : str
106 106 A string with the name of the person to contact.
107 107
108 108 contact_email : str
109 109 A string with the email address of the contact.
110 110
111 111 bug_tracker : str
112 112 A string with the URL for your project's bug tracker.
113 113
114 114 show_crash_traceback : bool
115 115 If false, don't print the crash traceback on stderr, only generate
116 116 the on-disk report
117 117
118 118 Non-argument instance attributes:
119 119
120 120 These instances contain some non-argument attributes which allow for
121 121 further customization of the crash handler's behavior. Please see the
122 122 source for further details.
123 123 """
124 124 self.crash_report_fname = "Crash_report_%s.txt" % app.name
125 125 self.app = app
126 126 self.call_pdb = call_pdb
127 127 #self.call_pdb = True # dbg
128 128 self.show_crash_traceback = show_crash_traceback
129 129 self.info = dict(app_name = app.name,
130 130 contact_name = contact_name,
131 131 contact_email = contact_email,
132 132 bug_tracker = bug_tracker,
133 133 crash_report_fname = self.crash_report_fname)
134 134
135 135
136 136 def __call__(self, etype, evalue, etb):
137 137 """Handle an exception, call for compatible with sys.excepthook"""
138 138
139 139 # do not allow the crash handler to be called twice without reinstalling it
140 140 # this prevents unlikely errors in the crash handling from entering an
141 141 # infinite loop.
142 142 sys.excepthook = sys.__excepthook__
143 143
144 144 # Report tracebacks shouldn't use color in general (safer for users)
145 145 color_scheme = 'NoColor'
146 146
147 147 # Use this ONLY for developer debugging (keep commented out for release)
148 148 #color_scheme = 'Linux' # dbg
149 149 try:
150 150 rptdir = self.app.ipython_dir
151 151 except:
152 152 rptdir = os.getcwd()
153 153 if rptdir is None or not os.path.isdir(rptdir):
154 154 rptdir = os.getcwd()
155 155 report_name = os.path.join(rptdir,self.crash_report_fname)
156 156 # write the report filename into the instance dict so it can get
157 157 # properly expanded out in the user message template
158 158 self.crash_report_fname = report_name
159 159 self.info['crash_report_fname'] = report_name
160 160 TBhandler = ultratb.VerboseTB(
161 161 color_scheme=color_scheme,
162 162 long_header=1,
163 163 call_pdb=self.call_pdb,
164 164 )
165 165 if self.call_pdb:
166 166 TBhandler(etype,evalue,etb)
167 167 return
168 168 else:
169 169 traceback = TBhandler.text(etype,evalue,etb,context=31)
170 170
171 171 # print traceback to screen
172 172 if self.show_crash_traceback:
173 173 print(traceback, file=sys.stderr)
174 174
175 175 # and generate a complete report on disk
176 176 try:
177 177 report = open(report_name,'w')
178 178 except:
179 179 print('Could not create crash report on disk.', file=sys.stderr)
180 180 return
181 181
182 182 # Inform user on stderr of what happened
183 183 print('\n'+'*'*70+'\n', file=sys.stderr)
184 184 print(self.message_template.format(**self.info), file=sys.stderr)
185 185
186 186 # Construct report on disk
187 187 report.write(self.make_report(traceback))
188 188 report.close()
189 189 input("Hit <Enter> to quit (your terminal may close):")
190 190
191 191 def make_report(self,traceback):
192 192 """Return a string containing a crash report."""
193 193
194 194 sec_sep = self.section_sep
195 195
196 196 report = ['*'*75+'\n\n'+'IPython post-mortem report\n\n']
197 197 rpt_add = report.append
198 198 rpt_add(sys_info())
199 199
200 200 try:
201 201 config = pformat(self.app.config)
202 202 rpt_add(sec_sep)
203 203 rpt_add('Application name: %s\n\n' % self.app_name)
204 204 rpt_add('Current user configuration structure:\n\n')
205 205 rpt_add(config)
206 206 except:
207 207 pass
208 208 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
209 209
210 210 return ''.join(report)
211 211
212 212
213 213 def crash_handler_lite(etype, evalue, tb):
214 214 """a light excepthook, adding a small message to the usual traceback"""
215 215 traceback.print_exception(etype, evalue, tb)
216 216
217 217 from IPython.core.interactiveshell import InteractiveShell
218 218 if InteractiveShell.initialized():
219 219 # we are in a Shell environment, give %magic example
220 220 config = "%config "
221 221 else:
222 222 # we are not in a shell, show generic config
223 223 config = "c."
224 224 print(_lite_message_template.format(email=author_email, config=config), file=sys.stderr)
225 225
General Comments 0
You need to be logged in to leave comments. Login now