mirror of
https://github.com/koloideal/Argenta.git
synced 2026-08-08 17:01:13 +03:00
docs: add CLI documentation section with translations and code snippets; refactor mock/ to examples/, improve CLI module (bug fixes, DX, error handling)
This commit is contained in:
@@ -0,0 +1,22 @@
|
|||||||
|
from argenta import App, Orchestrator
|
||||||
|
from argenta.command import Router, Command, Response
|
||||||
|
|
||||||
|
router = Router(title="Example")
|
||||||
|
|
||||||
|
@router.command(Command("hello", description="Say hello"))
|
||||||
|
def hello_handler(response: Response):
|
||||||
|
print("Hello, world!")
|
||||||
|
|
||||||
|
|
||||||
|
def create_app() -> App:
|
||||||
|
app = App()
|
||||||
|
app.include_router(router)
|
||||||
|
return app
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
orchestrator = Orchestrator()
|
||||||
|
orchestrator.run_repl(create_app())
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
from argenta import App, Orchestrator
|
||||||
|
from argenta.command import Router, Command, Response
|
||||||
|
|
||||||
|
router = Router(title="Example")
|
||||||
|
|
||||||
|
@router.command(Command("hello", description="Say hello"))
|
||||||
|
def hello_handler(response: Response):
|
||||||
|
print("Hello, world!")
|
||||||
|
|
||||||
|
app = App()
|
||||||
|
app.include_router(router)
|
||||||
|
|
||||||
|
orchestrator = Orchestrator()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
orchestrator.run_repl(app)
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
my_project/
|
||||||
|
├── main.py
|
||||||
|
├── handlers.py
|
||||||
|
└── .gitignore
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
my_project/
|
||||||
|
├── src/
|
||||||
|
│ └── my_project/
|
||||||
|
│ └── application/
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ ├── __main__.py
|
||||||
|
│ ├── routers.py
|
||||||
|
│ └── handlers/
|
||||||
|
│ ├── __init__.py
|
||||||
|
│ └── hello_world_handler.py
|
||||||
|
└── .gitignore
|
||||||
@@ -56,6 +56,7 @@ Argenta предназначена для создания приложений,
|
|||||||
|
|
||||||
root/redirect_stdout
|
root/redirect_stdout
|
||||||
root/dependency_injection
|
root/dependency_injection
|
||||||
|
root/cli
|
||||||
root/testing
|
root/testing
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
|
|||||||
@@ -0,0 +1,265 @@
|
|||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) 2025, kolo
|
||||||
|
# This file is distributed under the same license as the Argenta package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2025.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Argenta \n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2025-07-25 18:00+0300\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language: en\n"
|
||||||
|
"Language-Team: en <LL@li.org>\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Generated-By: Babel 2.17.0\n"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:3
|
||||||
|
msgid "Командная строка"
|
||||||
|
msgstr "Command Line Interface"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:5
|
||||||
|
msgid ""
|
||||||
|
"Помимо библиотеки, ``Argenta`` поставляется с собственным CLI-инструментом, "
|
||||||
|
"который помогает создавать проекты, запускать приложения, инспектировать "
|
||||||
|
"маршруты и собирать бинарники."
|
||||||
|
msgstr ""
|
||||||
|
"In addition to the library, ``Argenta`` ships with its own CLI tool that "
|
||||||
|
"helps scaffold projects, run applications, inspect routes, and build binaries."
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:8
|
||||||
|
msgid "Установка"
|
||||||
|
msgstr "Installation"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:10
|
||||||
|
msgid "CLI доступен как опциональная зависимость:"
|
||||||
|
msgstr "The CLI is available as an optional dependency:"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:16
|
||||||
|
msgid ""
|
||||||
|
"После установки команда ``argenta`` доступна в терминале:"
|
||||||
|
msgstr ""
|
||||||
|
"After installation, the ``argenta`` command is available in the terminal:"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:22
|
||||||
|
msgid ""
|
||||||
|
"Если вы устанавливали ``argenta`` без extras, CLI-инструмент не будет "
|
||||||
|
"доступен. Установите с ``[cli]`` для доступа к команде ``argenta``."
|
||||||
|
msgstr ""
|
||||||
|
"If you installed ``argenta`` without extras, the CLI tool will not be "
|
||||||
|
"available. Install with ``[cli]`` to access the ``argenta`` command."
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:25
|
||||||
|
msgid "Флаг ``--version``"
|
||||||
|
msgstr "The ``--version`` flag"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:27
|
||||||
|
msgid "Показать установленную версию ``Argenta``:"
|
||||||
|
msgstr "Show the installed ``Argenta`` version:"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:35
|
||||||
|
msgid "Создание проектов"
|
||||||
|
msgstr "Scaffolding Projects"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:38
|
||||||
|
msgid "Команда ``new``"
|
||||||
|
msgstr "The ``new`` command"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:40
|
||||||
|
msgid "Создаёт новую директорию проекта с boilerplate-кодом."
|
||||||
|
msgstr "Creates a new project directory with boilerplate code."
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:44
|
||||||
|
msgid "``project_name`` — имя директории проекта (обязательный аргумент)."
|
||||||
|
msgstr "``project_name`` — project directory name (required argument)."
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:45
|
||||||
|
msgid "``--with-arch`` — архитектура проекта: ``flat`` (по умолчанию) или ``src``."
|
||||||
|
msgstr "``--with-arch`` — project architecture: ``flat`` (default) or ``src``."
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:53
|
||||||
|
msgid "При архитектуре ``flat`` создаётся следующая структура:"
|
||||||
|
msgstr "With the ``flat`` architecture, the following structure is created:"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:59
|
||||||
|
msgid "При архитектуре ``src``:"
|
||||||
|
msgstr "With the ``src`` architecture:"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:67
|
||||||
|
msgid "Команда ``init``"
|
||||||
|
msgstr "The ``init`` command"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:69
|
||||||
|
msgid ""
|
||||||
|
"Инициализирует boilerplate в текущей директории. Удобно, когда проект уже "
|
||||||
|
"существует и нужно добавить структуру Argenta."
|
||||||
|
msgstr ""
|
||||||
|
"Initializes boilerplate in the current directory. Useful when the project "
|
||||||
|
"already exists and you need to add Argenta structure."
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:75
|
||||||
|
msgid ""
|
||||||
|
"Команда ``init`` не перезаписывает существующие файлы — они будут пропущены."
|
||||||
|
msgstr ""
|
||||||
|
"The ``init`` command does not overwrite existing files — they will be skipped."
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:80
|
||||||
|
msgid "Запуск приложений"
|
||||||
|
msgstr "Running Applications"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:83
|
||||||
|
msgid "Команда ``run``"
|
||||||
|
msgstr "The ``run`` command"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:85
|
||||||
|
msgid ""
|
||||||
|
"Запускает оркестратор ``Argenta`` из callable-ентрипойнта. Это альтернатива "
|
||||||
|
"прямому вызову ``python main.py``, но с автоматической настройкой окружения."
|
||||||
|
msgstr ""
|
||||||
|
"Starts the ``Argenta`` orchestrator from a callable entrypoint. This is an "
|
||||||
|
"alternative to directly calling ``python main.py``, but with automatic "
|
||||||
|
"environment setup."
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:89
|
||||||
|
msgid ""
|
||||||
|
"``entrypoint`` — путь к callable в формате "
|
||||||
|
"``<path/to/file.py>:<callable>`` или ``<path.to.module>:<callable>``."
|
||||||
|
msgstr ""
|
||||||
|
"``entrypoint`` — path to a callable in the format "
|
||||||
|
"``<path/to/file.py>:<callable>`` or ``<path.to.module>:<callable>``."
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:99
|
||||||
|
msgid ""
|
||||||
|
"Команда ``run`` устанавливает переменную окружения "
|
||||||
|
"``RUN_FROM_ARGENTA_RUNNER=1``, что отключает парсинг аргументов командной "
|
||||||
|
"строки в ``ArgParser``. Это позволяет запустить REPL без конфликтов с "
|
||||||
|
"CLI-аргументами ``argenta``."
|
||||||
|
msgstr ""
|
||||||
|
"The ``run`` command sets the ``RUN_FROM_ARGENTA_RUNNER=1`` environment "
|
||||||
|
"variable, which disables command-line argument parsing in ``ArgParser``. "
|
||||||
|
"This allows starting the REPL without conflicts with ``argenta`` CLI arguments."
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:104
|
||||||
|
msgid "Инспекция маршрутов"
|
||||||
|
msgstr "Inspecting Routes"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:107
|
||||||
|
msgid "Команда ``routes``"
|
||||||
|
msgstr "The ``routes`` command"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:109
|
||||||
|
msgid ""
|
||||||
|
"Отображает все зарегистрированные роутеры, команды, алиасы и флаги в виде "
|
||||||
|
"дерева. Принимает как инстанс ``App``, так и callable, возвращающий ``App``."
|
||||||
|
msgstr ""
|
||||||
|
"Displays all registered routers, commands, aliases, and flags as a tree. "
|
||||||
|
"Accepts either an ``App`` instance or a callable returning ``App``."
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:113
|
||||||
|
msgid ""
|
||||||
|
"``entrypoint`` — путь к ``App`` или callable в формате "
|
||||||
|
"``<path/to/file.py>:<app_or_callable>``."
|
||||||
|
msgstr ""
|
||||||
|
"``entrypoint`` — path to an ``App`` or callable in the format "
|
||||||
|
"``<path/to/file.py>:<app_or_callable>``."
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:125
|
||||||
|
msgid "Если передан инстанс ``App``:"
|
||||||
|
msgstr "If an ``App`` instance is passed:"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:131
|
||||||
|
msgid ""
|
||||||
|
"Если передан callable (фабрика), он будет вызван, и результат будет "
|
||||||
|
"использован для отображения маршрутов:"
|
||||||
|
msgstr ""
|
||||||
|
"If a callable (factory) is passed, it will be called, and the result will "
|
||||||
|
"be used to display routes:"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:139
|
||||||
|
msgid ""
|
||||||
|
"При использовании callable-ентрипойнта (например, ``create_app``) REPL не "
|
||||||
|
"запускается — фабрика вызывается, и маршруты считываются из возвращённого "
|
||||||
|
"``App``. Это полезно, когда роутеры подключаются внутри функции, а не на "
|
||||||
|
"уровне модуля."
|
||||||
|
msgstr ""
|
||||||
|
"When using a callable entrypoint (e.g., ``create_app``), the REPL is not "
|
||||||
|
"started — the factory is called, and routes are read from the returned "
|
||||||
|
"``App``. This is useful when routers are registered inside a function "
|
||||||
|
"rather than at the module level."
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:144
|
||||||
|
msgid "Сборка бинарников"
|
||||||
|
msgstr "Building Binaries"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:147
|
||||||
|
msgid "Команда ``build``"
|
||||||
|
msgstr "The ``build`` command"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:149
|
||||||
|
msgid "Компилирует проект в standalone-бинарник с помощью `Nuitka <https://nuitka.net/>`_."
|
||||||
|
msgstr "Compiles a project into a standalone binary using `Nuitka <https://nuitka.net/>`_."
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:153
|
||||||
|
msgid ""
|
||||||
|
"``entrypoint`` — путь к callable в формате "
|
||||||
|
"``<path/to/file.py>:<callable>``."
|
||||||
|
msgstr ""
|
||||||
|
"``entrypoint`` — path to a callable in the format "
|
||||||
|
"``<path/to/file.py>:<callable>``."
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:154
|
||||||
|
msgid ""
|
||||||
|
"``--output`` / ``-o`` — имя выходного бинарника (по умолчанию — имя файла "
|
||||||
|
"или пакета)."
|
||||||
|
msgstr ""
|
||||||
|
"``--output`` / ``-o`` — output binary name (defaults to the file or package name)."
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:166
|
||||||
|
msgid ""
|
||||||
|
"Для использования команды ``build`` необходимо установить ``Nuitka``:"
|
||||||
|
msgstr ""
|
||||||
|
"To use the ``build`` command, you must install ``Nuitka``:"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:174
|
||||||
|
msgid "Информация об окружении"
|
||||||
|
msgstr "Environment Information"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:177
|
||||||
|
msgid "Команда ``info``"
|
||||||
|
msgstr "The ``info`` command"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:179
|
||||||
|
msgid ""
|
||||||
|
"Отображает версию ``Argenta``, версию Python, платформу и ссылку на "
|
||||||
|
"документацию."
|
||||||
|
msgstr ""
|
||||||
|
"Displays the ``Argenta`` version, Python version, platform, and a link to "
|
||||||
|
"the documentation."
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:187
|
||||||
|
msgid "Формат ентрипойнтов"
|
||||||
|
msgstr "Entrypoint Format"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:190
|
||||||
|
msgid ""
|
||||||
|
"Все команды, принимающие ентрипойнт (``run``, ``routes``, ``build``), "
|
||||||
|
"используют единый формат:"
|
||||||
|
msgstr ""
|
||||||
|
"All commands that accept an entrypoint (``run``, ``routes``, ``build``) "
|
||||||
|
"use a unified format:"
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:196
|
||||||
|
msgid ""
|
||||||
|
"Поддерживаются как пути к файлам, так и dotted-модули. Если передан путь к "
|
||||||
|
"директории с ``__main__.py``, он будет разрешён автоматически."
|
||||||
|
msgstr ""
|
||||||
|
"Both file paths and dotted modules are supported. If a directory path "
|
||||||
|
"containing ``__main__.py`` is passed, it will be resolved automatically."
|
||||||
|
|
||||||
|
#: ../../root/cli.rst:199
|
||||||
|
msgid "Примеры валидных ентрипойнтов:"
|
||||||
|
msgstr "Examples of valid entrypoints:"
|
||||||
@@ -0,0 +1,244 @@
|
|||||||
|
.. _root_cli:
|
||||||
|
|
||||||
|
Командная строка
|
||||||
|
==================
|
||||||
|
|
||||||
|
Помимо библиотеки, ``Argenta`` поставляется с собственным CLI-инструментом, который помогает создавать проекты, запускать приложения, инспектировать маршруты и собирать бинарники.
|
||||||
|
|
||||||
|
Установка
|
||||||
|
---------
|
||||||
|
|
||||||
|
CLI доступен как опциональная зависимость:
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
pip install argenta[cli]
|
||||||
|
|
||||||
|
После установки команда ``argenta`` доступна в терминале:
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
argenta --help
|
||||||
|
|
||||||
|
.. image:: _static/cli/help.png
|
||||||
|
:alt: Argenta CLI help
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Если вы устанавливали ``argenta`` без extras, CLI-инструмент не будет доступен. Установите с ``[cli]`` для доступа к команде ``argenta``.
|
||||||
|
|
||||||
|
Флаг ``--version``
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Показать установленную версию ``Argenta``:
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
argenta --version
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
argenta -v
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
Создание проектов
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Команда ``new``
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Создаёт новую директорию проекта с boilerplate-кодом.
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
argenta new <project_name> [--with-arch flat|src]
|
||||||
|
|
||||||
|
* ``project_name`` — имя директории проекта (обязательный аргумент).
|
||||||
|
* ``--with-arch`` — архитектура проекта: ``flat`` (по умолчанию) или ``src``.
|
||||||
|
|
||||||
|
**Примеры:**
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
argenta new my-app
|
||||||
|
argenta new my-app --with-arch src
|
||||||
|
|
||||||
|
При архитектуре ``flat`` создаётся следующая структура:
|
||||||
|
|
||||||
|
.. literalinclude:: ../code_snippets/cli/flat_structure.txt
|
||||||
|
:language: text
|
||||||
|
|
||||||
|
При архитектуре ``src``:
|
||||||
|
|
||||||
|
.. literalinclude:: ../code_snippets/cli/src_structure.txt
|
||||||
|
:language: text
|
||||||
|
|
||||||
|
.. image:: _static/cli/new_command.png
|
||||||
|
:alt: argenta new command output
|
||||||
|
|
||||||
|
Команда ``init``
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Инициализирует boilerplate в текущей директории. Удобно, когда проект уже существует и нужно добавить структуру Argenta.
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
argenta init [--with-arch flat|src]
|
||||||
|
|
||||||
|
* ``--with-arch`` — архитектура проекта: ``flat`` (по умолчанию) или ``src``.
|
||||||
|
|
||||||
|
**Примеры:**
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
argenta init
|
||||||
|
argenta init --with-arch src
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Команда ``init`` не перезаписывает существующие файлы — они будут пропущены.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
Запуск приложений
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Команда ``run``
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Запускает оркестратор ``Argenta`` из callable-ентрипойнта. Это альтернатива прямому вызову ``python main.py``, но с автоматической настройкой окружения.
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
argenta run <entrypoint>
|
||||||
|
|
||||||
|
* ``entrypoint`` — путь к callable в формате ``<path/to/file.py>:<callable>`` или ``<path.to.module>:<callable>``.
|
||||||
|
|
||||||
|
**Примеры:**
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
argenta run app/main.py:main
|
||||||
|
argenta run my_project.application:main
|
||||||
|
|
||||||
|
.. image:: _static/cli/run_command.png
|
||||||
|
:alt: argenta run command output
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Команда ``run`` устанавливает переменную окружения ``RUN_FROM_ARGENTA_RUNNER=1``, что отключает парсинг аргументов командной строки в ``ArgParser``. Это позволяет запустить REPL без конфликтов с CLI-аргументами ``argenta``.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
Инспекция маршрутов
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Команда ``routes``
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Отображает все зарегистрированные роутеры, команды, алиасы и флаги в виде дерева. Принимает как инстанс ``App``, так и callable, возвращающий ``App``.
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
argenta routes <entrypoint>
|
||||||
|
|
||||||
|
* ``entrypoint`` — путь к ``App`` или callable в формате ``<path/to/file.py>:<app_or_callable>``.
|
||||||
|
|
||||||
|
**Примеры:**
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
argenta routes app/main.py:app
|
||||||
|
argenta routes app/main.py:create_app
|
||||||
|
|
||||||
|
Если передан инстанс ``App``:
|
||||||
|
|
||||||
|
.. literalinclude:: ../code_snippets/cli/app_instance.py
|
||||||
|
:language: python
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
Если передан callable (фабрика), он будет вызван, и результат будет использован для отображения маршрутов:
|
||||||
|
|
||||||
|
.. literalinclude:: ../code_snippets/cli/app_factory.py
|
||||||
|
:language: python
|
||||||
|
:linenos:
|
||||||
|
|
||||||
|
.. image:: _static/cli/routes_command.png
|
||||||
|
:alt: argenta routes command output
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
При использовании callable-ентрипойнта (например, ``create_app``) REPL не запускается — фабрика вызывается, и маршруты считываются из возвращённого ``App``. Это полезно, когда роутеры подключаются внутри функции, а не на уровне модуля.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
Сборка бинарников
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
Команда ``build``
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Компилирует проект в standalone-бинарник с помощью `Nuitka <https://nuitka.net/>`_.
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
argenta build <entrypoint> [--output <name>]
|
||||||
|
|
||||||
|
* ``entrypoint`` — путь к callable в формате ``<path/to/file.py>:<callable>``.
|
||||||
|
* ``--output`` / ``-o`` — имя выходного бинарника (по умолчанию — имя файла или пакета).
|
||||||
|
|
||||||
|
**Примеры:**
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
argenta build app/main.py:main
|
||||||
|
argenta build app/main.py:main --output myapp
|
||||||
|
argenta build app/__main__.py:main -o myapp
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
Для использования команды ``build`` необходимо установить ``Nuitka``:
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
pip install nuitka
|
||||||
|
|
||||||
|
.. image:: _static/cli/build_command.png
|
||||||
|
:alt: argenta build command output
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
Информация об окружении
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
Команда ``info``
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Отображает версию ``Argenta``, версию Python, платформу и ссылку на документацию.
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
argenta info
|
||||||
|
|
||||||
|
.. image:: _static/cli/info_command.png
|
||||||
|
:alt: argenta info command output
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
Формат ентрипойнтов
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Все команды, принимающие ентрипойнт (``run``, ``routes``, ``build``), используют единый формат:
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
<path/to/file.py>:<object_name>
|
||||||
|
<path.to.module>:<object_name>
|
||||||
|
|
||||||
|
Поддерживаются как пути к файлам, так и dotted-модули. Если передан путь к директории с ``__main__.py``, он будет разрешён автоматически.
|
||||||
|
|
||||||
|
**Примеры валидных ентрипойнтов:**
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
app/main.py:main
|
||||||
|
app/main.py:app
|
||||||
|
app/main.py:create_app
|
||||||
|
my_project.application:main
|
||||||
|
my_project/application/__main__.py:main
|
||||||
@@ -4,12 +4,12 @@ from argenta import App, Orchestrator
|
|||||||
from argenta.app import PredefinedMessages, StaticDividingLine, AutoCompleter
|
from argenta.app import PredefinedMessages, StaticDividingLine, AutoCompleter
|
||||||
from argenta.app.dividing_line.models import DynamicDividingLine
|
from argenta.app.dividing_line.models import DynamicDividingLine
|
||||||
from argenta.orchestrator import ArgParser
|
from argenta.orchestrator import ArgParser
|
||||||
from mock.mock_app.routers import work_router
|
from examples.example_app.routers import work_router
|
||||||
|
|
||||||
app: App = App(
|
app: App = App(
|
||||||
dividing_line=StaticDividingLine('~')
|
dividing_line=StaticDividingLine('~')
|
||||||
)
|
)
|
||||||
orchestrator: Orchestrator = Orchestrator(arg_parser=ArgParser(processed_args=[]))
|
orchestrator: Orchestrator = Orchestrator()
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
from importlib.metadata import version
|
||||||
|
|
||||||
|
import typer
|
||||||
from typer import Typer
|
from typer import Typer
|
||||||
|
|
||||||
from .commands import (
|
from .commands import (
|
||||||
@@ -9,50 +12,99 @@ from .commands import (
|
|||||||
run_handler,
|
run_handler,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
app = Typer(
|
||||||
|
name="argenta",
|
||||||
|
help="Argenta CLI — scaffold, run, inspect, and build CLI apps.",
|
||||||
|
no_args_is_help=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _version_callback(value: bool) -> None:
|
||||||
|
if value:
|
||||||
|
typer.echo(f"argenta {version('argenta')}")
|
||||||
|
raise typer.Exit()
|
||||||
|
|
||||||
|
|
||||||
|
@app.callback()
|
||||||
|
def _root(
|
||||||
|
version_flag: bool = typer.Option(
|
||||||
|
None,
|
||||||
|
"--version",
|
||||||
|
"-v",
|
||||||
|
callback=_version_callback,
|
||||||
|
is_eager=True,
|
||||||
|
help="Show Argenta version and exit.",
|
||||||
|
),
|
||||||
|
) -> None:
|
||||||
|
"""Argenta CLI — scaffold, run, inspect, and build CLI apps."""
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(
|
||||||
|
"run",
|
||||||
|
help="Start the orchestrator REPL from a callable entrypoint.",
|
||||||
|
short_help="Start the orchestrator REPL",
|
||||||
|
epilog="Example: argenta run app/main.py:main",
|
||||||
|
)
|
||||||
|
def _run(entrypoint_path: str = typer.Argument(help="Entrypoint as <path/to/file.py>:<callable>")) -> None:
|
||||||
|
run_handler(entrypoint_path)
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(
|
||||||
|
"init",
|
||||||
|
help="Scaffold a flat or src boilerplate in the current project directory.",
|
||||||
|
short_help="Initialize architecture in existing project",
|
||||||
|
epilog="Run from the project root. Example: argenta init --with-arch src",
|
||||||
|
)
|
||||||
|
def _init(with_arch: str = typer.Option("flat", "--with-arch", help="Architecture: flat or src")) -> None:
|
||||||
|
init_handler(with_arch=with_arch) # type: ignore[arg-type]
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(
|
||||||
|
"new",
|
||||||
|
help="Create a new project directory with a flat or src boilerplate.",
|
||||||
|
short_help="Create a new project with boilerplate",
|
||||||
|
epilog="Example: argenta new my-app --with-arch src",
|
||||||
|
)
|
||||||
|
def _new(
|
||||||
|
project_name: str = typer.Argument(help="Name of the new project directory"),
|
||||||
|
with_arch: str = typer.Option("flat", "--with-arch", help="Architecture: flat or src"),
|
||||||
|
) -> None:
|
||||||
|
new_handler(project_name=project_name, with_arch=with_arch) # type: ignore[arg-type]
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(
|
||||||
|
"routes",
|
||||||
|
help="Display all registered routes, commands, aliases, and flags. Accepts an App instance or a callable returning App.",
|
||||||
|
short_help="Show registered routes and commands",
|
||||||
|
epilog="Examples:\n argenta routes app/main.py:app\n argenta routes app/main.py:create_app",
|
||||||
|
)
|
||||||
|
def _routes(entrypoint_path: str = typer.Argument(help="Entrypoint as <path/to/file.py>:<app_or_callable>")) -> None:
|
||||||
|
routes_handler(entrypoint_path)
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(
|
||||||
|
name="info",
|
||||||
|
help="Display Argenta version, Python version, and platform info.",
|
||||||
|
short_help="Show Argenta version and environment info",
|
||||||
|
)
|
||||||
|
def _info() -> None:
|
||||||
|
info_handler()
|
||||||
|
|
||||||
|
|
||||||
|
@app.command(
|
||||||
|
name="build",
|
||||||
|
help="Compile a project entrypoint into a standalone binary using Nuitka.",
|
||||||
|
short_help="Build a standalone binary",
|
||||||
|
epilog="Example: argenta build app/main.py:main --output myapp",
|
||||||
|
)
|
||||||
|
def _build(
|
||||||
|
entry_point: str = typer.Argument(help="Entrypoint as <path/to/file.py>:<callable>"),
|
||||||
|
output_name: str | None = typer.Option(None, "--output", "-o", help="Output binary name"),
|
||||||
|
) -> None:
|
||||||
|
build_handler(entry_point=entry_point, output_name=output_name)
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
app = Typer()
|
|
||||||
app.command(
|
|
||||||
"run",
|
|
||||||
help="Command to start the orchestrator repl; the path to the callable object is required",
|
|
||||||
short_help="Start the orchestrator REPL",
|
|
||||||
epilog="Example: run app/main.py:main",
|
|
||||||
)(run_handler)
|
|
||||||
|
|
||||||
app.command(
|
|
||||||
"init",
|
|
||||||
help="Creates a flat/src boilerplate architecture in an existing project",
|
|
||||||
short_help="Initialize architecture in existing project",
|
|
||||||
epilog="Make sure you are in the project root before running this command.",
|
|
||||||
)(init_handler)
|
|
||||||
|
|
||||||
app.command(
|
|
||||||
"new",
|
|
||||||
help="Creates a project and in it flat/src boilerplate architecture",
|
|
||||||
short_help="Create a new project with boilerplate",
|
|
||||||
epilog="This will create a new directory with the project structure.",
|
|
||||||
)(new_handler)
|
|
||||||
|
|
||||||
app.command(
|
|
||||||
"routes",
|
|
||||||
help="Creates a project and in it flat/src boilerplate architecture",
|
|
||||||
short_help="Create a new project with boilerplate",
|
|
||||||
epilog="This will create a new directory with the project structure.",
|
|
||||||
)(routes_handler)
|
|
||||||
|
|
||||||
app.command(
|
|
||||||
name="info",
|
|
||||||
help="Displays information about the installed Argenta package and environment",
|
|
||||||
short_help="Show Argenta version and environment info",
|
|
||||||
epilog="Uses metadata to retrieve the installed package version.",
|
|
||||||
)(info_handler)
|
|
||||||
|
|
||||||
app.command(
|
|
||||||
name="build",
|
|
||||||
help="Compiles the project into a standalone binary using Nuitka",
|
|
||||||
short_help="Build a standalone binary",
|
|
||||||
)(build_handler)
|
|
||||||
|
|
||||||
app()
|
app()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
__all__ = [
|
||||||
|
"GITIGNORE_CONTENT",
|
||||||
|
"FLAT_MAIN_TEMPLATE",
|
||||||
|
"FLAT_HANDLERS_TEMPLATE",
|
||||||
|
"SRC_MAIN_TEMPLATE",
|
||||||
|
"SRC_ROUTERS_TEMPLATE",
|
||||||
|
"SRC_HANDLER_TEMPLATE",
|
||||||
|
"create_file",
|
||||||
|
]
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
GITIGNORE_CONTENT = """
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
.env
|
||||||
|
.venv/
|
||||||
|
env/
|
||||||
|
"""
|
||||||
|
|
||||||
|
FLAT_MAIN_TEMPLATE = """
|
||||||
|
from argenta import Orchestrator, App
|
||||||
|
|
||||||
|
from handlers import router
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
app = App()
|
||||||
|
app.include_router(router)
|
||||||
|
|
||||||
|
orchestrator = Orchestrator()
|
||||||
|
orchestrator.run_repl(app)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
"""
|
||||||
|
|
||||||
|
FLAT_HANDLERS_TEMPLATE = """
|
||||||
|
from argenta import Router, Response
|
||||||
|
|
||||||
|
router = Router("Hello command")
|
||||||
|
|
||||||
|
@router.command("hello")
|
||||||
|
def hello_handler(response: Response):
|
||||||
|
print("Hello world!")
|
||||||
|
"""
|
||||||
|
|
||||||
|
SRC_MAIN_TEMPLATE = """
|
||||||
|
from argenta import Orchestrator, App
|
||||||
|
|
||||||
|
from .routers import router
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
app = App()
|
||||||
|
app.include_router(router)
|
||||||
|
|
||||||
|
orchestrator = Orchestrator()
|
||||||
|
orchestrator.run_repl(app)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
"""
|
||||||
|
|
||||||
|
SRC_ROUTERS_TEMPLATE = """
|
||||||
|
from argenta import Router
|
||||||
|
from .handlers.hello_world_handler import hello_handler
|
||||||
|
|
||||||
|
router = Router()
|
||||||
|
|
||||||
|
router.command("hello")(hello_handler)
|
||||||
|
"""
|
||||||
|
|
||||||
|
SRC_HANDLER_TEMPLATE = """
|
||||||
|
from argenta import Response
|
||||||
|
|
||||||
|
|
||||||
|
def hello_handler(response: Response) -> None:
|
||||||
|
print("Hello world!")
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def create_file(path: Path, content: str) -> None:
|
||||||
|
if not path.exists():
|
||||||
|
path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
path.write_text(content.strip(), encoding="utf-8")
|
||||||
|
else:
|
||||||
|
print(f"Skipped: {path} (already exists)")
|
||||||
@@ -39,7 +39,7 @@ def build_handler(entry_point: str, output_name: str | None = None) -> None:
|
|||||||
"--standalone",
|
"--standalone",
|
||||||
"--onefile",
|
"--onefile",
|
||||||
f"--output-filename={name}",
|
f"--output-filename={name}",
|
||||||
f"--jobs={os.cpu_count()}",
|
f"--jobs={os.cpu_count() or 1}",
|
||||||
"--lto=no",
|
"--lto=no",
|
||||||
"--include-windows-runtime-dlls=no",
|
"--include-windows-runtime-dlls=no",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -31,6 +31,6 @@ def info_handler() -> None:
|
|||||||
table.add_row("Platform", f"{platform.system()} {platform.release()} ({platform.machine()})")
|
table.add_row("Platform", f"{platform.system()} {platform.release()} ({platform.machine()})")
|
||||||
table.add_row("Docs", "https://argenta.readthedocs.io")
|
table.add_row("Docs", "https://argenta.readthedocs.io")
|
||||||
|
|
||||||
console.print(f"[bold red]{text2art("Argenta", font='tarty1')}[/bold red]")
|
console.print(f"[bold red]{text2art('Argenta', font='tarty1')}[/bold red]")
|
||||||
console.print(Padding(table, pad=(2, 5)))
|
console.print(Padding(table, pad=(2, 5)))
|
||||||
console.print(Padding("[i]made with ❤ by [b]kolo[/b][/i]", pad=(0, 17)))
|
console.print(Padding("[i]made with ❤ by [b]kolo[/b][/i]", pad=(0, 17)))
|
||||||
|
|||||||
@@ -3,83 +3,15 @@ __all__ = ["init_handler"]
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
|
||||||
GITIGNORE_CONTENT = """
|
from ._templates import (
|
||||||
__pycache__/
|
FLAT_HANDLERS_TEMPLATE,
|
||||||
*.py[cod]
|
FLAT_MAIN_TEMPLATE,
|
||||||
.env
|
GITIGNORE_CONTENT,
|
||||||
.venv/
|
SRC_HANDLER_TEMPLATE,
|
||||||
env/
|
SRC_MAIN_TEMPLATE,
|
||||||
"""
|
SRC_ROUTERS_TEMPLATE,
|
||||||
|
create_file,
|
||||||
FLAT_MAIN_TEMPLATE = """
|
)
|
||||||
from argenta import Orchestrator, App
|
|
||||||
|
|
||||||
from handlers import router
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
app = App()
|
|
||||||
app.include_router(router)
|
|
||||||
|
|
||||||
orchestrator = Orchestrator()
|
|
||||||
orchestrator.run_repl(app)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
"""
|
|
||||||
|
|
||||||
FLAT_HANDLERS_TEMPLATE = """
|
|
||||||
from argenta import Router, Response
|
|
||||||
|
|
||||||
router = Router("Hello command")
|
|
||||||
|
|
||||||
@router.command("hello")
|
|
||||||
def start_handler(response: Response):
|
|
||||||
print("Hello world!")
|
|
||||||
"""
|
|
||||||
|
|
||||||
SRC_MAIN_TEMPLATE = """
|
|
||||||
from argenta import Orchestrator, App
|
|
||||||
|
|
||||||
from .routers import router
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
app = App()
|
|
||||||
app.include_router(router)
|
|
||||||
|
|
||||||
orchestrator = Orchestrator()
|
|
||||||
orchestrator.run_repl(app)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
"""
|
|
||||||
|
|
||||||
SRC_ROUTERS_TEMPLATE = """
|
|
||||||
from argenta import Router
|
|
||||||
from .handlers.hello_world_handler import hello_handler
|
|
||||||
|
|
||||||
router = Router()
|
|
||||||
|
|
||||||
router.command('hello')(hello_handler)
|
|
||||||
"""
|
|
||||||
|
|
||||||
SRC_HANDLER_TEMPLATE = """
|
|
||||||
from argenta import Response
|
|
||||||
|
|
||||||
|
|
||||||
def hello_handler(response: Response) -> None:
|
|
||||||
print("Hello world!")
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def create_file(path: Path, content: str) -> None:
|
|
||||||
if not path.exists():
|
|
||||||
path.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
path.write_text(content.strip(), encoding="utf-8")
|
|
||||||
else:
|
|
||||||
print(f"Skipped: {path} (already exists)")
|
|
||||||
|
|
||||||
|
|
||||||
def init_handler(with_arch: Literal["flat", "src"] = "flat") -> None:
|
def init_handler(with_arch: Literal["flat", "src"] = "flat") -> None:
|
||||||
|
|||||||
@@ -4,83 +4,15 @@ import sys
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
|
||||||
|
from ._templates import (
|
||||||
GITIGNORE_CONTENT = """
|
FLAT_HANDLERS_TEMPLATE,
|
||||||
__pycache__/
|
FLAT_MAIN_TEMPLATE,
|
||||||
*.py[cod]
|
GITIGNORE_CONTENT,
|
||||||
.env
|
SRC_HANDLER_TEMPLATE,
|
||||||
.venv/
|
SRC_MAIN_TEMPLATE,
|
||||||
env/
|
SRC_ROUTERS_TEMPLATE,
|
||||||
"""
|
create_file,
|
||||||
|
)
|
||||||
FLAT_MAIN_TEMPLATE = """
|
|
||||||
from argenta import Orchestrator, App
|
|
||||||
|
|
||||||
from handlers import router
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
app = App()
|
|
||||||
app.include_router(router)
|
|
||||||
|
|
||||||
orchestrator = Orchestrator()
|
|
||||||
orchestrator.run_repl(app)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
"""
|
|
||||||
|
|
||||||
FLAT_HANDLERS_TEMPLATE = """
|
|
||||||
from argenta import Router, Response
|
|
||||||
|
|
||||||
router = Router("Hello command")
|
|
||||||
|
|
||||||
@router.command("hello")
|
|
||||||
def start_handler(response: Response):
|
|
||||||
print("Hello world!")
|
|
||||||
"""
|
|
||||||
|
|
||||||
SRC_MAIN_TEMPLATE = """
|
|
||||||
from argenta import Orchestrator, App
|
|
||||||
|
|
||||||
from .routers import router
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
app = App()
|
|
||||||
app.include_router(router)
|
|
||||||
|
|
||||||
orchestrator = Orchestrator()
|
|
||||||
orchestrator.run_repl(app)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
"""
|
|
||||||
|
|
||||||
SRC_ROUTERS_TEMPLATE = """
|
|
||||||
from argenta import Router
|
|
||||||
from .handlers.hello_world_handler import hello_handler
|
|
||||||
|
|
||||||
router = Router()
|
|
||||||
|
|
||||||
router.command('hello')(hello_handler)
|
|
||||||
"""
|
|
||||||
|
|
||||||
SRC_HANDLER_TEMPLATE = """
|
|
||||||
from argenta import Response
|
|
||||||
|
|
||||||
|
|
||||||
def hello_handler(response: Response) -> None:
|
|
||||||
print("Hello world!")
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def create_file(path: Path, content: str) -> None:
|
|
||||||
if not path.exists():
|
|
||||||
path.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
path.write_text(content.strip(), encoding="utf-8")
|
|
||||||
else:
|
|
||||||
print(f"Skipped: {path} (already exists)")
|
|
||||||
|
|
||||||
|
|
||||||
def new_handler(project_name: str, with_arch: Literal["flat", "src"] = "flat") -> None:
|
def new_handler(project_name: str, with_arch: Literal["flat", "src"] = "flat") -> None:
|
||||||
@@ -88,7 +20,7 @@ def new_handler(project_name: str, with_arch: Literal["flat", "src"] = "flat") -
|
|||||||
|
|
||||||
if base_dir.exists():
|
if base_dir.exists():
|
||||||
print(f"Error: Directory '{project_name}' already exists.")
|
print(f"Error: Directory '{project_name}' already exists.")
|
||||||
sys.exit(1)
|
raise SystemExit(1)
|
||||||
|
|
||||||
base_dir.mkdir(parents=True)
|
base_dir.mkdir(parents=True)
|
||||||
print(f"Initialized project directory: {base_dir}")
|
print(f"Initialized project directory: {base_dir}")
|
||||||
|
|||||||
@@ -6,25 +6,53 @@ from rich.console import Console
|
|||||||
from rich.panel import Panel
|
from rich.panel import Panel
|
||||||
from rich.tree import Tree
|
from rich.tree import Tree
|
||||||
|
|
||||||
|
from argenta.app.models import App
|
||||||
|
|
||||||
from ..infrastructure.entrypoint_resolver.entity import (
|
from ..infrastructure.entrypoint_resolver.entity import (
|
||||||
|
CallableEntryPoint,
|
||||||
EntryPointAsApp,
|
EntryPointAsApp,
|
||||||
EntrypointResolver,
|
EntrypointResolver,
|
||||||
|
)
|
||||||
|
from ..infrastructure.entrypoint_resolver.exceptions import (
|
||||||
|
EntrypointError,
|
||||||
|
EntrypointNotAppInstanceError,
|
||||||
ResolveFromStringError,
|
ResolveFromStringError,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def routes_handler(entrypoint_path: str) -> None:
|
def routes_handler(entrypoint_path: str) -> None:
|
||||||
entrypoint_path, _, entrypoint_callable_name = entrypoint_path.partition(":")
|
file_path, _, callable_name = entrypoint_path.partition(":")
|
||||||
if not entrypoint_callable_name:
|
if not callable_name:
|
||||||
raise ResolveFromStringError(
|
Console().print(
|
||||||
"Path to callable object that run orchestrator repl must be in the format <path/to/file.py>:<object_name>"
|
f'[bold red]Error:[/bold red] "{entrypoint_path}" must be in format '
|
||||||
|
f'"<path/to/file.py>:<app_object>" or "<path.to.module>:<app_object>"'
|
||||||
)
|
)
|
||||||
|
raise SystemExit(1)
|
||||||
|
|
||||||
app_instance = EntrypointResolver[EntryPointAsApp](entrypoint_path).parse_entrypoint_with_type(
|
try:
|
||||||
entrypoint_callable_name
|
app_instance = EntrypointResolver[EntryPointAsApp](file_path).parse_entrypoint_with_type(
|
||||||
|
callable_name
|
||||||
)
|
)
|
||||||
|
|
||||||
app = app_instance.instance_object
|
app = app_instance.instance_object
|
||||||
|
except EntrypointNotAppInstanceError:
|
||||||
|
try:
|
||||||
|
callable_entrypoint = EntrypointResolver[CallableEntryPoint](
|
||||||
|
file_path
|
||||||
|
).parse_entrypoint_with_type(
|
||||||
|
callable_name
|
||||||
|
)
|
||||||
|
except (ResolveFromStringError, EntrypointError) as e:
|
||||||
|
Console().print(f"[bold red]Error:[/bold red] {e}")
|
||||||
|
raise SystemExit(1)
|
||||||
|
app = callable_entrypoint.instance_object()
|
||||||
|
if not isinstance(app, App):
|
||||||
|
Console().print(
|
||||||
|
f"[bold red]Error:[/bold red] callable must return an App instance, got {type(app).__name__}"
|
||||||
|
)
|
||||||
|
raise SystemExit(1)
|
||||||
|
except (ResolveFromStringError, EntrypointError) as e:
|
||||||
|
Console().print(f"[bold red]Error:[/bold red] {e}")
|
||||||
|
raise SystemExit(1)
|
||||||
routers = app.registered_routers
|
routers = app.registered_routers
|
||||||
|
|
||||||
console = Console()
|
console = Console()
|
||||||
|
|||||||
@@ -2,23 +2,33 @@ __all__ = ["run_handler"]
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from rich.console import Console
|
||||||
|
|
||||||
from ..infrastructure.entrypoint_resolver.entity import (
|
from ..infrastructure.entrypoint_resolver.entity import (
|
||||||
CallableEntryPoint,
|
CallableEntryPoint,
|
||||||
EntrypointResolver,
|
EntrypointResolver,
|
||||||
|
)
|
||||||
|
from ..infrastructure.entrypoint_resolver.exceptions import (
|
||||||
|
EntrypointError,
|
||||||
ResolveFromStringError,
|
ResolveFromStringError,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def run_handler(entrypoint_path: str) -> None:
|
def run_handler(entrypoint_path: str) -> None:
|
||||||
os.environ["RUN_FROM_ARGENTA_RUNNER"] = "1"
|
os.environ["RUN_FROM_ARGENTA_RUNNER"] = "1"
|
||||||
entrypoint_path, _, entrypoint_callable_name = entrypoint_path.partition(":")
|
file_path, _, callable_name = entrypoint_path.partition(":")
|
||||||
if not entrypoint_callable_name:
|
if not callable_name:
|
||||||
raise ResolveFromStringError(
|
Console().print(
|
||||||
"Path to callable object that run orchestrator repl must be in the format <path/to/file.py>:<object_name> or <path.to.module>:<object_name>"
|
f'[bold red]Error:[/bold red] "{entrypoint_path}" must be in format '
|
||||||
|
f'"<path/to/file.py>:<callable>" or "<path.to.module>:<callable>"'
|
||||||
)
|
)
|
||||||
|
raise SystemExit(1)
|
||||||
|
|
||||||
runner = EntrypointResolver[CallableEntryPoint](entrypoint_path).parse_entrypoint_with_type(
|
try:
|
||||||
entrypoint_callable_name
|
runner = EntrypointResolver[CallableEntryPoint](file_path).parse_entrypoint_with_type(
|
||||||
|
callable_name
|
||||||
)
|
)
|
||||||
|
|
||||||
runner.instance_object()
|
runner.instance_object()
|
||||||
|
except (ResolveFromStringError, EntrypointError) as e:
|
||||||
|
Console().print(f"[bold red]Error:[/bold red] {e}")
|
||||||
|
raise SystemExit(1)
|
||||||
|
|||||||
Reference in New Issue
Block a user