Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/IPython/core/crashhandler.py: 27%
73 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-20 06:09 +0000
1# encoding: utf-8
2"""sys.excepthook for IPython itself, leaves a detailed report on disk.
4Authors:
6* Fernando Perez
7* Brian E. Granger
8"""
10#-----------------------------------------------------------------------------
11# Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
12# Copyright (C) 2008-2011 The IPython Development Team
13#
14# Distributed under the terms of the BSD License. The full license is in
15# the file COPYING, distributed as part of this software.
16#-----------------------------------------------------------------------------
18#-----------------------------------------------------------------------------
19# Imports
20#-----------------------------------------------------------------------------
22import sys
23import traceback
24from pprint import pformat
25from pathlib import Path
27from IPython.core import ultratb
28from IPython.core.release import author_email
29from IPython.utils.sysinfo import sys_info
30from IPython.utils.py3compat import input
32from IPython.core.release import __version__ as version
34from typing import Optional
36#-----------------------------------------------------------------------------
37# Code
38#-----------------------------------------------------------------------------
40# Template for the user message.
41_default_message_template = """\
42Oops, {app_name} crashed. We do our best to make it stable, but...
44A crash report was automatically generated with the following information:
45 - A verbatim copy of the crash traceback.
46 - A copy of your input history during this session.
47 - Data on your current {app_name} configuration.
49It was left in the file named:
50\t'{crash_report_fname}'
51If you can email this file to the developers, the information in it will help
52them in understanding and correcting the problem.
54You can mail it to: {contact_name} at {contact_email}
55with the subject '{app_name} Crash Report'.
57If you want to do it now, the following command will work (under Unix):
58mail -s '{app_name} Crash Report' {contact_email} < {crash_report_fname}
60In your email, please also include information about:
61- The operating system under which the crash happened: Linux, macOS, Windows,
62 other, and which exact version (for example: Ubuntu 16.04.3, macOS 10.13.2,
63 Windows 10 Pro), and whether it is 32-bit or 64-bit;
64- How {app_name} was installed: using pip or conda, from GitHub, as part of
65 a Docker container, or other, providing more detail if possible;
66- How to reproduce the crash: what exact sequence of instructions can one
67 input to get the same crash? Ideally, find a minimal yet complete sequence
68 of instructions that yields the crash.
70To ensure accurate tracking of this issue, please file a report about it at:
71{bug_tracker}
72"""
74_lite_message_template = """
75If you suspect this is an IPython {version} bug, please report it at:
76 https://github.com/ipython/ipython/issues
77or send an email to the mailing list at {email}
79You can print a more detailed traceback right now with "%tb", or use "%debug"
80to interactively debug it.
82Extra-detailed tracebacks for bug-reporting purposes can be enabled via:
83 {config}Application.verbose_crash=True
84"""
87class CrashHandler(object):
88 """Customizable crash handlers for IPython applications.
90 Instances of this class provide a :meth:`__call__` method which can be
91 used as a ``sys.excepthook``. The :meth:`__call__` signature is::
93 def __call__(self, etype, evalue, etb)
94 """
96 message_template = _default_message_template
97 section_sep = '\n\n'+'*'*75+'\n\n'
99 def __init__(
100 self,
101 app,
102 contact_name: Optional[str] = None,
103 contact_email: Optional[str] = None,
104 bug_tracker: Optional[str] = None,
105 show_crash_traceback: bool = True,
106 call_pdb: bool = False,
107 ):
108 """Create a new crash handler
110 Parameters
111 ----------
112 app : Application
113 A running :class:`Application` instance, which will be queried at
114 crash time for internal information.
115 contact_name : str
116 A string with the name of the person to contact.
117 contact_email : str
118 A string with the email address of the contact.
119 bug_tracker : str
120 A string with the URL for your project's bug tracker.
121 show_crash_traceback : bool
122 If false, don't print the crash traceback on stderr, only generate
123 the on-disk report
124 call_pdb
125 Whether to call pdb on crash
127 Attributes
128 ----------
129 These instances contain some non-argument attributes which allow for
130 further customization of the crash handler's behavior. Please see the
131 source for further details.
133 """
134 self.crash_report_fname = "Crash_report_%s.txt" % app.name
135 self.app = app
136 self.call_pdb = call_pdb
137 #self.call_pdb = True # dbg
138 self.show_crash_traceback = show_crash_traceback
139 self.info = dict(app_name = app.name,
140 contact_name = contact_name,
141 contact_email = contact_email,
142 bug_tracker = bug_tracker,
143 crash_report_fname = self.crash_report_fname)
146 def __call__(self, etype, evalue, etb):
147 """Handle an exception, call for compatible with sys.excepthook"""
149 # do not allow the crash handler to be called twice without reinstalling it
150 # this prevents unlikely errors in the crash handling from entering an
151 # infinite loop.
152 sys.excepthook = sys.__excepthook__
154 # Report tracebacks shouldn't use color in general (safer for users)
155 color_scheme = 'NoColor'
157 # Use this ONLY for developer debugging (keep commented out for release)
158 #color_scheme = 'Linux' # dbg
159 try:
160 rptdir = self.app.ipython_dir
161 except:
162 rptdir = Path.cwd()
163 if rptdir is None or not Path.is_dir(rptdir):
164 rptdir = Path.cwd()
165 report_name = rptdir / self.crash_report_fname
166 # write the report filename into the instance dict so it can get
167 # properly expanded out in the user message template
168 self.crash_report_fname = report_name
169 self.info['crash_report_fname'] = report_name
170 TBhandler = ultratb.VerboseTB(
171 color_scheme=color_scheme,
172 long_header=1,
173 call_pdb=self.call_pdb,
174 )
175 if self.call_pdb:
176 TBhandler(etype,evalue,etb)
177 return
178 else:
179 traceback = TBhandler.text(etype,evalue,etb,context=31)
181 # print traceback to screen
182 if self.show_crash_traceback:
183 print(traceback, file=sys.stderr)
185 # and generate a complete report on disk
186 try:
187 report = open(report_name, "w", encoding="utf-8")
188 except:
189 print('Could not create crash report on disk.', file=sys.stderr)
190 return
192 with report:
193 # Inform user on stderr of what happened
194 print('\n'+'*'*70+'\n', file=sys.stderr)
195 print(self.message_template.format(**self.info), file=sys.stderr)
197 # Construct report on disk
198 report.write(self.make_report(traceback))
200 input("Hit <Enter> to quit (your terminal may close):")
202 def make_report(self,traceback):
203 """Return a string containing a crash report."""
205 sec_sep = self.section_sep
207 report = ['*'*75+'\n\n'+'IPython post-mortem report\n\n']
208 rpt_add = report.append
209 rpt_add(sys_info())
211 try:
212 config = pformat(self.app.config)
213 rpt_add(sec_sep)
214 rpt_add('Application name: %s\n\n' % self.app_name)
215 rpt_add('Current user configuration structure:\n\n')
216 rpt_add(config)
217 except:
218 pass
219 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback)
221 return ''.join(report)
224def crash_handler_lite(etype, evalue, tb):
225 """a light excepthook, adding a small message to the usual traceback"""
226 traceback.print_exception(etype, evalue, tb)
228 from IPython.core.interactiveshell import InteractiveShell
229 if InteractiveShell.initialized():
230 # we are in a Shell environment, give %magic example
231 config = "%config "
232 else:
233 # we are not in a shell, show generic config
234 config = "c."
235 print(_lite_message_template.format(email=author_email, config=config, version=version), file=sys.stderr)