Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pip/_vendor/rich/traceback.py: 29%
241 statements
« prev ^ index » next coverage.py v7.4.3, created at 2024-02-26 06:33 +0000
« prev ^ index » next coverage.py v7.4.3, created at 2024-02-26 06:33 +0000
1from __future__ import absolute_import
3import linecache
4import os
5import platform
6import sys
7from dataclasses import dataclass, field
8from traceback import walk_tb
9from types import ModuleType, TracebackType
10from typing import (
11 Any,
12 Callable,
13 Dict,
14 Iterable,
15 List,
16 Optional,
17 Sequence,
18 Tuple,
19 Type,
20 Union,
21)
23from pip._vendor.pygments.lexers import guess_lexer_for_filename
24from pip._vendor.pygments.token import Comment, Keyword, Name, Number, Operator, String
25from pip._vendor.pygments.token import Text as TextToken
26from pip._vendor.pygments.token import Token
27from pip._vendor.pygments.util import ClassNotFound
29from . import pretty
30from ._loop import loop_last
31from .columns import Columns
32from .console import Console, ConsoleOptions, ConsoleRenderable, RenderResult, group
33from .constrain import Constrain
34from .highlighter import RegexHighlighter, ReprHighlighter
35from .panel import Panel
36from .scope import render_scope
37from .style import Style
38from .syntax import Syntax
39from .text import Text
40from .theme import Theme
42WINDOWS = platform.system() == "Windows"
44LOCALS_MAX_LENGTH = 10
45LOCALS_MAX_STRING = 80
48def install(
49 *,
50 console: Optional[Console] = None,
51 width: Optional[int] = 100,
52 extra_lines: int = 3,
53 theme: Optional[str] = None,
54 word_wrap: bool = False,
55 show_locals: bool = False,
56 locals_max_length: int = LOCALS_MAX_LENGTH,
57 locals_max_string: int = LOCALS_MAX_STRING,
58 locals_hide_dunder: bool = True,
59 locals_hide_sunder: Optional[bool] = None,
60 indent_guides: bool = True,
61 suppress: Iterable[Union[str, ModuleType]] = (),
62 max_frames: int = 100,
63) -> Callable[[Type[BaseException], BaseException, Optional[TracebackType]], Any]:
64 """Install a rich traceback handler.
66 Once installed, any tracebacks will be printed with syntax highlighting and rich formatting.
69 Args:
70 console (Optional[Console], optional): Console to write exception to. Default uses internal Console instance.
71 width (Optional[int], optional): Width (in characters) of traceback. Defaults to 100.
72 extra_lines (int, optional): Extra lines of code. Defaults to 3.
73 theme (Optional[str], optional): Pygments theme to use in traceback. Defaults to ``None`` which will pick
74 a theme appropriate for the platform.
75 word_wrap (bool, optional): Enable word wrapping of long lines. Defaults to False.
76 show_locals (bool, optional): Enable display of local variables. Defaults to False.
77 locals_max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation.
78 Defaults to 10.
79 locals_max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to 80.
80 locals_hide_dunder (bool, optional): Hide locals prefixed with double underscore. Defaults to True.
81 locals_hide_sunder (bool, optional): Hide locals prefixed with single underscore. Defaults to False.
82 indent_guides (bool, optional): Enable indent guides in code and locals. Defaults to True.
83 suppress (Sequence[Union[str, ModuleType]]): Optional sequence of modules or paths to exclude from traceback.
85 Returns:
86 Callable: The previous exception handler that was replaced.
88 """
89 traceback_console = Console(stderr=True) if console is None else console
91 locals_hide_sunder = (
92 True
93 if (traceback_console.is_jupyter and locals_hide_sunder is None)
94 else locals_hide_sunder
95 )
97 def excepthook(
98 type_: Type[BaseException],
99 value: BaseException,
100 traceback: Optional[TracebackType],
101 ) -> None:
102 traceback_console.print(
103 Traceback.from_exception(
104 type_,
105 value,
106 traceback,
107 width=width,
108 extra_lines=extra_lines,
109 theme=theme,
110 word_wrap=word_wrap,
111 show_locals=show_locals,
112 locals_max_length=locals_max_length,
113 locals_max_string=locals_max_string,
114 locals_hide_dunder=locals_hide_dunder,
115 locals_hide_sunder=bool(locals_hide_sunder),
116 indent_guides=indent_guides,
117 suppress=suppress,
118 max_frames=max_frames,
119 )
120 )
122 def ipy_excepthook_closure(ip: Any) -> None: # pragma: no cover
123 tb_data = {} # store information about showtraceback call
124 default_showtraceback = ip.showtraceback # keep reference of default traceback
126 def ipy_show_traceback(*args: Any, **kwargs: Any) -> None:
127 """wrap the default ip.showtraceback to store info for ip._showtraceback"""
128 nonlocal tb_data
129 tb_data = kwargs
130 default_showtraceback(*args, **kwargs)
132 def ipy_display_traceback(
133 *args: Any, is_syntax: bool = False, **kwargs: Any
134 ) -> None:
135 """Internally called traceback from ip._showtraceback"""
136 nonlocal tb_data
137 exc_tuple = ip._get_exc_info()
139 # do not display trace on syntax error
140 tb: Optional[TracebackType] = None if is_syntax else exc_tuple[2]
142 # determine correct tb_offset
143 compiled = tb_data.get("running_compiled_code", False)
144 tb_offset = tb_data.get("tb_offset", 1 if compiled else 0)
145 # remove ipython internal frames from trace with tb_offset
146 for _ in range(tb_offset):
147 if tb is None:
148 break
149 tb = tb.tb_next
151 excepthook(exc_tuple[0], exc_tuple[1], tb)
152 tb_data = {} # clear data upon usage
154 # replace _showtraceback instead of showtraceback to allow ipython features such as debugging to work
155 # this is also what the ipython docs recommends to modify when subclassing InteractiveShell
156 ip._showtraceback = ipy_display_traceback
157 # add wrapper to capture tb_data
158 ip.showtraceback = ipy_show_traceback
159 ip.showsyntaxerror = lambda *args, **kwargs: ipy_display_traceback(
160 *args, is_syntax=True, **kwargs
161 )
163 try: # pragma: no cover
164 # if within ipython, use customized traceback
165 ip = get_ipython() # type: ignore[name-defined]
166 ipy_excepthook_closure(ip)
167 return sys.excepthook
168 except Exception:
169 # otherwise use default system hook
170 old_excepthook = sys.excepthook
171 sys.excepthook = excepthook
172 return old_excepthook
175@dataclass
176class Frame:
177 filename: str
178 lineno: int
179 name: str
180 line: str = ""
181 locals: Optional[Dict[str, pretty.Node]] = None
184@dataclass
185class _SyntaxError:
186 offset: int
187 filename: str
188 line: str
189 lineno: int
190 msg: str
193@dataclass
194class Stack:
195 exc_type: str
196 exc_value: str
197 syntax_error: Optional[_SyntaxError] = None
198 is_cause: bool = False
199 frames: List[Frame] = field(default_factory=list)
202@dataclass
203class Trace:
204 stacks: List[Stack]
207class PathHighlighter(RegexHighlighter):
208 highlights = [r"(?P<dim>.*/)(?P<bold>.+)"]
211class Traceback:
212 """A Console renderable that renders a traceback.
214 Args:
215 trace (Trace, optional): A `Trace` object produced from `extract`. Defaults to None, which uses
216 the last exception.
217 width (Optional[int], optional): Number of characters used to traceback. Defaults to 100.
218 extra_lines (int, optional): Additional lines of code to render. Defaults to 3.
219 theme (str, optional): Override pygments theme used in traceback.
220 word_wrap (bool, optional): Enable word wrapping of long lines. Defaults to False.
221 show_locals (bool, optional): Enable display of local variables. Defaults to False.
222 indent_guides (bool, optional): Enable indent guides in code and locals. Defaults to True.
223 locals_max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation.
224 Defaults to 10.
225 locals_max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to 80.
226 locals_hide_dunder (bool, optional): Hide locals prefixed with double underscore. Defaults to True.
227 locals_hide_sunder (bool, optional): Hide locals prefixed with single underscore. Defaults to False.
228 suppress (Sequence[Union[str, ModuleType]]): Optional sequence of modules or paths to exclude from traceback.
229 max_frames (int): Maximum number of frames to show in a traceback, 0 for no maximum. Defaults to 100.
231 """
233 LEXERS = {
234 "": "text",
235 ".py": "python",
236 ".pxd": "cython",
237 ".pyx": "cython",
238 ".pxi": "pyrex",
239 }
241 def __init__(
242 self,
243 trace: Optional[Trace] = None,
244 *,
245 width: Optional[int] = 100,
246 extra_lines: int = 3,
247 theme: Optional[str] = None,
248 word_wrap: bool = False,
249 show_locals: bool = False,
250 locals_max_length: int = LOCALS_MAX_LENGTH,
251 locals_max_string: int = LOCALS_MAX_STRING,
252 locals_hide_dunder: bool = True,
253 locals_hide_sunder: bool = False,
254 indent_guides: bool = True,
255 suppress: Iterable[Union[str, ModuleType]] = (),
256 max_frames: int = 100,
257 ):
258 if trace is None:
259 exc_type, exc_value, traceback = sys.exc_info()
260 if exc_type is None or exc_value is None or traceback is None:
261 raise ValueError(
262 "Value for 'trace' required if not called in except: block"
263 )
264 trace = self.extract(
265 exc_type, exc_value, traceback, show_locals=show_locals
266 )
267 self.trace = trace
268 self.width = width
269 self.extra_lines = extra_lines
270 self.theme = Syntax.get_theme(theme or "ansi_dark")
271 self.word_wrap = word_wrap
272 self.show_locals = show_locals
273 self.indent_guides = indent_guides
274 self.locals_max_length = locals_max_length
275 self.locals_max_string = locals_max_string
276 self.locals_hide_dunder = locals_hide_dunder
277 self.locals_hide_sunder = locals_hide_sunder
279 self.suppress: Sequence[str] = []
280 for suppress_entity in suppress:
281 if not isinstance(suppress_entity, str):
282 assert (
283 suppress_entity.__file__ is not None
284 ), f"{suppress_entity!r} must be a module with '__file__' attribute"
285 path = os.path.dirname(suppress_entity.__file__)
286 else:
287 path = suppress_entity
288 path = os.path.normpath(os.path.abspath(path))
289 self.suppress.append(path)
290 self.max_frames = max(4, max_frames) if max_frames > 0 else 0
292 @classmethod
293 def from_exception(
294 cls,
295 exc_type: Type[Any],
296 exc_value: BaseException,
297 traceback: Optional[TracebackType],
298 *,
299 width: Optional[int] = 100,
300 extra_lines: int = 3,
301 theme: Optional[str] = None,
302 word_wrap: bool = False,
303 show_locals: bool = False,
304 locals_max_length: int = LOCALS_MAX_LENGTH,
305 locals_max_string: int = LOCALS_MAX_STRING,
306 locals_hide_dunder: bool = True,
307 locals_hide_sunder: bool = False,
308 indent_guides: bool = True,
309 suppress: Iterable[Union[str, ModuleType]] = (),
310 max_frames: int = 100,
311 ) -> "Traceback":
312 """Create a traceback from exception info
314 Args:
315 exc_type (Type[BaseException]): Exception type.
316 exc_value (BaseException): Exception value.
317 traceback (TracebackType): Python Traceback object.
318 width (Optional[int], optional): Number of characters used to traceback. Defaults to 100.
319 extra_lines (int, optional): Additional lines of code to render. Defaults to 3.
320 theme (str, optional): Override pygments theme used in traceback.
321 word_wrap (bool, optional): Enable word wrapping of long lines. Defaults to False.
322 show_locals (bool, optional): Enable display of local variables. Defaults to False.
323 indent_guides (bool, optional): Enable indent guides in code and locals. Defaults to True.
324 locals_max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation.
325 Defaults to 10.
326 locals_max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to 80.
327 locals_hide_dunder (bool, optional): Hide locals prefixed with double underscore. Defaults to True.
328 locals_hide_sunder (bool, optional): Hide locals prefixed with single underscore. Defaults to False.
329 suppress (Iterable[Union[str, ModuleType]]): Optional sequence of modules or paths to exclude from traceback.
330 max_frames (int): Maximum number of frames to show in a traceback, 0 for no maximum. Defaults to 100.
332 Returns:
333 Traceback: A Traceback instance that may be printed.
334 """
335 rich_traceback = cls.extract(
336 exc_type,
337 exc_value,
338 traceback,
339 show_locals=show_locals,
340 locals_max_length=locals_max_length,
341 locals_max_string=locals_max_string,
342 locals_hide_dunder=locals_hide_dunder,
343 locals_hide_sunder=locals_hide_sunder,
344 )
346 return cls(
347 rich_traceback,
348 width=width,
349 extra_lines=extra_lines,
350 theme=theme,
351 word_wrap=word_wrap,
352 show_locals=show_locals,
353 indent_guides=indent_guides,
354 locals_max_length=locals_max_length,
355 locals_max_string=locals_max_string,
356 locals_hide_dunder=locals_hide_dunder,
357 locals_hide_sunder=locals_hide_sunder,
358 suppress=suppress,
359 max_frames=max_frames,
360 )
362 @classmethod
363 def extract(
364 cls,
365 exc_type: Type[BaseException],
366 exc_value: BaseException,
367 traceback: Optional[TracebackType],
368 *,
369 show_locals: bool = False,
370 locals_max_length: int = LOCALS_MAX_LENGTH,
371 locals_max_string: int = LOCALS_MAX_STRING,
372 locals_hide_dunder: bool = True,
373 locals_hide_sunder: bool = False,
374 ) -> Trace:
375 """Extract traceback information.
377 Args:
378 exc_type (Type[BaseException]): Exception type.
379 exc_value (BaseException): Exception value.
380 traceback (TracebackType): Python Traceback object.
381 show_locals (bool, optional): Enable display of local variables. Defaults to False.
382 locals_max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation.
383 Defaults to 10.
384 locals_max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to 80.
385 locals_hide_dunder (bool, optional): Hide locals prefixed with double underscore. Defaults to True.
386 locals_hide_sunder (bool, optional): Hide locals prefixed with single underscore. Defaults to False.
388 Returns:
389 Trace: A Trace instance which you can use to construct a `Traceback`.
390 """
392 stacks: List[Stack] = []
393 is_cause = False
395 from pip._vendor.rich import _IMPORT_CWD
397 def safe_str(_object: Any) -> str:
398 """Don't allow exceptions from __str__ to propagate."""
399 try:
400 return str(_object)
401 except Exception:
402 return "<exception str() failed>"
404 while True:
405 stack = Stack(
406 exc_type=safe_str(exc_type.__name__),
407 exc_value=safe_str(exc_value),
408 is_cause=is_cause,
409 )
411 if isinstance(exc_value, SyntaxError):
412 stack.syntax_error = _SyntaxError(
413 offset=exc_value.offset or 0,
414 filename=exc_value.filename or "?",
415 lineno=exc_value.lineno or 0,
416 line=exc_value.text or "",
417 msg=exc_value.msg,
418 )
420 stacks.append(stack)
421 append = stack.frames.append
423 def get_locals(
424 iter_locals: Iterable[Tuple[str, object]]
425 ) -> Iterable[Tuple[str, object]]:
426 """Extract locals from an iterator of key pairs."""
427 if not (locals_hide_dunder or locals_hide_sunder):
428 yield from iter_locals
429 return
430 for key, value in iter_locals:
431 if locals_hide_dunder and key.startswith("__"):
432 continue
433 if locals_hide_sunder and key.startswith("_"):
434 continue
435 yield key, value
437 for frame_summary, line_no in walk_tb(traceback):
438 filename = frame_summary.f_code.co_filename
439 if filename and not filename.startswith("<"):
440 if not os.path.isabs(filename):
441 filename = os.path.join(_IMPORT_CWD, filename)
442 if frame_summary.f_locals.get("_rich_traceback_omit", False):
443 continue
445 frame = Frame(
446 filename=filename or "?",
447 lineno=line_no,
448 name=frame_summary.f_code.co_name,
449 locals={
450 key: pretty.traverse(
451 value,
452 max_length=locals_max_length,
453 max_string=locals_max_string,
454 )
455 for key, value in get_locals(frame_summary.f_locals.items())
456 }
457 if show_locals
458 else None,
459 )
460 append(frame)
461 if frame_summary.f_locals.get("_rich_traceback_guard", False):
462 del stack.frames[:]
464 cause = getattr(exc_value, "__cause__", None)
465 if cause:
466 exc_type = cause.__class__
467 exc_value = cause
468 # __traceback__ can be None, e.g. for exceptions raised by the
469 # 'multiprocessing' module
470 traceback = cause.__traceback__
471 is_cause = True
472 continue
474 cause = exc_value.__context__
475 if cause and not getattr(exc_value, "__suppress_context__", False):
476 exc_type = cause.__class__
477 exc_value = cause
478 traceback = cause.__traceback__
479 is_cause = False
480 continue
481 # No cover, code is reached but coverage doesn't recognize it.
482 break # pragma: no cover
484 trace = Trace(stacks=stacks)
485 return trace
487 def __rich_console__(
488 self, console: Console, options: ConsoleOptions
489 ) -> RenderResult:
490 theme = self.theme
491 background_style = theme.get_background_style()
492 token_style = theme.get_style_for_token
494 traceback_theme = Theme(
495 {
496 "pretty": token_style(TextToken),
497 "pygments.text": token_style(Token),
498 "pygments.string": token_style(String),
499 "pygments.function": token_style(Name.Function),
500 "pygments.number": token_style(Number),
501 "repr.indent": token_style(Comment) + Style(dim=True),
502 "repr.str": token_style(String),
503 "repr.brace": token_style(TextToken) + Style(bold=True),
504 "repr.number": token_style(Number),
505 "repr.bool_true": token_style(Keyword.Constant),
506 "repr.bool_false": token_style(Keyword.Constant),
507 "repr.none": token_style(Keyword.Constant),
508 "scope.border": token_style(String.Delimiter),
509 "scope.equals": token_style(Operator),
510 "scope.key": token_style(Name),
511 "scope.key.special": token_style(Name.Constant) + Style(dim=True),
512 },
513 inherit=False,
514 )
516 highlighter = ReprHighlighter()
517 for last, stack in loop_last(reversed(self.trace.stacks)):
518 if stack.frames:
519 stack_renderable: ConsoleRenderable = Panel(
520 self._render_stack(stack),
521 title="[traceback.title]Traceback [dim](most recent call last)",
522 style=background_style,
523 border_style="traceback.border",
524 expand=True,
525 padding=(0, 1),
526 )
527 stack_renderable = Constrain(stack_renderable, self.width)
528 with console.use_theme(traceback_theme):
529 yield stack_renderable
530 if stack.syntax_error is not None:
531 with console.use_theme(traceback_theme):
532 yield Constrain(
533 Panel(
534 self._render_syntax_error(stack.syntax_error),
535 style=background_style,
536 border_style="traceback.border.syntax_error",
537 expand=True,
538 padding=(0, 1),
539 width=self.width,
540 ),
541 self.width,
542 )
543 yield Text.assemble(
544 (f"{stack.exc_type}: ", "traceback.exc_type"),
545 highlighter(stack.syntax_error.msg),
546 )
547 elif stack.exc_value:
548 yield Text.assemble(
549 (f"{stack.exc_type}: ", "traceback.exc_type"),
550 highlighter(stack.exc_value),
551 )
552 else:
553 yield Text.assemble((f"{stack.exc_type}", "traceback.exc_type"))
555 if not last:
556 if stack.is_cause:
557 yield Text.from_markup(
558 "\n[i]The above exception was the direct cause of the following exception:\n",
559 )
560 else:
561 yield Text.from_markup(
562 "\n[i]During handling of the above exception, another exception occurred:\n",
563 )
565 @group()
566 def _render_syntax_error(self, syntax_error: _SyntaxError) -> RenderResult:
567 highlighter = ReprHighlighter()
568 path_highlighter = PathHighlighter()
569 if syntax_error.filename != "<stdin>":
570 if os.path.exists(syntax_error.filename):
571 text = Text.assemble(
572 (f" {syntax_error.filename}", "pygments.string"),
573 (":", "pygments.text"),
574 (str(syntax_error.lineno), "pygments.number"),
575 style="pygments.text",
576 )
577 yield path_highlighter(text)
578 syntax_error_text = highlighter(syntax_error.line.rstrip())
579 syntax_error_text.no_wrap = True
580 offset = min(syntax_error.offset - 1, len(syntax_error_text))
581 syntax_error_text.stylize("bold underline", offset, offset)
582 syntax_error_text += Text.from_markup(
583 "\n" + " " * offset + "[traceback.offset]▲[/]",
584 style="pygments.text",
585 )
586 yield syntax_error_text
588 @classmethod
589 def _guess_lexer(cls, filename: str, code: str) -> str:
590 ext = os.path.splitext(filename)[-1]
591 if not ext:
592 # No extension, look at first line to see if it is a hashbang
593 # Note, this is an educated guess and not a guarantee
594 # If it fails, the only downside is that the code is highlighted strangely
595 new_line_index = code.index("\n")
596 first_line = code[:new_line_index] if new_line_index != -1 else code
597 if first_line.startswith("#!") and "python" in first_line.lower():
598 return "python"
599 try:
600 return cls.LEXERS.get(ext) or guess_lexer_for_filename(filename, code).name
601 except ClassNotFound:
602 return "text"
604 @group()
605 def _render_stack(self, stack: Stack) -> RenderResult:
606 path_highlighter = PathHighlighter()
607 theme = self.theme
609 def read_code(filename: str) -> str:
610 """Read files, and cache results on filename.
612 Args:
613 filename (str): Filename to read
615 Returns:
616 str: Contents of file
617 """
618 return "".join(linecache.getlines(filename))
620 def render_locals(frame: Frame) -> Iterable[ConsoleRenderable]:
621 if frame.locals:
622 yield render_scope(
623 frame.locals,
624 title="locals",
625 indent_guides=self.indent_guides,
626 max_length=self.locals_max_length,
627 max_string=self.locals_max_string,
628 )
630 exclude_frames: Optional[range] = None
631 if self.max_frames != 0:
632 exclude_frames = range(
633 self.max_frames // 2,
634 len(stack.frames) - self.max_frames // 2,
635 )
637 excluded = False
638 for frame_index, frame in enumerate(stack.frames):
640 if exclude_frames and frame_index in exclude_frames:
641 excluded = True
642 continue
644 if excluded:
645 assert exclude_frames is not None
646 yield Text(
647 f"\n... {len(exclude_frames)} frames hidden ...",
648 justify="center",
649 style="traceback.error",
650 )
651 excluded = False
653 first = frame_index == 0
654 frame_filename = frame.filename
655 suppressed = any(frame_filename.startswith(path) for path in self.suppress)
657 if os.path.exists(frame.filename):
658 text = Text.assemble(
659 path_highlighter(Text(frame.filename, style="pygments.string")),
660 (":", "pygments.text"),
661 (str(frame.lineno), "pygments.number"),
662 " in ",
663 (frame.name, "pygments.function"),
664 style="pygments.text",
665 )
666 else:
667 text = Text.assemble(
668 "in ",
669 (frame.name, "pygments.function"),
670 (":", "pygments.text"),
671 (str(frame.lineno), "pygments.number"),
672 style="pygments.text",
673 )
674 if not frame.filename.startswith("<") and not first:
675 yield ""
676 yield text
677 if frame.filename.startswith("<"):
678 yield from render_locals(frame)
679 continue
680 if not suppressed:
681 try:
682 code = read_code(frame.filename)
683 if not code:
684 # code may be an empty string if the file doesn't exist, OR
685 # if the traceback filename is generated dynamically
686 continue
687 lexer_name = self._guess_lexer(frame.filename, code)
688 syntax = Syntax(
689 code,
690 lexer_name,
691 theme=theme,
692 line_numbers=True,
693 line_range=(
694 frame.lineno - self.extra_lines,
695 frame.lineno + self.extra_lines,
696 ),
697 highlight_lines={frame.lineno},
698 word_wrap=self.word_wrap,
699 code_width=88,
700 indent_guides=self.indent_guides,
701 dedent=False,
702 )
703 yield ""
704 except Exception as error:
705 yield Text.assemble(
706 (f"\n{error}", "traceback.error"),
707 )
708 else:
709 yield (
710 Columns(
711 [
712 syntax,
713 *render_locals(frame),
714 ],
715 padding=1,
716 )
717 if frame.locals
718 else syntax
719 )
722if __name__ == "__main__": # pragma: no cover
724 from .console import Console
726 console = Console()
727 import sys
729 def bar(a: Any) -> None: # 这是对亚洲语言支持的测试。面对模棱两可的想法,拒绝猜测的诱惑
730 one = 1
731 print(one / a)
733 def foo(a: Any) -> None:
734 _rich_traceback_guard = True
735 zed = {
736 "characters": {
737 "Paul Atreides",
738 "Vladimir Harkonnen",
739 "Thufir Hawat",
740 "Duncan Idaho",
741 },
742 "atomic_types": (None, False, True),
743 }
744 bar(a)
746 def error() -> None:
748 try:
749 try:
750 foo(0)
751 except:
752 slfkjsldkfj # type: ignore[name-defined]
753 except:
754 console.print_exception(show_locals=True)
756 error()