"""ASV benchmarks for CLI output rendering overhead (issue #210). Measures render_detail, render_list, render_error, and render_success across all six output formats. """ from __future__ import annotations import importlib import io import sys from pathlib import Path _SRC = str(Path(__file__).resolve().parents[1] / "src") if _SRC not in sys.path: sys.path.insert(0, _SRC) import cleveragents # noqa: E402 importlib.reload(cleveragents) from rich.console import Console # noqa: E402 import cleveragents.cli.renderers as _renderers_mod # noqa: E402 from cleveragents.cli.renderers import ( # noqa: E402 ColumnSpec, render_detail, render_error, render_list, render_success, ) # --------------------------------------------------------------------------- # Shared sample data # --------------------------------------------------------------------------- _DETAIL_DATA = { "name": "bench-item", "count": 42, "active": True, "description": "A benchmark test item for measuring renderer overhead", } _LIST_COLUMNS = [ ColumnSpec(key="name", label="Name"), ColumnSpec(key="value", label="Value"), ColumnSpec(key="status", label="Status"), ] _LIST_ROWS_10 = [ { "name": f"item-{i}", "value": i * 10, "status": "active" if i % 2 == 0 else "inactive", } for i in range(10) ] # --------------------------------------------------------------------------- # Console buffer helpers # --------------------------------------------------------------------------- def _install_buffer_consoles() -> None: """Replace module-level consoles with buffer-backed instances.""" _renderers_mod._console = Console( file=io.StringIO(), no_color=True, highlight=False ) _renderers_mod._err_console = Console( file=io.StringIO(), no_color=True, highlight=False ) def _reset_buffers() -> None: """Seek to start and truncate the console buffers between iterations.""" for attr in ("_console", "_err_console"): console = getattr(_renderers_mod, attr) if console is not None and hasattr(console, "file"): console.file.seek(0) console.file.truncate() # --------------------------------------------------------------------------- # RenderDetailSuite # --------------------------------------------------------------------------- class RenderDetailSuite: """Benchmark render_detail across formats.""" def setup(self) -> None: _install_buffer_consoles() def teardown(self) -> None: _renderers_mod._console = None _renderers_mod._err_console = None def time_render_detail_json(self) -> None: _reset_buffers() render_detail(_DETAIL_DATA, fmt="json") def time_render_detail_yaml(self) -> None: _reset_buffers() render_detail(_DETAIL_DATA, fmt="yaml") def time_render_detail_plain(self) -> None: _reset_buffers() render_detail(_DETAIL_DATA, fmt="plain") def time_render_detail_rich(self) -> None: _reset_buffers() render_detail(_DETAIL_DATA, fmt="rich") # --------------------------------------------------------------------------- # RenderListSuite # --------------------------------------------------------------------------- class RenderListSuite: """Benchmark render_list across formats.""" def setup(self) -> None: _install_buffer_consoles() def teardown(self) -> None: _renderers_mod._console = None _renderers_mod._err_console = None def time_render_list_json_10_rows(self) -> None: _reset_buffers() render_list(_LIST_ROWS_10, columns=_LIST_COLUMNS, fmt="json") def time_render_list_plain_10_rows(self) -> None: _reset_buffers() render_list(_LIST_ROWS_10, columns=_LIST_COLUMNS, fmt="plain") def time_render_list_rich_10_rows(self) -> None: _reset_buffers() render_list(_LIST_ROWS_10, columns=_LIST_COLUMNS, fmt="rich") # --------------------------------------------------------------------------- # RenderErrorSuite # --------------------------------------------------------------------------- class RenderErrorSuite: """Benchmark render_error across formats.""" def setup(self) -> None: _install_buffer_consoles() def teardown(self) -> None: _renderers_mod._console = None _renderers_mod._err_console = None def time_render_error_rich(self) -> None: _reset_buffers() render_error("BenchError", "something went wrong", fmt="rich") def time_render_error_json(self) -> None: _reset_buffers() render_error("BenchError", "something went wrong", fmt="json") # --------------------------------------------------------------------------- # RenderSuccessSuite # --------------------------------------------------------------------------- class RenderSuccessSuite: """Benchmark render_success across formats.""" def setup(self) -> None: _install_buffer_consoles() def teardown(self) -> None: _renderers_mod._console = None _renderers_mod._err_console = None def time_render_success_rich(self) -> None: _reset_buffers() render_success("Benchmark complete", fmt="rich") def time_render_success_plain(self) -> None: _reset_buffers() render_success("Benchmark complete", fmt="plain")