| 273 | return "".join(self._te.format()) |
| 274 | |
| 275 | def render_traceback_html(self, include_title: bool = True) -> str: |
| 276 | library_frames = [f.is_library for f in self.all_frames] |
| 277 | mark_library = 0 < sum(library_frames) < len(library_frames) |
| 278 | rows = [] |
| 279 | |
| 280 | if not library_frames: |
| 281 | classes = "traceback noframe-traceback" |
| 282 | else: |
| 283 | classes = "traceback" |
| 284 | |
| 285 | for msg, current in reversed(self.all_tracebacks): |
| 286 | row_parts = [] |
| 287 | |
| 288 | if msg is not None: |
| 289 | row_parts.append(f'<li><div class="exc-divider">{msg}:</div>') |
| 290 | |
| 291 | for frame in current.stack: |
| 292 | frame = t.cast(DebugFrameSummary, frame) |
| 293 | info = f' title="{escape(frame.info)}"' if frame.info else "" |
| 294 | row_parts.append(f"<li{info}>{frame.render_html(mark_library)}") |
| 295 | |
| 296 | rows.append("\n".join(row_parts)) |
| 297 | |
| 298 | if sys.version_info < (3, 13): |
| 299 | exc_type_str = self._te.exc_type.__name__ |
| 300 | else: |
| 301 | exc_type_str = self._te.exc_type_str |
| 302 | |
| 303 | is_syntax_error = exc_type_str == "SyntaxError" |
| 304 | |
| 305 | if include_title: |
| 306 | if is_syntax_error: |
| 307 | title = "Syntax Error" |
| 308 | else: |
| 309 | title = "Traceback <em>(most recent call last)</em>:" |
| 310 | else: |
| 311 | title = "" |
| 312 | |
| 313 | exc_full = escape("".join(self._te.format_exception_only())) |
| 314 | |
| 315 | if is_syntax_error: |
| 316 | description = f"<pre class=syntaxerror>{exc_full}</pre>" |
| 317 | else: |
| 318 | description = f"<blockquote>{exc_full}</blockquote>" |
| 319 | |
| 320 | return SUMMARY_HTML % { |
| 321 | "classes": classes, |
| 322 | "title": f"<h3>{title}</h3>", |
| 323 | "frames": "\n".join(rows), |
| 324 | "description": description, |
| 325 | } |
| 326 | |
| 327 | def render_debugger_html( |
| 328 | self, evalex: bool, secret: str, evalex_trusted: bool |