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

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

76 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 

21import sys 

22import traceback 

23from pprint import pformat 

24from pathlib import Path 

25 

26import builtins as builtin_mod 

27 

28from IPython.core import ultratb 

29from IPython.core.application import Application 

30from IPython.core.release import author_email 

31from IPython.utils.sysinfo import sys_info 

32 

33from IPython.core.release import __version__ as version 

34 

35from typing import Optional, Dict 

36import types 

37 

38#----------------------------------------------------------------------------- 

39# Code 

40#----------------------------------------------------------------------------- 

41 

42# Template for the user message. 

43_default_message_template = """\ 

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

45 

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

47 - A verbatim copy of the crash traceback. 

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

49 - Data on your current {app_name} configuration. 

50 

51It was left in the file named: 

52\t'{crash_report_fname}' 

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

54them in understanding and correcting the problem. 

55 

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

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

58 

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

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

61 

62In your email, please also include information about: 

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

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

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

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

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

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

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

70 of instructions that yields the crash. 

71 

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

73{bug_tracker} 

74""" 

75 

76_lite_message_template = """ 

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

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

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

80 

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

82to interactively debug it. 

83 

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

85 {config}Application.verbose_crash=True 

86""" 

87 

88 

89class CrashHandler: 

90 """Customizable crash handlers for IPython applications. 

91 

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

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

94 

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

96 """ 

97 

98 message_template = _default_message_template 

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

100 info: Dict[str, Optional[str]] 

101 

102 def __init__( 

103 self, 

104 app: Application, 

105 contact_name: Optional[str] = None, 

106 contact_email: Optional[str] = None, 

107 bug_tracker: Optional[str] = None, 

108 show_crash_traceback: bool = True, 

109 call_pdb: bool = False, 

110 ): 

111 """Create a new crash handler 

112 

113 Parameters 

114 ---------- 

115 app : Application 

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

117 crash time for internal information. 

118 contact_name : str 

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

120 contact_email : str 

121 A string with the email address of the contact. 

122 bug_tracker : str 

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

124 show_crash_traceback : bool 

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

126 the on-disk report 

127 call_pdb 

128 Whether to call pdb on crash 

129 

130 Attributes 

131 ---------- 

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

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

134 source for further details. 

135 

136 """ 

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

138 self.app = app 

139 self.call_pdb = call_pdb 

140 #self.call_pdb = True # dbg 

141 self.show_crash_traceback = show_crash_traceback 

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

143 contact_name = contact_name, 

144 contact_email = contact_email, 

145 bug_tracker = bug_tracker, 

146 crash_report_fname = self.crash_report_fname) 

147 

148 def __call__( 

149 self, 

150 etype: type[BaseException], 

151 evalue: BaseException, 

152 etb: types.TracebackType, 

153 ) -> None: 

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

155 

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

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

158 # infinite loop. 

159 sys.excepthook = sys.__excepthook__ 

160 

161 

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

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

164 if ipython_dir is not None: 

165 assert isinstance(ipython_dir, str) 

166 rptdir = Path(ipython_dir) 

167 else: 

168 rptdir = Path.cwd() 

169 if not rptdir.is_dir(): 

170 rptdir = Path.cwd() 

171 report_name = rptdir / self.crash_report_fname 

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

173 # properly expanded out in the user message template 

174 self.crash_report_fname = str(report_name) 

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

176 TBhandler = ultratb.VerboseTB( 

177 theme_name="nocolor", 

178 long_header=True, 

179 call_pdb=self.call_pdb, 

180 ) 

181 if self.call_pdb: 

182 TBhandler(etype,evalue,etb) 

183 return 

184 else: 

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

186 

187 # print traceback to screen 

188 if self.show_crash_traceback: 

189 print(traceback, file=sys.stderr) 

190 

191 # and generate a complete report on disk 

192 try: 

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

194 except: 

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

196 return 

197 

198 with report: 

199 # Inform user on stderr of what happened 

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

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

202 

203 # Construct report on disk 

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

205 

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

207 

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

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

210 

211 sec_sep = self.section_sep 

212 

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

214 rpt_add = report.append 

215 rpt_add(sys_info()) 

216 

217 try: 

218 config = pformat(self.app.config) 

219 rpt_add(sec_sep) 

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

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

222 rpt_add(config) 

223 except: 

224 pass 

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

226 

227 return ''.join(report) 

228 

229 

230def crash_handler_lite( 

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

232) -> None: 

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

234 traceback.print_exception(etype, evalue, tb) 

235 

236 from IPython.core.interactiveshell import InteractiveShell 

237 if InteractiveShell.initialized(): 

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

239 config = "%config " 

240 else: 

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

242 config = "c." 

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

244