Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/IPython/core/crashhandler.py: 31%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

78 statements  

1"""sys.excepthook for IPython itself, leaves a detailed report on disk. 

2 

3Authors: 

4 

5* Fernando Perez 

6* Brian E. Granger 

7""" 

8 

9#----------------------------------------------------------------------------- 

10# Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu> 

11# Copyright (C) 2008-2011 The IPython Development Team 

12# 

13# Distributed under the terms of the BSD License. The full license is in 

14# the file COPYING, distributed as part of this software. 

15#----------------------------------------------------------------------------- 

16 

17#----------------------------------------------------------------------------- 

18# Imports 

19#----------------------------------------------------------------------------- 

20 

21from __future__ import annotations 

22 

23import sys 

24import traceback 

25from pprint import pformat 

26from pathlib import Path 

27 

28import builtins as builtin_mod 

29 

30from typing import TYPE_CHECKING 

31 

32from IPython.core import ultratb 

33from IPython.core.release import author_email 

34from IPython.utils.sysinfo import sys_info 

35 

36from IPython.core.release import __version__ as version 

37 

38import types 

39 

40if TYPE_CHECKING: 

41 # avoid a circular import: application imports crashhandler at module load 

42 from IPython.core.application import Application 

43 

44#----------------------------------------------------------------------------- 

45# Code 

46#----------------------------------------------------------------------------- 

47 

48# Template for the user message. 

49_default_message_template = """\ 

50Oops, {app_name} crashed. We do our best to make it stable, but... 

51 

52A crash report was automatically generated with the following information: 

53 - A verbatim copy of the crash traceback. 

54 - A copy of your input history during this session. 

55 - Data on your current {app_name} configuration. 

56 

57It was left in the file named: 

58\t'{crash_report_fname}' 

59If you can email this file to the developers, the information in it will help 

60them in understanding and correcting the problem. 

61 

62You can mail it to: {contact_name} at {contact_email} 

63with the subject '{app_name} Crash Report'. 

64 

65If you want to do it now, the following command will work (under Unix): 

66mail -s '{app_name} Crash Report' {contact_email} < {crash_report_fname} 

67 

68In your email, please also include information about: 

69- The operating system under which the crash happened: Linux, macOS, Windows, 

70 other, and which exact version (for example: Ubuntu 16.04.3, macOS 10.13.2, 

71 Windows 10 Pro), and whether it is 32-bit or 64-bit; 

72- How {app_name} was installed: using pip or conda, from GitHub, as part of 

73 a Docker container, or other, providing more detail if possible; 

74- How to reproduce the crash: what exact sequence of instructions can one 

75 input to get the same crash? Ideally, find a minimal yet complete sequence 

76 of instructions that yields the crash. 

77 

78To ensure accurate tracking of this issue, please file a report about it at: 

79{bug_tracker} 

80""" 

81 

82_lite_message_template = """ 

83If you suspect this is an IPython {version} bug, please report it at: 

84 https://github.com/ipython/ipython/issues 

85or send an email to the mailing list at {email} 

86 

87You can print a more detailed traceback right now with "%tb", or use "%debug" 

88to interactively debug it. 

89 

90Extra-detailed tracebacks for bug-reporting purposes can be enabled via: 

91 {config}Application.verbose_crash=True 

92""" 

93 

94 

95class CrashHandler: 

96 """Customizable crash handlers for IPython applications. 

97 

98 Instances of this class provide a :meth:`__call__` method which can be 

99 used as a ``sys.excepthook``. The :meth:`__call__` signature is:: 

100 

101 def __call__(self, etype, evalue, etb) 

102 """ 

103 

104 message_template = _default_message_template 

105 section_sep = '\n\n'+'*'*75+'\n\n' 

106 info: dict[str, str | None] 

107 

108 def __init__( 

109 self, 

110 app: Application, 

111 contact_name: str | None = None, 

112 contact_email: str | None = None, 

113 bug_tracker: str | None = None, 

114 show_crash_traceback: bool = True, 

115 call_pdb: bool = False, 

116 ): 

117 """Create a new crash handler 

118 

119 Parameters 

120 ---------- 

121 app : Application 

122 A running :class:`Application` instance, which will be queried at 

123 crash time for internal information. 

124 contact_name : str 

125 A string with the name of the person to contact. 

126 contact_email : str 

127 A string with the email address of the contact. 

128 bug_tracker : str 

129 A string with the URL for your project's bug tracker. 

130 show_crash_traceback : bool 

131 If false, don't print the crash traceback on stderr, only generate 

132 the on-disk report 

133 call_pdb 

134 Whether to call pdb on crash 

135 

136 Attributes 

137 ---------- 

138 These instances contain some non-argument attributes which allow for 

139 further customization of the crash handler's behavior. Please see the 

140 source for further details. 

141 

142 """ 

143 self.crash_report_fname = "Crash_report_%s.txt" % app.name 

144 self.app = app 

145 self.call_pdb = call_pdb 

146 #self.call_pdb = True # dbg 

147 self.show_crash_traceback = show_crash_traceback 

148 self.info = dict(app_name = app.name, 

149 contact_name = contact_name, 

150 contact_email = contact_email, 

151 bug_tracker = bug_tracker, 

152 crash_report_fname = self.crash_report_fname) 

153 

154 def __call__( 

155 self, 

156 etype: type[BaseException], 

157 evalue: BaseException, 

158 etb: types.TracebackType, 

159 ) -> None: 

160 """Handle an exception, call for compatible with sys.excepthook""" 

161 

162 # do not allow the crash handler to be called twice without reinstalling it 

163 # this prevents unlikely errors in the crash handling from entering an 

164 # infinite loop. 

165 sys.excepthook = sys.__excepthook__ 

166 

167 # Use this ONLY for developer debugging (keep commented out for release) 

168 ipython_dir = getattr(self.app, "ipython_dir", None) 

169 if ipython_dir is not None: 

170 assert isinstance(ipython_dir, str) 

171 rptdir = Path(ipython_dir) 

172 else: 

173 rptdir = Path.cwd() 

174 if not rptdir.is_dir(): 

175 rptdir = Path.cwd() 

176 report_name = rptdir / self.crash_report_fname 

177 # write the report filename into the instance dict so it can get 

178 # properly expanded out in the user message template 

179 self.crash_report_fname = str(report_name) 

180 self.info["crash_report_fname"] = str(report_name) 

181 TBhandler = ultratb.VerboseTB( 

182 theme_name="nocolor", 

183 long_header=True, 

184 call_pdb=self.call_pdb, 

185 ) 

186 if self.call_pdb: 

187 TBhandler(etype,evalue,etb) 

188 return 

189 else: 

190 traceback = TBhandler.text(etype,evalue,etb,context=31) 

191 

192 # print traceback to screen 

193 if self.show_crash_traceback: 

194 print(traceback, file=sys.stderr) 

195 

196 # and generate a complete report on disk 

197 try: 

198 report = open(report_name, "w", encoding="utf-8") 

199 except OSError: 

200 print('Could not create crash report on disk.', file=sys.stderr) 

201 return 

202 

203 with report: 

204 # Inform user on stderr of what happened 

205 print('\n'+'*'*70+'\n', file=sys.stderr) 

206 print(self.message_template.format(**self.info), file=sys.stderr) 

207 

208 # Construct report on disk 

209 report.write(self.make_report(str(traceback))) 

210 

211 builtin_mod.input("Hit <Enter> to quit (your terminal may close):") 

212 

213 def make_report(self, traceback: str) -> str: 

214 """Return a string containing a crash report.""" 

215 

216 sec_sep = self.section_sep 

217 

218 report = ['*'*75+'\n\n'+'IPython post-mortem report\n\n'] 

219 rpt_add = report.append 

220 rpt_add(sys_info()) 

221 

222 try: 

223 config = pformat(self.app.config) 

224 rpt_add(sec_sep) 

225 rpt_add("Application name: %s\n\n" % self.app.name) 

226 rpt_add("Current user configuration structure:\n\n") 

227 rpt_add(config) 

228 except Exception: 

229 pass 

230 rpt_add(sec_sep+'Crash traceback:\n\n' + traceback) 

231 

232 return ''.join(report) 

233 

234 

235def crash_handler_lite( 

236 etype: type[BaseException], evalue: BaseException, tb: types.TracebackType 

237) -> None: 

238 """a light excepthook, adding a small message to the usual traceback""" 

239 traceback.print_exception(etype, evalue, tb) 

240 

241 from IPython.core.interactiveshell import InteractiveShell 

242 if InteractiveShell.initialized(): 

243 # we are in a Shell environment, give %magic example 

244 config = "%config " 

245 else: 

246 # we are not in a shell, show generic config 

247 config = "c." 

248 print(_lite_message_template.format(email=author_email, config=config, version=version), file=sys.stderr)