From 0f8b1c05fcb8cab224780d3a3c7ddfa70bbd0dfa Mon Sep 17 00:00:00 2001 From: kolo Date: Thu, 15 Jan 2026 02:02:50 +0300 Subject: [PATCH] pretty gifff --- README.md | 2 +- README.ru.md | 2 +- metrics/__init__.py | 1 + metrics/__main__.py | 11 ++++++++- metrics/benchmarks/pre_cycle_setup.py | 8 +++++++ metrics/registry.py | 6 ++--- metrics/utils.py | 13 +++++----- metrics_tests/__init__.py | 0 metrics_tests/time_of_precycle_setup.py | 32 ------------------------- mock/min_app/main.py | 3 ++- src/argenta/app/models.py | 7 +++--- tests/unit_tests/test_app.py | 2 -- 12 files changed, 36 insertions(+), 51 deletions(-) delete mode 100644 metrics_tests/__init__.py delete mode 100644 metrics_tests/time_of_precycle_setup.py diff --git a/README.md b/README.md index e36e48f..6bcc4c1 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Argenta is the **"Simplest"**, **"Most Modular"**, and **"Most Elegant"** way to --- -![preview](https://i.ibb.co/fzWcfgFq/2025-12-04-173045.png) +![preview](https://vhs.charm.sh/vhs-2hvLCEgclmwZPJZt1vLGKi.gif) **Argenta** allows you to build interactive CLI applications incredibly easily. There's no need to manually parse complex command structures or manage state transitions — just use routers and commands! diff --git a/README.ru.md b/README.ru.md index fe00e96..5ee21fc 100644 --- a/README.ru.md +++ b/README.ru.md @@ -9,7 +9,7 @@ Argenta — это **"Самый простой"**, **"Самый модульн --- -![preview](https://i.ibb.co/fzWcfgFq/2025-12-04-173045.png) +![preview](https://vhs.charm.sh/vhs-2hvLCEgclmwZPJZt1vLGKi.gif) **Argenta** позволяет создавать интерактивные CLI-приложения невероятно легко. Не нужно вручную парсить сложные структуры команд или управлять переходами состояний — просто используйте роутеры и команды! diff --git a/metrics/__init__.py b/metrics/__init__.py index e69de29..bb87be0 100644 --- a/metrics/__init__.py +++ b/metrics/__init__.py @@ -0,0 +1 @@ +from .benchmarks.pre_cycle_setup import * \ No newline at end of file diff --git a/metrics/__main__.py b/metrics/__main__.py index 0082c3b..6e3bee0 100644 --- a/metrics/__main__.py +++ b/metrics/__main__.py @@ -1,10 +1,19 @@ +from metrics.utils import attempts_to_average from .registry import Benchmarks, Benchmark def main(): all_benchmarks: list[Benchmark] = Benchmarks.get_benchmarks() - for benchmark in all_benchmarks: pass + for benchmark in all_benchmarks: + bench_attempts: list[float] = [] + for _ in range(benchmark.iterations): + bench_attempts.append(benchmark.run()) + + print(f'Name: {benchmark.name}\n' + f'Description: {benchmark.description}\n' + f'Iterations: {benchmark.iterations}\n' + f'Average time per iteration: {attempts_to_average(bench_attempts, benchmark.iterations)} ms\n') if __name__ == '__main__': diff --git a/metrics/benchmarks/pre_cycle_setup.py b/metrics/benchmarks/pre_cycle_setup.py index 419a34f..8db6d17 100644 --- a/metrics/benchmarks/pre_cycle_setup.py +++ b/metrics/benchmarks/pre_cycle_setup.py @@ -1,3 +1,11 @@ +__all__ = [ + "benchmark_no_aliases", + "benchmark_many_aliases", + "benchmark_few_aliases", + "benchmark_extreme_aliases", + "benchmark_very_many_aliases" +] + from argenta import App from argenta.router import Router from argenta.command.models import Command diff --git a/metrics/registry.py b/metrics/registry.py index 306a305..db7ca06 100644 --- a/metrics/registry.py +++ b/metrics/registry.py @@ -23,7 +23,7 @@ class Benchmark: self.description = description self.iterations = iterations - def __call__(self) -> float: + def run(self) -> float: return self.func() @override @@ -84,9 +84,9 @@ class Benchmarks: return decorator else: return decorator(call) - + @classmethod def get_benchmarks(cls) -> list[Benchmark]: return cls._benchmarks - + benchmark = Benchmarks.register diff --git a/metrics/utils.py b/metrics/utils.py index ac6adf9..2c3f83e 100644 --- a/metrics/utils.py +++ b/metrics/utils.py @@ -1,22 +1,23 @@ __all__ = [ "get_time_of_pre_cycle_setup", + "attempts_to_average" ] import io from contextlib import redirect_stdout import time +from decimal import Decimal, ROUND_HALF_UP from argenta import App -def get_time_of_pre_cycle_setup(app: App) -> float: - """ - Public. Return time of pre cycle setup - :param app: app instance for testing time of pre cycle setup - :return: time of pre cycle setup as float - """ +def get_time_of_pre_cycle_setup(app: App) -> float: start = time.monotonic() with redirect_stdout(io.StringIO()): app._pre_cycle_setup() # pyright: ignore[reportPrivateUsage] end = time.monotonic() return end - start + + +def attempts_to_average(bench_attempts: list[float], iterations: int) -> Decimal: + return Decimal(sum(bench_attempts) / iterations).quantize(Decimal("0.00001"), rounding=ROUND_HALF_UP) diff --git a/metrics_tests/__init__.py b/metrics_tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/metrics_tests/time_of_precycle_setup.py b/metrics_tests/time_of_precycle_setup.py deleted file mode 100644 index 83e36f5..0000000 --- a/metrics_tests/time_of_precycle_setup.py +++ /dev/null @@ -1,32 +0,0 @@ -from argenta.app import App -from argenta.command import Command -from argenta.metrics import get_time_of_pre_cycle_setup -from argenta.response import Response -from argenta.router import Router - - -def commands_with_two_aliases(num_of_commands: int): - router = Router() - - for i in range(num_of_commands): - @router.command(Command(f'cmd{i}', aliases=[f'cdr{i}', f'prt{i}'])) - def handler(response: Response): # pyright: ignore[reportUnusedFunction, reportUnusedParameter] - pass - - app = App() - app.include_router(router) - - return get_time_of_pre_cycle_setup(app) - -def commands_with_one_aliases(num_of_commands: int): - router = Router() - - for i in range(num_of_commands): - @router.command(Command(f'cmd{i}', aliases=[f'cdr{i}'])) - def handler(response: Response): # pyright: ignore[reportUnusedFunction, reportUnusedParameter] - pass - - app = App() - app.include_router(router) - - return get_time_of_pre_cycle_setup(app) diff --git a/mock/min_app/main.py b/mock/min_app/main.py index 97eb5e9..a2b4326 100644 --- a/mock/min_app/main.py +++ b/mock/min_app/main.py @@ -1,9 +1,10 @@ # main.py from argenta import App, Orchestrator +from argenta.app import DynamicDividingLine from .routers import router -app: App = App() +app: App = App(prompt='>>> ', dividing_line=DynamicDividingLine('~')) orchestrator: Orchestrator = Orchestrator() def main() -> None: diff --git a/src/argenta/app/models.py b/src/argenta/app/models.py index d2363df..644c42c 100644 --- a/src/argenta/app/models.py +++ b/src/argenta/app/models.py @@ -339,9 +339,6 @@ class BaseApp: self._autocompleter.initial_setup(self.registered_routers.get_triggers()) - if not self._override_system_messages: - self._setup_default_view() - self._print_func(self._initial_message) for message in self._messages_on_startup: @@ -382,7 +379,7 @@ DEFAULT_DIVIDING_LINE: StaticDividingLine = StaticDividingLine() DEFAULT_PRINT_FUNC: Printer = Console().print DEFAULT_AUTOCOMPLETER: AutoCompleter = AutoCompleter() -DEFAULT_EXIT_COMMAND: Command = Command("Q", description="Exit command") +DEFAULT_EXIT_COMMAND: Command = Command("q", description="Exit command") class App(BaseApp): @@ -427,6 +424,8 @@ class App(BaseApp): autocompleter=autocompleter, print_func=print_func, ) + if not self._override_system_messages: + self._setup_default_view() def run_polling(self) -> None: """ diff --git a/tests/unit_tests/test_app.py b/tests/unit_tests/test_app.py index 4306b18..13b7924 100644 --- a/tests/unit_tests/test_app.py +++ b/tests/unit_tests/test_app.py @@ -361,8 +361,6 @@ def test_set_exit_command_handler_stores_handler() -> None: def test_setup_default_view_formats_prompt() -> None: app = App(prompt='>>') - app._setup_default_view() - assert app._prompt == '[italic dim bold]>>'