From 8edd59c1b8b8e07e12e6bf17f2fa51bfceabbb57 Mon Sep 17 00:00:00 2001 From: kolo Date: Fri, 7 Nov 2025 21:25:35 +0300 Subject: [PATCH] docs --- .../dependency_injection/snippet.py | 2 - .../dependency_injection/snippet4.py | 1 - .../overriding_formatting/sample.py | 13 ------ docs/code_snippets/redirect_stdout/sample.py | 4 +- docs/code_snippets/redirect_stdout/sample2.py | 5 +-- docs/root/dependency_injection.rst | 19 ++++++--- docs/root/overriding_formatting.rst | 12 ++---- docs/root/redirect_stdout.rst | 12 +++--- mock/mock_app/main.py | 12 ++---- mock/mock_app/routers.py | 5 ++- src/argenta/app/models.py | 41 +++++++------------ 11 files changed, 48 insertions(+), 78 deletions(-) delete mode 100644 docs/code_snippets/overriding_formatting/sample.py diff --git a/docs/code_snippets/dependency_injection/snippet.py b/docs/code_snippets/dependency_injection/snippet.py index b2d310b..681a8df 100644 --- a/docs/code_snippets/dependency_injection/snippet.py +++ b/docs/code_snippets/dependency_injection/snippet.py @@ -1,11 +1,9 @@ from sqlite3 import Connection - from argenta import Response, Router from argenta.di import FromDishka router = Router() - @router.command("connect") def connect_handler(response: Response, connection: FromDishka[Connection]): connection.execute("...") diff --git a/docs/code_snippets/dependency_injection/snippet4.py b/docs/code_snippets/dependency_injection/snippet4.py index 5ce3a03..1050d9e 100644 --- a/docs/code_snippets/dependency_injection/snippet4.py +++ b/docs/code_snippets/dependency_injection/snippet4.py @@ -4,7 +4,6 @@ from argenta.orchestrator.argparser import ArgSpace router = Router() - @router.command("info") def connect_handler(response: Response, argspace: FromDishka[ArgSpace]): print(argspace.get_by_name("type")) diff --git a/docs/code_snippets/overriding_formatting/sample.py b/docs/code_snippets/overriding_formatting/sample.py deleted file mode 100644 index 160b622..0000000 --- a/docs/code_snippets/overriding_formatting/sample.py +++ /dev/null @@ -1,13 +0,0 @@ -from argenta import App - - -def custom_print_function(text: str) -> None: - """Простая пользовательская функция вывода с префиксом.""" - print(f"Префикс: {text}") - - -app = App( - initial_message="My App", - override_system_messages=True, - print_func=custom_print_function, -) diff --git a/docs/code_snippets/redirect_stdout/sample.py b/docs/code_snippets/redirect_stdout/sample.py index 51e5f9e..aa6c71e 100644 --- a/docs/code_snippets/redirect_stdout/sample.py +++ b/docs/code_snippets/redirect_stdout/sample.py @@ -1,10 +1,10 @@ -from argenta.router import Router +from argenta import Response, Router # Для этого роутера перехват stdout будет отключен interactive_router = Router(disable_redirect_stdout=True) @interactive_router.command("ask") -def ask_name(response): +def ask_name(response: Response): name = input("Как вас зовут? ") print(f"Приятно познакомиться, {name}!") diff --git a/docs/code_snippets/redirect_stdout/sample2.py b/docs/code_snippets/redirect_stdout/sample2.py index 320d641..1b599ab 100644 --- a/docs/code_snippets/redirect_stdout/sample2.py +++ b/docs/code_snippets/redirect_stdout/sample2.py @@ -1,6 +1,5 @@ -from argenta.app import App -from argenta.app.dividing_line import StaticDividingLine +from argenta import App +from argenta.app import StaticDividingLine # Все роутеры по умолчанию будут использовать статическую линию длиной 50 символов -# (если для них не отключен перехват stdout) app = App(dividing_line=StaticDividingLine(length=50)) diff --git a/docs/root/dependency_injection.rst b/docs/root/dependency_injection.rst index 70ab172..b252e0d 100644 --- a/docs/root/dependency_injection.rst +++ b/docs/root/dependency_injection.rst @@ -3,10 +3,12 @@ Внедрение зависимостей ======================= -Внедрение зависимостей (Dependency Injection, DI) — это паттерн проектирования, который помогает писать слабосвязанный, легко тестируемый и расширяемый код. Вместо того чтобы обработчики сами создавали нужные им объекты (зависимости), они лишь объявляют их в качестве аргументов. В момент вызова ``Argenta`` автоматически "внедряет" эти зависимости. +Внедрение зависимостей (Dependency Injection, DI) — это паттерн проектирования, который помогает писать слабосвязанный, легко тестируемый и расширяемый код. Вместо того чтобы обработчики сами создавали нужные им объекты (зависимости), они получают их извне. ``Argenta`` использует библиотеку ``dishka`` для реализации DI, что позволяет декларативно объявлять зависимости прямо в сигнатурах ваших обработчиков. -Подробнее о `DI`, `IoC` и API для создания провайдеров можно прочитать в `официальной документации dishka `_. +Подробнее о **DI**, **IoC** и API для создания провайдеров можно прочитать в `официальной документации dishka `_. + +----- Основная идея ------------- @@ -14,7 +16,7 @@ Представьте, что вашему обработчику для работы нужен доступ к базе данных. Вместо импорта и инициализации соединения внутри функции, вы просто объявляете его как аргумент с аннотацией типа: .. note:: - ``argenta.di.FromDishka`` является псевдонимом для ``dishka.FromDishka``, и они полностью взаимозаменяемы. + ``argenta.di.FromDishka`` является алиасом для ``dishka.FromDishka``, и они полностью взаимозаменяемы. .. literalinclude:: ../code_snippets/dependency_injection/snippet.py :language: python @@ -32,6 +34,8 @@ :language: python :linenos: +----- + Как это работает? ----------------- @@ -40,6 +44,8 @@ * **Провайдер (Provider)** — это "рецепт", который объясняет, как создавать и настраивать ту или иную зависимость (например, подключение к БД, API-клиент или любой другой сервис). * **Контейнер (IoC Container)** — это "фабрика", которая хранит все рецепты (провайдеры) и по запросу создаёт и выдаёт готовые зависимости. +----- + Встроенные провайдеры ----------------------- @@ -50,14 +56,15 @@ .. literalinclude:: ../code_snippets/dependency_injection/snippet4.py :language: python :linenos: + +----- Обмен данными между хендлерами ------------------------------ -Помимо DI, обработчики могут обмениваться данными в рамках сессии через **объект контекста**. В ``Argenta`` эту роль выполняет объект ``Response``. +Помимо DI, обработчики могут обмениваться данными в рамках сессии через **объект контекста**. В ``Argenta`` эту роль выполняет объект ``DataBridge``. Каждый обработчик может записывать в него данные, а также читать, обновлять и удалять их. .. seealso:: - - Подробнее об этом можно прочитать в разделе :ref:`root_api_response`. + Подробнее об этом можно прочитать в разделе :ref:`root_api_bridge`. diff --git a/docs/root/overriding_formatting.rst b/docs/root/overriding_formatting.rst index 13a9c14..0c1f254 100644 --- a/docs/root/overriding_formatting.rst +++ b/docs/root/overriding_formatting.rst @@ -29,14 +29,10 @@ Кастомизация вывода ------------------- -Для полной замены логики вывода в конструкторе ``App`` предусмотрен параметр ``print_func``. +Для полной замены логики вывода текста в конструкторе ``App`` предусмотрен параметр ``print_func``. * **print_func**: ``Callable[[str], None]`` - Этот параметр позволяет передать любую вызываемую сущность (например, функцию), которая будет использоваться для вывода всех системных сообщений. По умолчанию это обёртка над ``rich.console.Console().print``. Вы можете передать сюда свою функцию, чтобы, например, логировать вывод в файл или отправлять его по сети. + Этот параметр позволяет передать любую вызываемую сущность (например, функцию), которая будет использоваться для вывода всех системных сообщений. По умолчанию это ``rich.console.Console().print``. Вы можете передать сюда свою функцию, чтобы, например, логировать вывод в файл или отправлять его по сети. -Пример использования --------------------- - -.. literalinclude:: ../code_snippets/overriding_formatting/sample.py - :language: python - :linenos: +.. important:: + При переопределении функции вывода вам следует убедиться, что она поддерживает разметку ``rich``, иначе системные сообщения будут выводиться в сыром виде, в этом случае рекомендуется переопределить стандартное форматирование с помощью ``override_system_messages=True``. diff --git a/docs/root/redirect_stdout.rst b/docs/root/redirect_stdout.rst index 4d32e98..9e726c5 100644 --- a/docs/root/redirect_stdout.rst +++ b/docs/root/redirect_stdout.rst @@ -14,14 +14,14 @@ Пример приложения с динамической разделительной линией: -.. image:: https://i.ibb.co/ZptzLJ1n/2025-11-03-121308.png +.. image:: https://i.ibb.co/yn9rWnNC/2025-11-07-180751.png :alt: Example of an application with a dynamic dividing line Как вы можете заметить разделительная линия ровно той же длины, что и самая длинная строка в выводе. То же приложение с статической линией: -.. image:: https://i.ibb.co/YFGRY2c0/2025-11-03-121650.png +.. image:: https://i.ibb.co/P8B4xyp/2025-11-07-180330.png :alt: Example of an application with a static dividing line В этом примере разделительная линия имеет фиксированную длину (по умолчанию 25 символов). @@ -31,7 +31,7 @@ Побочные эффекты перехвата ``stdout`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Главный побочный эффект этого механизма проявляется при использовании функций, которые одновременно ожидают ввод от пользователя и выводят приглашение в консоль. Классический пример — стандартная функция ``input()``. +Побочный эффект этого механизма проявляется при использовании функций, которые последовательно выводят текст в консоль и ожидают ввод от пользователя. Классический пример — стандартная функция ``input()``. .. code-block:: python :linenos: @@ -41,7 +41,7 @@ print(f"Привет, {user_name}!") .. warning:: - При включённом перехвате ``stdout`` текст-приглашение (например, ``"Введите ваше имя: "``) **не будет выведен в консоль немедленно**. Он попадёт в буфер, и пользователь увидит только мигающий курсор. Текст приглашения отобразится лишь после завершения работы обработчика вместе с остальным выводом. Это может сбить пользователя с толку. + При включённом перехвате ``stdout`` текст (например, ``"Введите ваше имя: "``) **не будет выведен в консоль немедленно**. Он попадёт в буфер и отобразится лишь после завершения работы обработчика вместе с остальным выводом. Это может сбить пользователя с толку. ----- @@ -72,9 +72,11 @@ * Требует включённого перехвата ``stdout`` (``disable_redirect_stdout=False`` в роутере). 2. **StaticDividingLine(length: int = 25)** - * Линия имеет фиксированную длину (по умолчанию 25 символов), которую можно задать через аргумент `length`. + * Линия имеет фиксированную длину (по умолчанию 25 символов), которую можно задать через аргумент ``length``. * Используется принудительно для роутеров с ``disable_redirect_stdout=True``, так как без перехвата вывода невозможно определить динамическую длину. +----- + Настройка разделительной линии в `App` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/mock/mock_app/main.py b/mock/mock_app/main.py index 3efab8a..0ea40b8 100644 --- a/mock/mock_app/main.py +++ b/mock/mock_app/main.py @@ -1,16 +1,10 @@ from argenta import App, Orchestrator -from argenta.app import PredefinedMessages, StaticDividingLine +from argenta.app import PredefinedMessages +from argenta.app.dividing_line.models import StaticDividingLine, DynamicDividingLine from mock.mock_app.routers import work_router -def print_hello(entity: str): - with open('hello.txt', 'a') as file: - file.write(f'printer called: {entity}\n') - print(entity) - app: App = App( - dividing_line=StaticDividingLine(), - override_system_messages=True, - print_func=print_hello + dividing_line=DynamicDividingLine('^'), ) orchestrator: Orchestrator = Orchestrator() diff --git a/mock/mock_app/routers.py b/mock/mock_app/routers.py index db29a7c..2edc8d6 100644 --- a/mock/mock_app/routers.py +++ b/mock/mock_app/routers.py @@ -1,8 +1,9 @@ from argenta import Router, Response, Command -work_router: Router = Router(title="Base points:") +work_router: Router = Router(title="Base points:", disable_redirect_stdout=True) @work_router.command(Command('hello', description="Hello, world!")) def command_help(response: Response): - print('Hello, world!') + c = input("Enter your name: ") + print(f"Hello, {c}!") diff --git a/src/argenta/app/models.py b/src/argenta/app/models.py index 37a8725..d1faa31 100644 --- a/src/argenta/app/models.py +++ b/src/argenta/app/models.py @@ -483,35 +483,22 @@ class App(BaseApp): ] if processing_router.disable_redirect_stdout: - if isinstance(self._dividing_line, StaticDividingLine): - self._print_func( - self._dividing_line.get_full_static_line( - is_override=self._override_system_messages - ) + dividing_line_unit_part: str = self._dividing_line.get_unit_part() + self._print_func( + StaticDividingLine( + dividing_line_unit_part + ).get_full_static_line( + is_override=self._override_system_messages ) - processing_router.finds_appropriate_handler(input_command) - self._print_func( - self._dividing_line.get_full_static_line( - is_override=self._override_system_messages - ) - ) - else: - dividing_line_unit_part: str = self._dividing_line.get_unit_part() - self._print_func( - StaticDividingLine( - dividing_line_unit_part - ).get_full_static_line( - is_override=self._override_system_messages - ) - ) - processing_router.finds_appropriate_handler(input_command) - self._print_func( - StaticDividingLine( - dividing_line_unit_part - ).get_full_static_line( - is_override=self._override_system_messages - ) + ) + processing_router.finds_appropriate_handler(input_command) + self._print_func( + StaticDividingLine( + dividing_line_unit_part + ).get_full_static_line( + is_override=self._override_system_messages ) + ) else: with redirect_stdout(io.StringIO()) as stdout: processing_router.finds_appropriate_handler(input_command)