(self, frame: inspect.FrameInfo, is_collapsed: bool)
| 197 | return CENTER_LINE.format(**values) |
| 198 | |
| 199 | def generate_frame_html(self, frame: inspect.FrameInfo, is_collapsed: bool) -> str: |
| 200 | code_context = "".join( |
| 201 | self.format_line( |
| 202 | index, |
| 203 | line, |
| 204 | frame.lineno, |
| 205 | frame.index, # type: ignore[arg-type] |
| 206 | ) |
| 207 | for index, line in enumerate(frame.code_context or []) |
| 208 | ) |
| 209 | |
| 210 | values = { |
| 211 | # HTML escape - filename could contain < or >, especially if it's a virtual |
| 212 | # file e.g. <stdin> in the REPL |
| 213 | "frame_filename": html.escape(frame.filename), |
| 214 | "frame_lineno": frame.lineno, |
| 215 | # HTML escape - if you try very hard it's possible to name a function with < |
| 216 | # or > |
| 217 | "frame_name": html.escape(frame.function), |
| 218 | "code_context": code_context, |
| 219 | "collapsed": "collapsed" if is_collapsed else "", |
| 220 | "collapse_button": "+" if is_collapsed else "‒", |
| 221 | } |
| 222 | return FRAME_TEMPLATE.format(**values) |
| 223 | |
| 224 | def generate_html(self, exc: Exception, limit: int = 7) -> str: |
| 225 | traceback_obj = traceback.TracebackException.from_exception(exc, capture_locals=True) |
no test coverage detected