From 47c91815070ded3f85b719aaff11aa30b3c667da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikit=D0=B0=20Tsvetk=D0=BEv?= Date: Fri, 24 May 2024 19:05:46 +0400 Subject: [PATCH] add tb_width param (#84) --- .../rich/printer/test_rich_printer.py | 2 +- .../plugins/director/rich/reporter/_utils.py | 2 ++ .../reporter/test_rich_reporter_failed.py | 4 +++ ...t_rich_reporter_failed_legacy_verbosity.py | 5 +-- vedro/plugins/director/rich/_rich_printer.py | 11 ++++-- vedro/plugins/director/rich/_rich_reporter.py | 34 +++++++++++++++++-- 6 files changed, 50 insertions(+), 8 deletions(-) diff --git a/tests/plugins/director/rich/printer/test_rich_printer.py b/tests/plugins/director/rich/printer/test_rich_printer.py index fd61118e..4bd86c92 100644 --- a/tests/plugins/director/rich/printer/test_rich_printer.py +++ b/tests/plugins/director/rich/printer/test_rich_printer.py @@ -221,7 +221,7 @@ def test_print_exception(*, printer: RichPrinter, exc_info: ExcInfo, console_: M def test_print_pretty_exception(*, printer: RichPrinter, exc_info: ExcInfo, console_: Mock): with given: trace = Traceback.extract(exc_info.type, exc_info.value, exc_info.traceback) - tb = TestTraceback(trace, max_frames=8, word_wrap=False) + tb = TestTraceback(trace, max_frames=8, word_wrap=False, width=console_.size.width) with when: printer.print_pretty_exception(exc_info) diff --git a/tests/plugins/director/rich/reporter/_utils.py b/tests/plugins/director/rich/reporter/_utils.py index 7dbcbafd..06ca5905 100644 --- a/tests/plugins/director/rich/reporter/_utils.py +++ b/tests/plugins/director/rich/reporter/_utils.py @@ -52,6 +52,7 @@ def rich_reporter(dispatcher: Dispatcher, async def fire_arg_parsed_event(dispatcher: Dispatcher, *, verbose: int = 0, + show_scope: bool = RichReporter_.show_scope, show_timings: bool = RichReporter_.show_timings, show_paths: bool = RichReporter_.show_paths, show_steps: bool = RichReporter_.show_steps, @@ -66,6 +67,7 @@ async def fire_arg_parsed_event(dispatcher: Dispatcher, *, await dispatcher.fire(arg_parse_event) namespace = Namespace(verbose=verbose, + show_scope=show_scope, show_timings=show_timings, show_paths=show_paths, show_steps=show_steps, diff --git a/tests/plugins/director/rich/reporter/test_rich_reporter_failed.py b/tests/plugins/director/rich/reporter/test_rich_reporter_failed.py index 4c9eb6e8..de553dab 100644 --- a/tests/plugins/director/rich/reporter/test_rich_reporter_failed.py +++ b/tests/plugins/director/rich/reporter/test_rich_reporter_failed.py @@ -61,6 +61,7 @@ async def test_scenario_failed(show_locals: bool, show_internal_calls: bool, *, StepStatus.FAILED, elapsed=None, prefix=" " * 3), call.print_pretty_exception(exc_info, + width=100, max_frames=8, show_locals=show_locals, show_internal_calls=show_internal_calls) @@ -104,6 +105,7 @@ async def test_scenario_failed_show_paths(dispatcher: Dispatcher, printer_: Mock StepStatus.FAILED, elapsed=None, prefix=" " * 3), call.print_pretty_exception(exc_info, + width=100, max_frames=8, show_locals=False, show_internal_calls=False) @@ -144,6 +146,7 @@ async def test_scenario_failed_verbose(*, dispatcher: Dispatcher, printer_: Mock StepStatus.FAILED, elapsed=None, prefix=" " * 3), call.print_pretty_exception(exc_info, + width=100, max_frames=8, show_locals=False, show_internal_calls=False), @@ -188,6 +191,7 @@ async def test_scenario_failed_verbose_show_timings(dispatcher: Dispatcher, StepStatus.FAILED, elapsed=3.0, prefix=" " * 3), call.print_pretty_exception(exc_info, + width=100, max_frames=8, show_locals=False, show_internal_calls=False), diff --git a/tests/plugins/director/rich/reporter/test_rich_reporter_failed_legacy_verbosity.py b/tests/plugins/director/rich/reporter/test_rich_reporter_failed_legacy_verbosity.py index 13114773..fd532de8 100644 --- a/tests/plugins/director/rich/reporter/test_rich_reporter_failed_legacy_verbosity.py +++ b/tests/plugins/director/rich/reporter/test_rich_reporter_failed_legacy_verbosity.py @@ -105,6 +105,7 @@ async def test_scenario_failed_verbose2(show_locals: bool, show_internal_calls: StepStatus.FAILED, elapsed=None, prefix=" " * 3), call.print_pretty_exception(exc_info, + width=100, max_frames=8, show_locals=show_locals, show_internal_calls=show_internal_calls) @@ -143,7 +144,7 @@ async def test_scenario_failed_verbose3_without_scope(*, dispatcher: Dispatcher, call.print_step_name(step_result_failed.step_name, StepStatus.FAILED, elapsed=None, prefix=" " * 3), - call.print_pretty_exception(exc_info, max_frames=8, show_locals=False, + call.print_pretty_exception(exc_info, width=100, max_frames=8, show_locals=False, show_internal_calls=False), ] @@ -181,7 +182,7 @@ async def test_scenario_failed_verbose3_with_scope(*, dispatcher: Dispatcher, pr call.print_step_name(step_result_failed.step_name, StepStatus.FAILED, elapsed=None, prefix=" " * 3), - call.print_pretty_exception(exc_info, max_frames=8, show_locals=False, + call.print_pretty_exception(exc_info, width=100, max_frames=8, show_locals=False, show_internal_calls=False), call.print_scope(scope, scope_width=-1) diff --git a/vedro/plugins/director/rich/_rich_printer.py b/vedro/plugins/director/rich/_rich_printer.py index f8c79964..dab09329 100644 --- a/vedro/plugins/director/rich/_rich_printer.py +++ b/vedro/plugins/director/rich/_rich_printer.py @@ -1,6 +1,7 @@ import json import os import warnings +from atexit import register as on_exit from os import linesep from traceback import format_exception from types import FrameType, TracebackType @@ -135,7 +136,8 @@ def print_pretty_exception(self, exc_info: ExcInfo, *, max_frames: int = 8, # min=4 (see rich.traceback.Traceback impl) show_locals: bool = False, show_internal_calls: bool = False, - word_wrap: bool = False) -> None: + word_wrap: bool = False, + width: Optional[int] = None) -> None: if show_internal_calls: traceback = exc_info.traceback else: @@ -147,7 +149,11 @@ def print_pretty_exception(self, exc_info: ExcInfo, *, if show_locals: self._filter_locals(trace) - tb = self._traceback_factory(trace, max_frames=max_frames, word_wrap=word_wrap) + if width is None: + width = self._console.size.width + + tb = self._traceback_factory(trace, max_frames=max_frames, word_wrap=word_wrap, + width=width) self._console.print(tb) self.print_empty_line() @@ -251,6 +257,7 @@ def show_spinner(self, status: RenderableType = "") -> None: self.hide_spinner() self._scenario_spinner = self._console.status(status) self._scenario_spinner.start() + on_exit(self.hide_spinner) def hide_spinner(self) -> None: if self._scenario_spinner: diff --git a/vedro/plugins/director/rich/_rich_reporter.py b/vedro/plugins/director/rich/_rich_reporter.py index 173dea36..bea40aa1 100644 --- a/vedro/plugins/director/rich/_rich_reporter.py +++ b/vedro/plugins/director/rich/_rich_reporter.py @@ -31,6 +31,7 @@ def __init__(self, config: Type["RichReporter"], *, self._tb_show_locals = config.tb_show_locals self._scope_width = config.scope_width self._tb_max_frames = config.tb_max_frames + self._tb_width = config.tb_width self._show_scenario_extras = config.show_scenario_extras self._show_step_extras = config.show_step_extras self._show_skipped = config.show_skipped @@ -40,7 +41,9 @@ def __init__(self, config: Type["RichReporter"], *, self._show_steps = config.show_steps self._hide_namespaces = config.hide_namespaces self._show_scenario_spinner = config.show_scenario_spinner + self._show_discovering_spinner = False self._show_interrupted_traceback = config.show_interrupted_traceback + self._show_scope = config.show_scope self._v2_verbosity = config.v2_verbosity self._ring_bell = config.ring_bell self._namespace: Union[str, None] = None @@ -74,6 +77,11 @@ def on_arg_parse(self, event: ArgParseEvent) -> None: action="count", default=self._verbosity, help=help_message) + group.add_argument("--show-scope", + action="store_true", + default=self._show_scope, + help="Show a snapshot of crucial variables (Scope) " + "when a scenario fails") group.add_argument("--show-timings", action="store_true", default=self._show_timings, @@ -110,8 +118,14 @@ def on_arg_parse(self, event: ArgParseEvent) -> None: def on_arg_parsed(self, event: ArgParsedEvent) -> None: self._verbosity = event.args.verbose + self._show_scope = event.args.show_scope + if self._v2_verbosity: self._verbosity = self._verbosity + 2 + + if self._show_scope: + self._verbosity = 3 + self._show_timings = event.args.show_timings self._show_paths = event.args.show_paths self._show_steps = event.args.show_steps @@ -135,7 +149,12 @@ def on_arg_parsed(self, event: ArgParsedEvent) -> None: raise ValueError( "RichReporter: to enable `show_skip_reason` set `show_scenario_extras` to `True`") + if self._show_discovering_spinner: + self._printer.show_spinner("Discovering scenarios...") + def on_startup(self, event: StartupEvent) -> None: + if self._show_discovering_spinner: + self._printer.hide_spinner() self._printer.print_header() def on_scenario_run(self, event: ScenarioRunEvent) -> None: @@ -164,6 +183,7 @@ def on_scenario_skipped(self, event: ScenarioSkippedEvent) -> None: def _print_exception(self, exc_info: ExcInfo) -> None: if self._tb_pretty: self._printer.print_pretty_exception(exc_info, + width=self._tb_width, max_frames=self._tb_max_frames, show_locals=self._tb_show_locals, show_internal_calls=self._tb_show_internal_calls) @@ -344,18 +364,26 @@ class RichReporter(PluginConfig): # Available if `tb_pretty` is True tb_show_locals: bool = False + # Set the width of the traceback output + # If None, terminal width will be used + # Available if `tb_pretty` is True + tb_width: Union[int, None] = 100 + + # Max stack trace entries to show (min=4) + tb_max_frames: int = 8 + # Truncate lines in Scope based on scope_width value. # If scope_width is None, lines are truncated to the terminal's width. # If scope_width is -1, lines aren't truncated. # Otherwise, lines are truncated to the given length. scope_width: Union[int, None] = -1 - # Max stack trace entries to show (min=4) - tb_max_frames: int = 8 - # Show traceback if the execution is interrupted show_interrupted_traceback: bool = False + # Show a snapshot of crucial variables (Scope) when a test scenario fails + show_scope: bool = False + # Enable new verbose levels v2_verbosity: bool = True