mirror of
https://github.com/koloideal/Argenta.git
synced 2026-06-10 10:05:28 +03:00
docs
This commit is contained in:
@@ -1,11 +1,9 @@
|
|||||||
from sqlite3 import Connection
|
from sqlite3 import Connection
|
||||||
|
|
||||||
from argenta import Response, Router
|
from argenta import Response, Router
|
||||||
from argenta.di import FromDishka
|
from argenta.di import FromDishka
|
||||||
|
|
||||||
router = Router()
|
router = Router()
|
||||||
|
|
||||||
|
|
||||||
@router.command("connect")
|
@router.command("connect")
|
||||||
def connect_handler(response: Response, connection: FromDishka[Connection]):
|
def connect_handler(response: Response, connection: FromDishka[Connection]):
|
||||||
connection.execute("...")
|
connection.execute("...")
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ from argenta.orchestrator.argparser import ArgSpace
|
|||||||
|
|
||||||
router = Router()
|
router = Router()
|
||||||
|
|
||||||
|
|
||||||
@router.command("info")
|
@router.command("info")
|
||||||
def connect_handler(response: Response, argspace: FromDishka[ArgSpace]):
|
def connect_handler(response: Response, argspace: FromDishka[ArgSpace]):
|
||||||
print(argspace.get_by_name("type"))
|
print(argspace.get_by_name("type"))
|
||||||
|
|||||||
@@ -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,
|
|
||||||
)
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
from argenta.router import Router
|
from argenta import Response, Router
|
||||||
|
|
||||||
# Для этого роутера перехват stdout будет отключен
|
# Для этого роутера перехват stdout будет отключен
|
||||||
interactive_router = Router(disable_redirect_stdout=True)
|
interactive_router = Router(disable_redirect_stdout=True)
|
||||||
|
|
||||||
|
|
||||||
@interactive_router.command("ask")
|
@interactive_router.command("ask")
|
||||||
def ask_name(response):
|
def ask_name(response: Response):
|
||||||
name = input("Как вас зовут? ")
|
name = input("Как вас зовут? ")
|
||||||
print(f"Приятно познакомиться, {name}!")
|
print(f"Приятно познакомиться, {name}!")
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from argenta.app import App
|
from argenta import App
|
||||||
from argenta.app.dividing_line import StaticDividingLine
|
from argenta.app import StaticDividingLine
|
||||||
|
|
||||||
# Все роутеры по умолчанию будут использовать статическую линию длиной 50 символов
|
# Все роутеры по умолчанию будут использовать статическую линию длиной 50 символов
|
||||||
# (если для них не отключен перехват stdout)
|
|
||||||
app = App(dividing_line=StaticDividingLine(length=50))
|
app = App(dividing_line=StaticDividingLine(length=50))
|
||||||
|
|||||||
@@ -3,10 +3,12 @@
|
|||||||
Внедрение зависимостей
|
Внедрение зависимостей
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
Внедрение зависимостей (Dependency Injection, DI) — это паттерн проектирования, который помогает писать слабосвязанный, легко тестируемый и расширяемый код. Вместо того чтобы обработчики сами создавали нужные им объекты (зависимости), они лишь объявляют их в качестве аргументов. В момент вызова ``Argenta`` автоматически "внедряет" эти зависимости.
|
Внедрение зависимостей (Dependency Injection, DI) — это паттерн проектирования, который помогает писать слабосвязанный, легко тестируемый и расширяемый код. Вместо того чтобы обработчики сами создавали нужные им объекты (зависимости), они получают их извне.
|
||||||
|
|
||||||
``Argenta`` использует библиотеку ``dishka`` для реализации DI, что позволяет декларативно объявлять зависимости прямо в сигнатурах ваших обработчиков.
|
``Argenta`` использует библиотеку ``dishka`` для реализации DI, что позволяет декларативно объявлять зависимости прямо в сигнатурах ваших обработчиков.
|
||||||
Подробнее о `DI`, `IoC` и API для создания провайдеров можно прочитать в `официальной документации dishka <https://dishka.readthedocs.io/en/stable/di_intro.html>`_.
|
Подробнее о **DI**, **IoC** и API для создания провайдеров можно прочитать в `официальной документации dishka <https://dishka.readthedocs.io/en/stable/di_intro.html>`_.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
Основная идея
|
Основная идея
|
||||||
-------------
|
-------------
|
||||||
@@ -14,7 +16,7 @@
|
|||||||
Представьте, что вашему обработчику для работы нужен доступ к базе данных. Вместо импорта и инициализации соединения внутри функции, вы просто объявляете его как аргумент с аннотацией типа:
|
Представьте, что вашему обработчику для работы нужен доступ к базе данных. Вместо импорта и инициализации соединения внутри функции, вы просто объявляете его как аргумент с аннотацией типа:
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
``argenta.di.FromDishka`` является псевдонимом для ``dishka.FromDishka``, и они полностью взаимозаменяемы.
|
``argenta.di.FromDishka`` является алиасом для ``dishka.FromDishka``, и они полностью взаимозаменяемы.
|
||||||
|
|
||||||
.. literalinclude:: ../code_snippets/dependency_injection/snippet.py
|
.. literalinclude:: ../code_snippets/dependency_injection/snippet.py
|
||||||
:language: python
|
:language: python
|
||||||
@@ -32,6 +34,8 @@
|
|||||||
:language: python
|
:language: python
|
||||||
:linenos:
|
:linenos:
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
Как это работает?
|
Как это работает?
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
@@ -40,6 +44,8 @@
|
|||||||
* **Провайдер (Provider)** — это "рецепт", который объясняет, как создавать и настраивать ту или иную зависимость (например, подключение к БД, API-клиент или любой другой сервис).
|
* **Провайдер (Provider)** — это "рецепт", который объясняет, как создавать и настраивать ту или иную зависимость (например, подключение к БД, API-клиент или любой другой сервис).
|
||||||
* **Контейнер (IoC Container)** — это "фабрика", которая хранит все рецепты (провайдеры) и по запросу создаёт и выдаёт готовые зависимости.
|
* **Контейнер (IoC Container)** — это "фабрика", которая хранит все рецепты (провайдеры) и по запросу создаёт и выдаёт готовые зависимости.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
Встроенные провайдеры
|
Встроенные провайдеры
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
@@ -51,13 +57,14 @@
|
|||||||
:language: python
|
:language: python
|
||||||
:linenos:
|
:linenos:
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
Обмен данными между хендлерами
|
Обмен данными между хендлерами
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
Помимо DI, обработчики могут обмениваться данными в рамках сессии через **объект контекста**. В ``Argenta`` эту роль выполняет объект ``Response``.
|
Помимо DI, обработчики могут обмениваться данными в рамках сессии через **объект контекста**. В ``Argenta`` эту роль выполняет объект ``DataBridge``.
|
||||||
|
|
||||||
Каждый обработчик может записывать в него данные, а также читать, обновлять и удалять их.
|
Каждый обработчик может записывать в него данные, а также читать, обновлять и удалять их.
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
Подробнее об этом можно прочитать в разделе :ref:`root_api_bridge`.
|
||||||
Подробнее об этом можно прочитать в разделе :ref:`root_api_response`.
|
|
||||||
|
|||||||
@@ -29,14 +29,10 @@
|
|||||||
Кастомизация вывода
|
Кастомизация вывода
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Для полной замены логики вывода в конструкторе ``App`` предусмотрен параметр ``print_func``.
|
Для полной замены логики вывода текста в конструкторе ``App`` предусмотрен параметр ``print_func``.
|
||||||
|
|
||||||
* **print_func**: ``Callable[[str], None]``
|
* **print_func**: ``Callable[[str], None]``
|
||||||
Этот параметр позволяет передать любую вызываемую сущность (например, функцию), которая будет использоваться для вывода всех системных сообщений. По умолчанию это обёртка над ``rich.console.Console().print``. Вы можете передать сюда свою функцию, чтобы, например, логировать вывод в файл или отправлять его по сети.
|
Этот параметр позволяет передать любую вызываемую сущность (например, функцию), которая будет использоваться для вывода всех системных сообщений. По умолчанию это ``rich.console.Console().print``. Вы можете передать сюда свою функцию, чтобы, например, логировать вывод в файл или отправлять его по сети.
|
||||||
|
|
||||||
Пример использования
|
.. important::
|
||||||
--------------------
|
При переопределении функции вывода вам следует убедиться, что она поддерживает разметку ``rich``, иначе системные сообщения будут выводиться в сыром виде, в этом случае рекомендуется переопределить стандартное форматирование с помощью ``override_system_messages=True``.
|
||||||
|
|
||||||
.. literalinclude:: ../code_snippets/overriding_formatting/sample.py
|
|
||||||
:language: python
|
|
||||||
:linenos:
|
|
||||||
|
|||||||
@@ -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
|
: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
|
:alt: Example of an application with a static dividing line
|
||||||
|
|
||||||
В этом примере разделительная линия имеет фиксированную длину (по умолчанию 25 символов).
|
В этом примере разделительная линия имеет фиксированную длину (по умолчанию 25 символов).
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
Побочные эффекты перехвата ``stdout``
|
Побочные эффекты перехвата ``stdout``
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Главный побочный эффект этого механизма проявляется при использовании функций, которые одновременно ожидают ввод от пользователя и выводят приглашение в консоль. Классический пример — стандартная функция ``input()``.
|
Побочный эффект этого механизма проявляется при использовании функций, которые последовательно выводят текст в консоль и ожидают ввод от пользователя. Классический пример — стандартная функция ``input()``.
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
:linenos:
|
:linenos:
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
print(f"Привет, {user_name}!")
|
print(f"Привет, {user_name}!")
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
При включённом перехвате ``stdout`` текст-приглашение (например, ``"Введите ваше имя: "``) **не будет выведен в консоль немедленно**. Он попадёт в буфер, и пользователь увидит только мигающий курсор. Текст приглашения отобразится лишь после завершения работы обработчика вместе с остальным выводом. Это может сбить пользователя с толку.
|
При включённом перехвате ``stdout`` текст (например, ``"Введите ваше имя: "``) **не будет выведен в консоль немедленно**. Он попадёт в буфер и отобразится лишь после завершения работы обработчика вместе с остальным выводом. Это может сбить пользователя с толку.
|
||||||
|
|
||||||
-----
|
-----
|
||||||
|
|
||||||
@@ -72,9 +72,11 @@
|
|||||||
* Требует включённого перехвата ``stdout`` (``disable_redirect_stdout=False`` в роутере).
|
* Требует включённого перехвата ``stdout`` (``disable_redirect_stdout=False`` в роутере).
|
||||||
|
|
||||||
2. **StaticDividingLine(length: int = 25)**
|
2. **StaticDividingLine(length: int = 25)**
|
||||||
* Линия имеет фиксированную длину (по умолчанию 25 символов), которую можно задать через аргумент `length`.
|
* Линия имеет фиксированную длину (по умолчанию 25 символов), которую можно задать через аргумент ``length``.
|
||||||
* Используется принудительно для роутеров с ``disable_redirect_stdout=True``, так как без перехвата вывода невозможно определить динамическую длину.
|
* Используется принудительно для роутеров с ``disable_redirect_stdout=True``, так как без перехвата вывода невозможно определить динамическую длину.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
Настройка разделительной линии в `App`
|
Настройка разделительной линии в `App`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
from argenta import App, Orchestrator
|
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
|
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(
|
app: App = App(
|
||||||
dividing_line=StaticDividingLine(),
|
dividing_line=DynamicDividingLine('^'),
|
||||||
override_system_messages=True,
|
|
||||||
print_func=print_hello
|
|
||||||
)
|
)
|
||||||
orchestrator: Orchestrator = Orchestrator()
|
orchestrator: Orchestrator = Orchestrator()
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
from argenta import Router, Response, Command
|
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!"))
|
@work_router.command(Command('hello', description="Hello, world!"))
|
||||||
def command_help(response: Response):
|
def command_help(response: Response):
|
||||||
print('Hello, world!')
|
c = input("Enter your name: ")
|
||||||
|
print(f"Hello, {c}!")
|
||||||
|
|||||||
@@ -483,19 +483,6 @@ class App(BaseApp):
|
|||||||
]
|
]
|
||||||
|
|
||||||
if processing_router.disable_redirect_stdout:
|
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
|
|
||||||
)
|
|
||||||
)
|
|
||||||
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()
|
dividing_line_unit_part: str = self._dividing_line.get_unit_part()
|
||||||
self._print_func(
|
self._print_func(
|
||||||
StaticDividingLine(
|
StaticDividingLine(
|
||||||
|
|||||||
Reference in New Issue
Block a user