update docs and cli module

This commit is contained in:
2026-08-03 20:00:18 +03:00
parent 6b9bea155f
commit 9f9c650ec6
12 changed files with 806 additions and 239 deletions
+1
View File
@@ -1,5 +1,6 @@
#### joe made this: http://goel.io/joe #### joe made this: http://goel.io/joe
.devin
metrics/reports/diagrams metrics/reports/diagrams
*.dist *.dist
*build *build
+15
View File
@@ -0,0 +1,15 @@
# Argenta
## Agent skills
### Issue tracker
Issues live as GitHub issues in `koloideal/Argenta` (uses the `gh` CLI). See `docs/agents/issue-tracker.md`.
### Triage labels
Five canonical labels used as-is: `needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`, `wontfix`. See `docs/agents/triage-labels.md`.
### Domain docs
Single-context — one `CONTEXT.md` + `docs/adr/` at the repo root. See `docs/agents/domain.md`.
+51
View File
@@ -0,0 +1,51 @@
# Domain Docs
How the engineering skills should consume this repo's domain documentation when exploring the codebase.
## Before exploring, read these
- **`CONTEXT.md`** at the repo root, or
- **`CONTEXT-MAP.md`** at the repo root if it exists — it points at one `CONTEXT.md` per context. Read each one relevant to the topic.
- **`docs/adr/`** — read ADRs that touch the area you're about to work in. In multi-context repos, also check `src/<context>/docs/adr/` for context-scoped decisions.
If any of these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The `/domain-modeling` skill (reached via `/grill-with-docs` and `/improve-codebase-architecture`) creates them lazily when terms or decisions actually get resolved.
## File structure
Single-context repo (most repos):
```
/
├── CONTEXT.md
├── docs/adr/
│ ├── 0001-event-sourced-orders.md
│ └── 0002-postgres-for-write-model.md
└── src/
```
Multi-context repo (presence of `CONTEXT-MAP.md` at the root):
```
/
├── CONTEXT-MAP.md
├── docs/adr/ ← system-wide decisions
└── src/
├── ordering/
│ ├── CONTEXT.md
│ └── docs/adr/ ← context-specific decisions
└── billing/
├── CONTEXT.md
└── docs/adr/
```
## Use the glossary's vocabulary
When your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `CONTEXT.md`. Don't drift to synonyms the glossary explicitly avoids.
If the concept you need isn't in the glossary yet, that's a signal — either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for `/domain-modeling`).
## Flag ADR conflicts
If your output contradicts an existing ADR, surface it explicitly rather than silently overriding:
> _Contradicts ADR-0007 (event-sourced orders) — but worth reopening because…_
+45
View File
@@ -0,0 +1,45 @@
# Issue tracker: GitHub
Issues and PRDs for this repo live as GitHub issues. Use the `gh` CLI for all operations.
## Conventions
- **Create an issue**: `gh issue create --title "..." --body "..."`. Use a heredoc for multi-line bodies.
- **Read an issue**: `gh issue view <number> --comments`, filtering comments by `jq` and also fetching labels.
- **List issues**: `gh issue list --state open --json number,title,body,labels,comments --jq '[.[] | {number, title, body, labels: [.labels[].name], comments: [.comments[].body]}]'` with appropriate `--label` and `--state` filters.
- **Comment on an issue**: `gh issue comment <number> --body "..."`
- **Apply / remove labels**: `gh issue edit <number> --add-label "..."` / `--remove-label "..."`
- **Close**: `gh issue close <number> --comment "..."`
Infer the repo from `git remote -v``gh` does this automatically when run inside a clone.
## Pull requests as a triage surface
**PRs as a request surface: no.** _(Set to `yes` if this repo treats external PRs as feature requests; `/triage` reads this flag.)_
When set to `yes`, PRs run through the same labels and states as issues, using the `gh pr` equivalents:
- **Read a PR**: `gh pr view <number> --comments` and `gh pr diff <number>` for the diff.
- **List external PRs for triage**: `gh pr list --state open --json number,title,body,labels,author,authorAssociation,comments` then keep only `authorAssociation` of `CONTRIBUTOR`, `FIRST_TIME_CONTRIBUTOR`, or `NONE` (drop `OWNER`/`MEMBER`/`COLLABORATOR`).
- **Comment / label / close**: `gh pr comment`, `gh pr edit --add-label`/`--remove-label`, `gh pr close`.
GitHub shares one number space across issues and PRs, so a bare `#42` may be either — resolve with `gh pr view 42` and fall back to `gh issue view 42`.
## When a skill says "publish to the issue tracker"
Create a GitHub issue.
## When a skill says "fetch the relevant ticket"
Run `gh issue view <number> --comments`.
## Wayfinding operations
Used by `/wayfinder`. The **map** is a single issue with **child** issues as tickets.
- **Map**: a single issue labelled `wayfinder:map`, holding the Notes / Decisions-so-far / Fog body. `gh issue create --label wayfinder:map`.
- **Child ticket**: an issue linked to the map as a GitHub sub-issue (`gh api` on the sub-issues endpoint). Where sub-issues aren't enabled, add the child to a task list in the map body and put `Part of #<map>` at the top of the child body. Labels: `wayfinder:<type>` (`research`/`prototype`/`grilling`/`task`). Once claimed, the ticket is assigned to the driving dev.
- **Blocking**: GitHub's **native issue dependencies** — the canonical, UI-visible representation. Add an edge with `gh api --method POST repos/<owner>/<repo>/issues/<child>/dependencies/blocked_by -F issue_id=<blocker-db-id>`, where `<blocker-db-id>` is the blocker's numeric **database id** (`gh api repos/<owner>/<repo>/issues/<n> --jq .id`, _not_ the `#number` or `node_id`). GitHub reports `issue_dependencies_summary.blocked_by` (open blockers only — the live gate). Where dependencies aren't available, fall back to a `Blocked by: #<n>, #<n>` line at the top of the child body. A ticket is unblocked when every blocker is closed.
- **Frontier query**: list the map's open children (`gh issue list --state open`, scoped to the map's sub-issues / task list), drop any with an open blocker (`issue_dependencies_summary.blocked_by > 0`, or an open issue in the `Blocked by` line) or an assignee; first in map order wins.
- **Claim**: `gh issue edit <n> --add-assignee @me` — the session's first write.
- **Resolve**: `gh issue comment <n> --body "<answer>"`, then `gh issue close <n>`, then append a context pointer (gist + link) to the map's Decisions-so-far.
+15
View File
@@ -0,0 +1,15 @@
# Triage Labels
The skills speak in terms of five canonical triage roles. This file maps those roles to the actual label strings used in this repo's issue tracker.
| Label in mattpocock/skills | Label in our tracker | Meaning |
| -------------------------- | -------------------- | ---------------------------------------- |
| `needs-triage` | `needs-triage` | Maintainer needs to evaluate this issue |
| `needs-info` | `needs-info` | Waiting on reporter for more information |
| `ready-for-agent` | `ready-for-agent` | Fully specified, ready for an AFK agent |
| `ready-for-human` | `ready-for-human` | Requires human implementation |
| `wontfix` | `wontfix` | Will not be actioned |
When a skill mentions a role (e.g. "apply the AFK-ready triage label"), use the corresponding label string from this table.
Edit the right-hand column to match whatever vocabulary you actually use.
+486 -151
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Argenta \n" "Project-Id-Version: Argenta \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-07-25 18:00+0300\n" "POT-Creation-Date: 2026-08-03 18:51+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: en\n" "Language: en\n"
@@ -18,221 +18,495 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.17.0\n" "Generated-By: Babel 2.17.0\n"
#: ../../root/cli.rst:3 #: ../../root/cli.rst:4
msgid "Командная строка" msgid "CLI"
msgstr "Command Line Interface" msgstr "CLI"
#: ../../root/cli.rst:5 #: ../../root/cli.rst:6
msgid "" msgid ""
"Помимо библиотеки, ``Argenta`` поставляется с собственным CLI-инструментом, " "Помимо библиотеки, ``Argenta`` поставляется с собственным "
"который помогает создавать проекты, запускать приложения, инспектировать " "CLI-инструментом. Он берёт на себя рутину, которая сопровождает "
"маршруты и собирать бинарники." "разработку CLI-приложений: создаёт каркас проекта, запускает приложение, "
"инспектирует зарегистрированные маршруты и собирает standalone-бинарник."
msgstr "" msgstr ""
"In addition to the library, ``Argenta`` ships with its own CLI tool that " "In addition to the library, ``Argenta`` ships with its own CLI tool. It "
"helps scaffold projects, run applications, inspect routes, and build binaries." "takes over the routine that surrounds CLI app development: scaffolds a "
"project, runs the application, inspects registered routes, and builds a "
"standalone binary."
#: ../../root/cli.rst:8 #: ../../root/cli.rst:8
msgid ""
"CLI поставляется как опциональная зависимость — основная библиотека "
"остаётся лёгкой, а инструмент доступен только тем, кому он нужен."
msgstr ""
"The CLI is shipped as an optional dependency — the core library stays "
"light, and the tool is available only to those who need it."
#: ../../root/cli.rst:11
msgid "Установка" msgid "Установка"
msgstr "Installation" msgstr "Installation"
#: ../../root/cli.rst:10 #: ../../root/cli.rst:13
msgid "CLI доступен как опциональная зависимость:" msgid "CLI доступен как опциональная зависимость ``[cli]``:"
msgstr "The CLI is available as an optional dependency:" msgstr "The CLI is available as the optional ``[cli]`` dependency:"
#: ../../root/cli.rst:16 #: ../../root/cli.rst:23
msgid "После установки команда ``argenta`` доступна в терминале:"
msgstr "After installation, the ``argenta`` command is available in the terminal:"
#: ../../root/cli.rst:34
msgid "" msgid ""
"После установки команда ``argenta`` доступна в терминале:" "Если ``argenta`` установлена без extras, команда ``argenta`` не будет "
"доступна. Установите с ``[cli]``, чтобы получить доступ к "
"CLI-инструменту."
msgstr "" msgstr ""
"After installation, the ``argenta`` command is available in the terminal:" "If ``argenta`` is installed without extras, the ``argenta`` command will "
"not be available. Install with ``[cli]`` to get access to the CLI tool."
#: ../../root/cli.rst:22 #: ../../root/cli.rst:37
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``" msgid "Флаг ``--version``"
msgstr "The ``--version`` flag" msgstr "The ``--version`` flag"
#: ../../root/cli.rst:27 #: ../../root/cli.rst:39
msgid "Показать установленную версию ``Argenta``:" msgid "Показать установленную версию ``Argenta``:"
msgstr "Show the installed ``Argenta`` version:" 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 #: ../../root/cli.rst:45
msgid "``--with-arch`` — архитектура проекта: ``flat`` (по умолчанию) или ``src``." msgid "Аналогично через короткий флаг:"
msgstr "``--with-arch`` — project architecture: ``flat`` (default) or ``src``." msgstr "Equivalently, via the short flag:"
#: ../../root/cli.rst:53 #: ../../root/cli.rst:56
msgid "При архитектуре ``flat`` создаётся следующая структура:" msgid "Формат entrypoint"
msgstr "With the ``flat`` architecture, the following structure is created:" msgstr "Entrypoint format"
#: ../../root/cli.rst:59 #: ../../root/cli.rst:58
msgid "При архитектуре ``src``:" msgid ""
msgstr "With the ``src`` architecture:" "Команды ``run``, ``routes`` и ``build`` принимают **entrypoint** — "
"указатель на объект внутри проекта, который нужно запустить, "
"инспектировать или собрать. Единый формат описан здесь, чтобы не "
"повторяться в каждой команде."
msgstr ""
"The ``run``, ``routes`` and ``build`` commands accept an **entrypoint** —"
" a pointer to an object inside the project to run, inspect, or build. The"
" shared format is documented here once instead of repeating it in each "
"command."
#: ../../root/cli.rst:60
msgid "Формат entrypoint:"
msgstr "Entrypoint format:"
#: ../../root/cli.rst:67 #: ../../root/cli.rst:67
msgid "Команда ``init``" msgid "Поддерживаются два способа адресации:"
msgstr "The ``init`` command" msgstr "Two addressing styles are supported:"
#: ../../root/cli.rst:69 #: ../../root/cli.rst:69
msgid "" msgid ""
"Инициализирует boilerplate в текущей директории. Удобно, когда проект уже " "**Путь к файлу** — ``app/main.py:main``. Удобно при работе с конкретным "
"существует и нужно добавить структуру Argenta." "файлом."
msgstr "" msgstr ""
"Initializes boilerplate in the current directory. Useful when the project " "**File path** — ``app/main.py:main``. Convenient when working with a "
"already exists and you need to add Argenta structure." "specific file."
#: ../../root/cli.rst:75 #: ../../root/cli.rst:70
msgid "" msgid ""
"Команда ``init`` не перезаписывает существующие файлы — они будут пропущены." "**Dotted-модуль** — ``my_project.application:main``. Естественно для "
"установленных пакетов."
msgstr "" msgstr ""
"The ``init`` command does not overwrite existing files — they will be skipped." "**Dotted module** — ``my_project.application:main``. Natural for "
"installed packages."
#: ../../root/cli.rst:80 #: ../../root/cli.rst:72
msgid "Запуск приложений" msgid ""
msgstr "Running Applications" "Если передан путь к директории с ``__main__.py``, он разрешается "
"автоматически — указывать файл явно не нужно."
msgstr ""
"If a directory path containing ``__main__.py`` is passed, it is resolved "
"automatically — no need to name the file explicitly."
#: ../../root/cli.rst:83 #: ../../root/cli.rst:74
msgid "**Примеры валидных entrypoint-ов:**"
msgstr "**Examples of valid entrypoints:**"
#: ../../root/cli.rst:84
msgid ""
"Тип объекта зависит от команды: ``run`` и ``build`` ожидают callable, "
"``routes`` — инстанс ``App`` или callable, возвращающий ``App``."
msgstr ""
"The expected object type depends on the command: ``run`` and ``build`` "
"expect a callable, ``routes`` expects an ``App`` instance or a callable "
"returning ``App``."
#: ../../root/cli.rst:89
msgid "Создание проектов"
msgstr "Scaffolding projects"
#: ../../root/cli.rst:92
msgid "Команда ``new``"
msgstr "The ``new`` command"
#: ../../root/cli.rst:94
msgid ""
"Создаёт новую директорию проекта с boilerplate-кодом. Это отправная "
"точка: вместо ручной настройки структуры — готовый каркас за одну "
"команду."
msgstr ""
"Creates a new project directory with boilerplate code. It is the starting"
" point: instead of setting up the structure by hand, a ready-made "
"skeleton in a single command."
#: ../../root/cli.rst:100
msgid "``project_name`` — имя директории проекта (обязательный аргумент)."
msgstr "``project_name`` — project directory name (required argument)."
#: ../../root/cli.rst:101 ../../root/cli.rst:133
msgid "``--arch`` — архитектура проекта: ``flat`` (по умолчанию) или ``src``."
msgstr "``--arch`` — project architecture: ``flat`` (default) or ``src``."
#: ../../root/cli.rst:103 ../../root/cli.rst:135 ../../root/cli.rst:161
#: ../../root/cli.rst:191
msgid "**Примеры:**"
msgstr "**Examples:**"
#: ../../root/cli.rst:110
msgid "При архитектуре ``flat`` создаётся следующая структура:"
msgstr "With the ``flat`` architecture, the following structure is created:"
#: ../../root/cli.rst:115
msgid "При архитектуре ``src``:"
msgstr "With the ``src`` architecture:"
#: ../../root/cli.rst:125
msgid "Команда ``init``"
msgstr "The ``init`` command"
#: ../../root/cli.rst:127
msgid ""
"Делает то же, что и ``new``, но в текущей директории. Удобно, когда "
"проект уже существует и нужно добавить структуру Argenta, не создавая "
"лишний уровень вложенности."
msgstr ""
"Does the same as ``new``, but in the current directory. Convenient when "
"the project already exists and the Argenta structure needs to be added "
"without introducing an extra level of nesting."
#: ../../root/cli.rst:143
msgid ""
"Команда ``init`` не перезаписывает существующие файлы — они будут "
"пропущены."
msgstr "The ``init`` command does not overwrite existing files — they are skipped."
#: ../../root/cli.rst:148
msgid "Запуск приложения"
msgstr "Running an application"
#: ../../root/cli.rst:151
msgid "Команда ``run``" msgid "Команда ``run``"
msgstr "The ``run`` command" msgstr "The ``run`` command"
#: ../../root/cli.rst:85 #: ../../root/cli.rst:153
msgid "" msgid ""
"Запускает оркестратор ``Argenta`` из callable-ентрипойнта. Это альтернатива " "Запускает оркестратор ``Argenta`` из callable-entrypoint. Это "
"прямому вызову ``python main.py``, но с автоматической настройкой окружения." "альтернатива прямому вызову ``python main.py``, но с автоматической "
"настройкой окружения."
msgstr "" msgstr ""
"Starts the ``Argenta`` orchestrator from a callable entrypoint. This is an " "Starts the ``Argenta`` orchestrator from a callable entrypoint. It is an "
"alternative to directly calling ``python main.py``, but with automatic " "alternative to calling ``python main.py`` directly, but with automatic "
"environment setup." "environment setup."
#: ../../root/cli.rst:89 #: ../../root/cli.rst:159 ../../root/cli.rst:189 ../../root/cli.rst:249
msgid "" msgid "Формат entrypoint — см. :ref:`Формат entrypoint <cli_entrypoint>`."
"``entrypoint`` — путь к callable в формате " msgstr "Entrypoint format — see :ref:`Entrypoint format <cli_entrypoint>`."
"``<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 #: ../../root/cli.rst:173
msgid "" msgid ""
"Команда ``run`` устанавливает переменную окружения " "Команда ``run`` устанавливает переменную окружения "
"``RUN_FROM_ARGENTA_RUNNER=1``, что отключает парсинг аргументов командной " "``RUN_FROM_ARGENTA_RUNNER=1``. ``ArgParser`` видит этот флаг и пропускает"
"строки в ``ArgParser``. Это позволяет запустить REPL без конфликтов с " " парсинг ``sys.argv``, поэтому аргументы самого ``argenta`` (типа "
"CLI-аргументами ``argenta``." "``--help``, ``--version``) не конфликтуют с аргументами запускаемого "
"приложения. REPL стартует чисто, без ошибок про неизвестные флаги."
msgstr "" msgstr ""
"The ``run`` command sets the ``RUN_FROM_ARGENTA_RUNNER=1`` environment " "The ``run`` command sets the ``RUN_FROM_ARGENTA_RUNNER=1`` environment "
"variable, which disables command-line argument parsing in ``ArgParser``. " "variable. ``ArgParser`` sees this flag and skips parsing ``sys.argv``, so"
"This allows starting the REPL without conflicts with ``argenta`` CLI arguments." " the ``argenta`` arguments themselves (such as ``--help``, ``--version``)"
" do not conflict with the arguments of the application being launched. "
"The REPL starts cleanly, with no errors about unknown flags."
#: ../../root/cli.rst:104 #: ../../root/cli.rst:178
msgid "Инспекция маршрутов" msgid "Инспекция маршрутов"
msgstr "Inspecting Routes" msgstr "Inspecting routes"
#: ../../root/cli.rst:107 #: ../../root/cli.rst:181
msgid "Команда ``routes``" msgid "Команда ``routes``"
msgstr "The ``routes`` command" msgstr "The ``routes`` command"
#: ../../root/cli.rst:109 #: ../../root/cli.rst:183
msgid "" msgid ""
"Отображает все зарегистрированные роутеры, команды, алиасы и флаги в виде" "Отображает все зарегистрированные роутеры, команды, алиасы и флаги в виде"
"дерева. Принимает как инстанс ``App``, так и callable, возвращающий ``App``." " дерева. Принимает как инстанс ``App``, так и callable, возвращающий "
"``App``."
msgstr "" msgstr ""
"Displays all registered routers, commands, aliases, and flags as a tree. " "Displays all registered routers, commands, aliases, and flags as a tree. "
"Accepts either an ``App`` instance or a callable returning ``App``." "Accepts either an ``App`` instance or a callable returning ``App``."
#: ../../root/cli.rst:113 #: ../../root/cli.rst:198
msgid "" msgid ""
"``entrypoint`` — путь к ``App`` или callable в формате " "Инстанс ``App`` передаётся напрямую, если роутеры подключены на уровне "
"``<path/to/file.py>:<app_or_callable>``." "модуля:"
msgstr "" msgstr ""
"``entrypoint`` — path to an ``App`` or callable in the format " "An ``App`` instance is passed directly when routers are registered at the"
"``<path/to/file.py>:<app_or_callable>``." " module level:"
#: ../../root/cli.rst:125 #: ../../root/cli.rst:204
msgid "Если передан инстанс ``App``:"
msgstr "If an ``App`` instance is passed:"
#: ../../root/cli.rst:131
msgid "" msgid ""
"Если передан callable (фабрика), он будет вызван, и результат будет " "Фабрика ``create_app`` передаётся, если роутеры регистрируются внутри "
"использован для отображения маршрутов:" "функции — например, зависят от конфига или DI:"
msgstr "" msgstr ""
"If a callable (factory) is passed, it will be called, and the result will " "A ``create_app`` factory is passed when routers are registered inside a "
"be used to display routes:" "function — for example, when they depend on config or DI:"
#: ../../root/cli.rst:139 #: ../../root/cli.rst:211
msgid "" msgid ""
"При использовании callable-ентрипойнта (например, ``create_app``) REPL не " "При использовании callable-entrypoint REPL не запускается — фабрика "
"запускается — фабрика вызывается, и маршруты считываются из возвращённого " "вызывается, и маршруты считываются из возвращённого ``App``."
"``App``. Это полезно, когда роутеры подключаются внутри функции, а не на "
"уровне модуля."
msgstr "" msgstr ""
"When using a callable entrypoint (e.g., ``create_app``), the REPL is not " "When a callable entrypoint is used, the REPL is not started — the factory"
"started — the factory is called, and routes are read from the returned " " is called, and routes are read from the returned ``App``."
"``App``. This is useful when routers are registered inside a function "
"rather than at the module level."
#: ../../root/cli.rst:144 #: ../../root/cli.rst:213 ../../root/cli.rst:325
msgid "Сборка бинарников" msgid "Пример вывода:"
msgstr "Building Binaries" msgstr "Example output:"
#: ../../root/cli.rst:147 #: ../../root/cli.rst:238
msgid "Сборка бинарника"
msgstr "Building a binary"
#: ../../root/cli.rst:241
msgid "Команда ``build``" msgid "Команда ``build``"
msgstr "The ``build`` command" msgstr "The ``build`` command"
#: ../../root/cli.rst:149 #: ../../root/cli.rst:243
msgid "Компилирует проект в standalone-бинарник с помощью `Nuitka <https://nuitka.net/>`_."
msgstr "Compiles a project into a standalone binary using `Nuitka <https://nuitka.net/>`_."
#: ../../root/cli.rst:153
msgid "" msgid ""
"``entrypoint`` — путь к callable в формате " "Компилирует проект в standalone-бинарник с помощью `Nuitka "
"``<path/to/file.py>:<callable>``." "<https://nuitka.net/>`_, которая входит в ``[cli]`` extra."
msgstr "" msgstr ""
"``entrypoint`` — path to a callable in the format " "Compiles a project into a standalone binary using `Nuitka "
"``<path/to/file.py>:<callable>``." "<https://nuitka.net/>`_, which is included in the ``[cli]`` extra."
#: ../../root/cli.rst:154 #: ../../root/cli.rst:251
msgid "" msgid ""
"``--output`` / ``-o`` — имя выходного бинарника (по умолчанию — имя файла" "``--output`` / ``-o`` — имя выходного бинарника (по умолчанию — имя файла"
" или пакета)." " или пакета)."
msgstr "" msgstr ""
"``--output`` / ``-o`` — output binary name (defaults to the file or package name)." "``--output`` / ``-o`` — output binary name (defaults to the file or "
"package name)."
#: ../../root/cli.rst:166 #: ../../root/cli.rst:252
msgid "" msgid ""
"Для использования команды ``build`` необходимо установить ``Nuitka``:" "``--`` — разделитель, после которого передаются **произвольные флаги "
"Nuitka**. Они добавляются к вызову Nuitka после аргументов Argenta, "
"поэтому могут переопределять дефолты и добавлять любые опции, которые "
"Nuitka поддерживает."
msgstr "" msgstr ""
"To use the ``build`` command, you must install ``Nuitka``:" "``--`` — a separator after which **arbitrary Nuitka flags** are passed."
" They are appended to the Nuitka invocation after Argenta's arguments,"
" so they can override defaults and add any options Nuitka supports."
#: ../../root/cli.rst:174 #: ../../root/cli.rst:254
#, fuzzy
msgid "**Базовые примеры:**"
msgstr "**Basic examples:**"
#: ../../root/cli.rst:262
msgid "**Примеры с флагами Nuitka:**"
msgstr "**Examples with Nuitka flags:**"
#: ../../root/cli.rst:271
msgid "Что делает Argenta по умолчанию"
msgstr "What Argenta does by default"
#: ../../root/cli.rst:273
msgid "Команда ``build`` формирует вызов Nuitka со следующими аргументами:"
msgstr "The ``build`` command assembles a Nuitka invocation with the following arguments:"
#: ../../root/cli.rst:275
msgid ""
"``--standalone --onefile`` — собирает единый бинарник со всеми "
"зависимостями внутри."
msgstr ""
"``--standalone --onefile`` — builds a single binary with all dependencies"
" bundled inside."
#: ../../root/cli.rst:276
msgid ""
"``--output-filename=<name>`` — имя выходного файла (из ``--output`` или "
"имени entrypoint)."
msgstr ""
"``--output-filename=<name>`` — output file name (from ``--output`` or the"
" entrypoint name)."
#: ../../root/cli.rst:277
msgid "``--jobs=<cpu_count>`` — параллельная компиляция на всех ядрах."
msgstr "``--jobs=<cpu_count>`` — parallel compilation across all cores."
#: ../../root/cli.rst:278
msgid ""
"``--lto=no`` — LTO отключён по умолчанию (быстрее сборка, медленнее "
"запуск)."
msgstr ""
"``--lto=no`` — LTO is disabled by default (faster build, slower startup)."
#: ../../root/cli.rst:279
msgid ""
"``--include-windows-runtime-dlls=no`` — на Windows не включает runtime "
"DLL в бинарник."
msgstr ""
"``--include-windows-runtime-dlls=no`` — on Windows, runtime DLLs are not"
" bundled into the binary."
#: ../../root/cli.rst:280
msgid ""
"``--python-flag=-m`` — добавляется автоматически, если entrypoint "
"указывает на ``__main__.py``."
msgstr ""
"``--python-flag=-m`` — added automatically when the entrypoint points at"
" a ``__main__.py``."
#: ../../root/cli.rst:282
msgid ""
"Все эти дефолты можно переопределить, передав соответствующий флаг после "
"``--``. Например, ``-- --lto=yes`` включит LTO, а ``-- --jobs=1`` "
"отключит параллельную сборку."
msgstr ""
"Any of these defaults can be overridden by passing the corresponding flag"
" after ``--``. For example, ``-- --lto=yes`` enables LTO, and ``--"
" --jobs=1`` disables parallel compilation."
#: ../../root/cli.rst:285
msgid "Основные флаги Nuitka и их нюансы"
msgstr "Key Nuitka flags and their trade-offs"
#: ../../root/cli.rst:287
msgid ""
"Полный список флагов — в `документации Nuitka <https://nuitka.net/user-"
"documentation/user-manual.html>`_. Ниже — те, с которыми чаще всего "
"сталкиваются при сборке CLI-приложений."
msgstr ""
"The full flag list is in the `Nuitka documentation <https://nuitka.net"
"/user-documentation/user-manual.html>`_. Below are the ones most often"
" encountered when building CLI applications."
#: ../../root/cli.rst:289
#, python-brace-format
msgid "``--lto={yes,no,auto}``"
msgstr "``--lto={yes,no,auto}``"
#: ../../root/cli.rst:290
msgid ""
"Link-Time Optimization. ``yes`` — бинарник меньше и быстрее запускается, "
"но сборка длится заметно дольше. ``no`` (дефолт Argenta) — сборка "
"быстрее, бинарник больше. ``auto`` — Nuitka выбирает сам. Для "
"production-сборки имеет смысл ``yes``, для итеративной разработки — "
"``no``."
msgstr ""
"Link-Time Optimization. ``yes`` — the binary is smaller and starts"
" faster, but the build takes noticeably longer. ``no`` (Argenta's"
" default) — faster build, larger binary. ``auto`` — Nuitka decides. For"
" production builds ``yes`` makes sense; for iterative development, ``no``."
#: ../../root/cli.rst:292
msgid "``--include-package=<package>``"
msgstr "``--include-package=<package>``"
#: ../../root/cli.rst:293
msgid ""
"Явно включает пакет в бинарник. Nuitka отслеживает импорты статически, "
"поэтому пакеты, которые импортируются динамически (через ``importlib``, "
"плагины, ``__import__``), в бинарник не попадают — их нужно добавлять "
"вручную. Типичные кандидаты: ``numpy``, ``pandas``, ``rich``, "
"``prompt_toolkit``."
msgstr ""
"Explicitly includes a package in the binary. Nuitka tracks imports"
" statically, so packages imported dynamically (via ``importlib``, plugins,"
" ``__import__``) do not end up in the binary — they must be added by hand."
" Common candidates: ``numpy``, ``pandas``, ``rich``, ``prompt_toolkit``."
#: ../../root/cli.rst:295
msgid "``--include-data-files=<source>=<dest>``"
msgstr "``--include-data-files=<source>=<dest>``"
#: ../../root/cli.rst:296
msgid ""
"Включает файлы данных (шаблоны, конфиги, ассеты) в бинарник. Формат: "
"``--include-data-files=assets/logo.png=assets/logo.png``. Для директорий "
"целиком — ``--include-data-dir=assets=assets``. Без этого файлы, которые "
"приложение читает во время выполнения, не будут найдены в собранном "
"бинарнике."
msgstr ""
"Includes data files (templates, configs, assets) into the binary. Format:"
" ``--include-data-files=assets/logo.png=assets/logo.png``. For whole"
" directories — ``--include-data-dir=assets=assets``. Without this, files"
" the application reads at runtime will not be found inside the built binary."
#: ../../root/cli.rst:298
msgid "``--enable-plugin=<plugin>``"
msgstr "``--enable-plugin=<plugin>``"
#: ../../root/cli.rst:299
msgid ""
"Включает `плагин Nuitka <https://nuitka.net/user-documentation/user-"
"manual.html#plugins>`_ для поддержки фреймворков, требующих специальной "
"обработки. Распространённые: ``anti-bloat`` (вырезает ненужные части "
"тяжёлых пакетов), ``numpy`` (корректная сборка с numpy), ``tk-inter`` "
"(Tkinter GUI), ``triton`` (PyTorch triton kernels)."
msgstr ""
"Enables a `Nuitka plugin <https://nuitka.net/user-documentation/user-"
"manual.html#plugins>`_ for frameworks that need special handling. Common"
" ones: ``anti-bloat`` (strips unneeded parts of heavy packages), ``numpy``"
" (correct numpy bundling), ``tk-inter`` (Tkinter GUI), ``triton`` (PyTorch"
" triton kernels)."
#: ../../root/cli.rst:301
msgid "``--onefile`` / ``--standalone``"
msgstr "``--onefile`` / ``--standalone``"
#: ../../root/cli.rst:302
msgid ""
"``--onefile`` (дефолт Argenta) — единый бинарник, удобный для "
"дистрибуции. При запуске распаковывается во временную директорию, поэтому"
" стартует медленнее. ``--standalone`` — папка с бинарником и "
"зависимостями, стартует быстрее, но дистрибуция — это вся папка целиком. "
"Чтобы переключиться: ``-- --standalone`` (переопределит дефолтный "
"``--onefile``)."
msgstr ""
"``--onefile`` (Argenta's default) — a single binary, convenient for"
" distribution. It unpacks into a temporary directory on startup, so it"
" starts slower. ``--standalone`` — a folder with the binary and its"
" dependencies; starts faster, but distribution means shipping the whole"
" folder. To switch: ``-- --standalone`` (overrides the default ``--onefile``)."
#: ../../root/cli.rst:304
msgid "``--jobs=<n>``"
msgstr "``--jobs=<n>``"
#: ../../root/cli.rst:305
msgid ""
"Количество параллельных процессов компиляции. Дефолт Argenta — все ядра "
"(``os.cpu_count()``). На машинах с малым объёмом памяти имеет смысл "
"ограничить: ``-- --jobs=2``."
msgstr ""
"Number of parallel compilation processes. Argenta's default is all cores"
" (``os.cpu_count()``). On memory-constrained machines it makes sense to"
" limit it: ``-- --jobs=2``."
#: ../../root/cli.rst:314
msgid "Информация об окружении" msgid "Информация об окружении"
msgstr "Environment Information" msgstr "Environment information"
#: ../../root/cli.rst:177 #: ../../root/cli.rst:317
msgid "Команда ``info``" msgid "Команда ``info``"
msgstr "The ``info`` command" msgstr "The ``info`` command"
#: ../../root/cli.rst:179 #: ../../root/cli.rst:319
msgid "" msgid ""
"Отображает версию ``Argenta``, версию Python, платформу и ссылку на " "Отображает версию ``Argenta``, версию Python, платформу и ссылку на "
"документацию." "документацию."
@@ -240,26 +514,87 @@ msgstr ""
"Displays the ``Argenta`` version, Python version, platform, and a link to" "Displays the ``Argenta`` version, Python version, platform, and a link to"
" the documentation." " the documentation."
#: ../../root/cli.rst:187 #~ msgid "Командная строка"
msgid "Формат ентрипойнтов" #~ msgstr "Command Line Interface"
msgstr "Entrypoint Format"
#: ../../root/cli.rst:190 #~ msgid "Создаёт новую директорию проекта с boilerplate-кодом."
msgid "" #~ msgstr "Creates a new project directory with boilerplate code."
"Все команды, принимающие ентрипойнт (``run``, ``routes``, ``build``), "
"используют единый формат:"
msgstr ""
"All commands that accept an entrypoint (``run``, ``routes``, ``build``) "
"use a unified format:"
#: ../../root/cli.rst:196 #~ msgid ""
msgid "" #~ "``entrypoint`` — путь к callable в "
"Поддерживаются как пути к файлам, так и dotted-модули. Если передан путь к " #~ "формате ``<path/to/file.py>:<callable>`` или "
"директории с ``__main__.py``, он будет разрешён автоматически." #~ "``<path.to.module>:<callable>``."
msgstr "" #~ msgstr ""
"Both file paths and dotted modules are supported. If a directory path " #~ "``entrypoint`` — path to a callable "
"containing ``__main__.py`` is passed, it will be resolved automatically." #~ "in the format ``<path/to/file.py>:<callable>`` "
#~ "or ``<path.to.module>:<callable>``."
#~ 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."
#~ 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>``."
#~ msgid "Если передан инстанс ``App``:"
#~ msgstr "If an ``App`` instance is passed:"
#~ msgid ""
#~ "Если передан callable (фабрика), он "
#~ "будет вызван, и результат будет "
#~ "использован для отображения маршрутов:"
#~ msgstr ""
#~ "If a callable (factory) is passed, "
#~ "it will be called, and the result"
#~ " will be used to display routes:"
#~ msgid ""
#~ "``entrypoint`` — путь к callable в "
#~ "формате ``<path/to/file.py>:<callable>``."
#~ msgstr ""
#~ "``entrypoint`` — path to a callable "
#~ "in the format ``<path/to/file.py>:<callable>``."
#~ msgid "Для использования команды ``build`` необходимо установить ``Nuitka``:"
#~ msgstr "To use the ``build`` command, you must install ``Nuitka``:"
#~ msgid "Формат ентрипойнтов"
#~ msgstr "Entrypoint Format"
#~ msgid ""
#~ "Все команды, принимающие ентрипойнт (``run``,"
#~ " ``routes``, ``build``), используют единый "
#~ "формат:"
#~ msgstr ""
#~ "All commands that accept an entrypoint"
#~ " (``run``, ``routes``, ``build``) use a "
#~ "unified format:"
#~ 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:"
+3 -2
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Argenta \n" "Project-Id-Version: Argenta \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-12-04 20:39+0300\n" "POT-Creation-Date: 2026-08-03 17:30+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: en\n" "Language: en\n"
@@ -82,8 +82,9 @@ msgid "E2E-тестирование цикла"
msgstr "E2E Testing of the Loop" msgstr "E2E Testing of the Loop"
#: ../../root/testing.rst:48 #: ../../root/testing.rst:48
#, fuzzy
msgid "" msgid ""
"Полный запуск цикла ``start_polling`` можно покрывать через подпроцесс с " "Полный запуск цикла ``run_repl`` можно покрывать через подпроцесс с "
"передачей строк в ``stdin``. Это тяжелее и обычно не требуется. Если всё " "передачей строк в ``stdin``. Это тяжелее и обычно не требуется. Если всё "
"же необходимо — пример ниже." "же необходимо — пример ниже."
msgstr "" msgstr ""
+149 -63
View File
@@ -1,33 +1,39 @@
.. _root_cli: .. _root_cli:
Командная строка CLI
================== ===
Помимо библиотеки, ``Argenta`` поставляется с собственным CLI-инструментом, который помогает создавать проекты, запускать приложения, инспектировать маршруты и собирать бинарники. Помимо библиотеки, ``Argenta`` поставляется с собственным CLI-инструментом. Он берёт на себя рутину, которая сопровождает разработку CLI-приложений: создаёт каркас проекта, запускает приложение, инспектирует зарегистрированные маршруты и собирает standalone-бинарник.
CLI поставляется как опциональная зависимость — основная библиотека остаётся лёгкой, а инструмент доступен только тем, кому он нужен.
Установка Установка
--------- ---------
CLI доступен как опциональная зависимость: CLI доступен как опциональная зависимость ``[cli]``:
.. code-block:: shell .. code-block:: shell
pip install argenta[cli] pip install argenta[cli]
.. code-block:: shell
uv add argenta[cli]
После установки команда ``argenta`` доступна в терминале: После установки команда ``argenta`` доступна в терминале:
.. code-block:: shell .. code-block:: shell
argenta --help argenta --help
.. image:: _static/cli/help.png .. image:: https://i.ibb.co/p60T7fvh/image.png
:alt: Argenta CLI help :alt: Argenta CLI help
.. note:: .. note::
Если вы устанавливали ``argenta`` без extras, CLI-инструмент не будет доступен. Установите с ``[cli]`` для доступа к команде ``argenta``. Если ``argenta`` установлена без extras, команда ``argenta`` не будет доступна. Установите с ``[cli]``, чтобы получить доступ к CLI-инструменту.
Флаг ``--version`` Флаг ``--version``
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
Показать установленную версию ``Argenta``: Показать установленную версию ``Argenta``:
@@ -35,33 +41,70 @@ CLI доступен как опциональная зависимость:
argenta --version argenta --version
Аналогично через короткий флаг:
.. code-block:: shell .. code-block:: shell
argenta -v argenta -v
----- -----
.. _cli_entrypoint:
Формат entrypoint
-----------------
Команды ``run``, ``routes`` и ``build`` принимают **entrypoint** — указатель на объект внутри проекта, который нужно запустить, инспектировать или собрать. Единый формат описан здесь, чтобы не повторяться в каждой команде.
Формат entrypoint:
.. code-block:: text
<path/to/file.py>:<object_name>
<path.to.module>:<object_name>
Поддерживаются два способа адресации:
* **Путь к файлу**``app/main.py:main``. Удобно при работе с конкретным файлом.
* **Dotted-модуль**``my_project.application:main``. Естественно для установленных пакетов.
Если передан путь к директории с ``__main__.py``, он разрешается автоматически — указывать файл явно не нужно.
**Примеры валидных entrypoint-ов:**
.. 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
Тип объекта зависит от команды: ``run`` и ``build`` ожидают callable, ``routes`` — инстанс ``App`` или callable, возвращающий ``App``.
-----
Создание проектов Создание проектов
----------------- -----------------
Команда ``new`` Команда ``new``
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
Создаёт новую директорию проекта с boilerplate-кодом. Создаёт новую директорию проекта с boilerplate-кодом. Это отправная точка: вместо ручной настройки структуры — готовый каркас за одну команду.
.. code-block:: shell .. code-block:: shell
argenta new <project_name> [--with-arch flat|src] argenta new <project_name> [--arch flat|src]
* ``project_name`` — имя директории проекта (обязательный аргумент). * ``project_name`` — имя директории проекта (обязательный аргумент).
* ``--with-arch`` — архитектура проекта: ``flat`` (по умолчанию) или ``src``. * ``--arch`` — архитектура проекта: ``flat`` (по умолчанию) или ``src``.
**Примеры:** **Примеры:**
.. code-block:: shell .. code-block:: shell
argenta new my-app argenta new my-app
argenta new my-app --with-arch src argenta new my-app --arch src
При архитектуре ``flat`` создаётся следующая структура: При архитектуре ``flat`` создаётся следующая структура:
@@ -73,45 +116,45 @@ CLI доступен как опциональная зависимость:
.. literalinclude:: ../code_snippets/cli/src_structure.txt .. literalinclude:: ../code_snippets/cli/src_structure.txt
:language: text :language: text
.. image:: _static/cli/new_command.png .. image:: https://i.ibb.co/gY6zTQd/image.png
:alt: argenta new command output :alt: argenta new command output
Команда ``init`` Команда ``init``
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
Инициализирует boilerplate в текущей директории. Удобно, когда проект уже существует и нужно добавить структуру Argenta. Делает то же, что и ``new``, но в текущей директории. Удобно, когда проект уже существует и нужно добавить структуру Argenta, не создавая лишний уровень вложенности.
.. code-block:: shell .. code-block:: shell
argenta init [--with-arch flat|src] argenta init [--arch flat|src]
* ``--with-arch`` — архитектура проекта: ``flat`` (по умолчанию) или ``src``. * ``--arch`` — архитектура проекта: ``flat`` (по умолчанию) или ``src``.
**Примеры:** **Примеры:**
.. code-block:: shell .. code-block:: shell
argenta init argenta init
argenta init --with-arch src argenta init --arch src
.. note:: .. note::
Команда ``init`` не перезаписывает существующие файлы — они будут пропущены. Команда ``init`` не перезаписывает существующие файлы — они будут пропущены.
----- -----
Запуск приложений Запуск приложения
----------------- -----------------
Команда ``run`` Команда ``run``
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
Запускает оркестратор ``Argenta`` из callable-ентрипойнта. Это альтернатива прямому вызову ``python main.py``, но с автоматической настройкой окружения. Запускает оркестратор ``Argenta`` из callable-entrypoint. Это альтернатива прямому вызову ``python main.py``, но с автоматической настройкой окружения.
.. code-block:: shell .. code-block:: shell
argenta run <entrypoint> argenta run <entrypoint>
* ``entrypoint`` — путь к callable в формате ``<path/to/file.py>:<callable>`` или ``<path.to.module>:<callable>``. Формат entrypoint — см. :ref:`Формат entrypoint <cli_entrypoint>`.
**Примеры:** **Примеры:**
@@ -120,11 +163,11 @@ CLI доступен как опциональная зависимость:
argenta run app/main.py:main argenta run app/main.py:main
argenta run my_project.application:main argenta run my_project.application:main
.. image:: _static/cli/run_command.png .. image:: https://i.ibb.co/fVPzxWxp/image.png
:alt: argenta run command output :alt: argenta run command output
.. note:: .. note::
Команда ``run`` устанавливает переменную окружения ``RUN_FROM_ARGENTA_RUNNER=1``, что отключает парсинг аргументов командной строки в ``ArgParser``. Это позволяет запустить REPL без конфликтов с CLI-аргументами ``argenta``. Команда ``run`` устанавливает переменную окружения ``RUN_FROM_ARGENTA_RUNNER=1``. ``ArgParser`` видит этот флаг и пропускает парсинг ``sys.argv``, поэтому аргументы самого ``argenta`` (типа ``--help``, ``--version``) не конфликтуют с аргументами запускаемого приложения. REPL стартует чисто, без ошибок про неизвестные флаги.
----- -----
@@ -140,7 +183,7 @@ CLI доступен как опциональная зависимость:
argenta routes <entrypoint> argenta routes <entrypoint>
* ``entrypoint`` — путь к ``App`` или callable в формате ``<path/to/file.py>:<app_or_callable>``. Формат entrypoint — см. :ref:`Формат entrypoint <cli_entrypoint>`.
**Примеры:** **Примеры:**
@@ -149,42 +192,62 @@ CLI доступен как опциональная зависимость:
argenta routes app/main.py:app argenta routes app/main.py:app
argenta routes app/main.py:create_app argenta routes app/main.py:create_app
Если передан инстанс ``App``: Инстанс ``App`` передаётся напрямую, если роутеры подключены на уровне модуля:
.. literalinclude:: ../code_snippets/cli/app_instance.py .. literalinclude:: ../code_snippets/cli/app_instance.py
:language: python :language: python
:linenos: :linenos:
Если передан callable (фабрика), он будет вызван, и результат будет использован для отображения маршрутов: Фабрика ``create_app`` передаётся, если роутеры регистрируются внутри функции — например, зависят от конфига или DI:
.. literalinclude:: ../code_snippets/cli/app_factory.py .. literalinclude:: ../code_snippets/cli/app_factory.py
:language: python :language: python
:linenos: :linenos:
.. image:: _static/cli/routes_command.png
:alt: argenta routes command output
.. note:: .. note::
При использовании callable-ентрипойнта (например, ``create_app``) REPL не запускается — фабрика вызывается, и маршруты считываются из возвращённого ``App``. Это полезно, когда роутеры подключаются внутри функции, а не на уровне модуля. При использовании callable-entrypoint REPL не запускается — фабрика вызывается, и маршруты считываются из возвращённого ``App``.
Пример вывода:
.. code-block:: text
──────────────────────────────────────────
App Stats
──────────────────────────────────────────
Total Routers: 1
Total Commands: 1
Total Aliases: 0
Total Flags: 0
──────────────────────────────────────────
📦 App object: <App>
└── 📁 Router: Example
└── ⚡ hello
📝 description: Say hello
.. image:: https://i.ibb.co/wNFvKcqM/image.png
:alt: argenta routes command output
----- -----
Сборка бинарников Сборка бинарника
----------------- ----------------
Команда ``build`` Команда ``build``
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
Компилирует проект в standalone-бинарник с помощью `Nuitka <https://nuitka.net/>`_. Компилирует проект в standalone-бинарник с помощью `Nuitka <https://nuitka.net/>`_, которая входит в ``[cli]`` extra.
.. code-block:: shell .. code-block:: shell
argenta build <entrypoint> [--output <name>] argenta build <entrypoint> [--output <name>] [-- <nuitka-flags>...]
Формат entrypoint — см. :ref:`Формат entrypoint <cli_entrypoint>`.
* ``entrypoint`` — путь к callable в формате ``<path/to/file.py>:<callable>``.
* ``--output`` / ``-o`` — имя выходного бинарника (по умолчанию — имя файла или пакета). * ``--output`` / ``-o`` — имя выходного бинарника (по умолчанию — имя файла или пакета).
* ``--`` — разделитель, после которого передаются **произвольные флаги Nuitka**. Они добавляются к вызову Nuitka после аргументов Argenta, поэтому могут переопределять дефолты и добавлять любые опции, которые Nuitka поддерживает.
**Примеры:** **Базовые примеры:**
.. code-block:: shell .. code-block:: shell
@@ -192,14 +255,52 @@ CLI доступен как опциональная зависимость:
argenta build app/main.py:main --output myapp argenta build app/main.py:main --output myapp
argenta build app/__main__.py:main -o myapp argenta build app/__main__.py:main -o myapp
.. warning:: **Примеры с флагами Nuitka:**
Для использования команды ``build`` необходимо установить ``Nuitka``:
.. code-block:: shell .. code-block:: shell
pip install nuitka argenta build app/main.py:main -- --lto=yes
argenta build app/main.py:main -- --include-package=numpy
argenta build app/main.py:main -o myapp -- --lto=auto --include-data-files=assets/*=assets/
.. image:: _static/cli/build_command.png Что делает Argenta по умолчанию
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Команда ``build`` формирует вызов Nuitka со следующими аргументами:
* ``--standalone --onefile`` — собирает единый бинарник со всеми зависимостями внутри.
* ``--output-filename=<name>`` — имя выходного файла (из ``--output`` или имени entrypoint).
* ``--jobs=<cpu_count>`` — параллельная компиляция на всех ядрах.
* ``--lto=no`` — LTO отключён по умолчанию (быстрее сборка, медленнее запуск).
* ``--include-windows-runtime-dlls=no`` — на Windows не включает runtime DLL в бинарник.
* ``--python-flag=-m`` — добавляется автоматически, если entrypoint указывает на ``__main__.py``.
Все эти дефолты можно переопределить, передав соответствующий флаг после ``--``. Например, ``-- --lto=yes`` включит LTO, а ``-- --jobs=1`` отключит параллельную сборку.
Основные флаги Nuitka и их нюансы
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Полный список флагов — в `документации Nuitka <https://nuitka.net/user-documentation/user-manual.html>`_. Ниже — те, с которыми чаще всего сталкиваются при сборке CLI-приложений.
``--lto={yes,no,auto}``
Link-Time Optimization. ``yes`` — бинарник меньше и быстрее запускается, но сборка длится заметно дольше. ``no`` (дефолт Argenta) — сборка быстрее, бинарник больше. ``auto`` — Nuitka выбирает сам. Для production-сборки имеет смысл ``yes``, для итеративной разработки — ``no``.
``--include-package=<package>``
Явно включает пакет в бинарник. Nuitka отслеживает импорты статически, поэтому пакеты, которые импортируются динамически (через ``importlib``, плагины, ``__import__``), в бинарник не попадают — их нужно добавлять вручную. Типичные кандидаты: ``numpy``, ``pandas``, ``rich``, ``prompt_toolkit``.
``--include-data-files=<source>=<dest>``
Включает файлы данных (шаблоны, конфиги, ассеты) в бинарник. Формат: ``--include-data-files=assets/logo.png=assets/logo.png``. Для директорий целиком — ``--include-data-dir=assets=assets``. Без этого файлы, которые приложение читает во время выполнения, не будут найдены в собранном бинарнике.
``--enable-plugin=<plugin>``
Включает `плагин Nuitka <https://nuitka.net/user-documentation/user-manual.html#plugins>`_ для поддержки фреймворков, требующих специальной обработки. Распространённые: ``anti-bloat`` (вырезает ненужные части тяжёлых пакетов), ``numpy`` (корректная сборка с numpy), ``tk-inter`` (Tkinter GUI), ``triton`` (PyTorch triton kernels).
``--onefile`` / ``--standalone``
``--onefile`` (дефолт Argenta) — единый бинарник, удобный для дистрибуции. При запуске распаковывается во временную директорию, поэтому стартует медленнее. ``--standalone`` — папка с бинарником и зависимостями, стартует быстрее, но дистрибуция — это вся папка целиком. Чтобы переключиться: ``-- --standalone`` (переопределит дефолтный ``--onefile``).
``--jobs=<n>``
Количество параллельных процессов компиляции. Дефолт Argenta — все ядра (``os.cpu_count()``). На машинах с малым объёмом памяти имеет смысл ограничить: ``-- --jobs=2``.
.. image:: https://i.ibb.co/VsVXxf7/image.png
:alt: argenta build command output :alt: argenta build command output
----- -----
@@ -216,29 +317,14 @@ CLI доступен как опциональная зависимость:
argenta info argenta info
.. image:: _static/cli/info_command.png Пример вывода:
.. code-block:: text
Argenta 1.2.0
Python 3.13.0
Platform Linux-7.1.5-zen1-2-zen-x86_64-with-glibc2.40
Docs https://argenta.readthedocs.io
.. image:: https://i.ibb.co/B5k8Ftyg/image.png
:alt: argenta info command output :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
+18 -10
View File
@@ -1,7 +1,7 @@
from importlib.metadata import version from importlib.metadata import version
import typer import typer
from typer import Typer from typer import Context, Typer
from .commands import ( from .commands import (
build_handler, build_handler,
@@ -53,23 +53,23 @@ def _run(entrypoint_path: str = typer.Argument(help="Entrypoint as <path/to/file
"init", "init",
help="Scaffold a flat or src boilerplate in the current project directory.", help="Scaffold a flat or src boilerplate in the current project directory.",
short_help="Initialize architecture in existing project", short_help="Initialize architecture in existing project",
epilog="Run from the project root. Example: argenta init --with-arch src", epilog="Run from the project root. Example: argenta init --arch src",
) )
def _init(with_arch: str = typer.Option("flat", "--with-arch", help="Architecture: flat or src")) -> None: def _init(arch: str = typer.Option("flat", "--arch", help="Architecture: flat or src")) -> None:
init_handler(with_arch=with_arch) # type: ignore[arg-type] init_handler(arch=arch) # type: ignore[arg-type]
@app.command( @app.command(
"new", "new",
help="Create a new project directory with a flat or src boilerplate.", help="Create a new project directory with a flat or src boilerplate.",
short_help="Create a new project with boilerplate", short_help="Create a new project with boilerplate",
epilog="Example: argenta new my-app --with-arch src", epilog="Example: argenta new my-app --arch src",
) )
def _new( def _new(
project_name: str = typer.Argument(help="Name of the new project directory"), 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"), arch: str = typer.Option("flat", "--arch", help="Architecture: flat or src"),
) -> None: ) -> None:
new_handler(project_name=project_name, with_arch=with_arch) # type: ignore[arg-type] new_handler(project_name=project_name, arch=arch) # type: ignore[arg-type]
@app.command( @app.command(
@@ -93,15 +93,23 @@ def _info() -> None:
@app.command( @app.command(
name="build", name="build",
help="Compile a project entrypoint into a standalone binary using Nuitka.", help="Compile a project entrypoint into a standalone binary using Nuitka. "
"Any Nuitka flags can be passed after a `--` separator, e.g. "
"`argenta build app/main.py:main -- --lto=yes --include-package=numpy`.",
short_help="Build a standalone binary", short_help="Build a standalone binary",
epilog="Example: argenta build app/main.py:main --output myapp", epilog=(
"Examples:\n"
" argenta build app/main.py:main --output myapp\n"
" argenta build app/main.py:main -- --lto=yes --include-data-files=assets/*=assets/"
),
context_settings={"allow_extra_args": True, "ignore_unknown_options": True},
) )
def _build( def _build(
ctx: Context,
entry_point: str = typer.Argument(help="Entrypoint as <path/to/file.py>:<callable>"), 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"), output_name: str | None = typer.Option(None, "--output", "-o", help="Output binary name"),
) -> None: ) -> None:
build_handler(entry_point=entry_point, output_name=output_name) build_handler(entry_point=entry_point, output_name=output_name, extra_nuitka_args=ctx.args)
def main() -> None: def main() -> None:
+11 -1
View File
@@ -8,7 +8,11 @@ from pathlib import Path
from rich.console import Console from rich.console import Console
def build_handler(entry_point: str, output_name: str | None = None) -> None: def build_handler(
entry_point: str,
output_name: str | None = None,
extra_nuitka_args: list[str] | None = None,
) -> None:
console = Console() console = Console()
file_path, _, callable_name = entry_point.partition(":") file_path, _, callable_name = entry_point.partition(":")
@@ -47,6 +51,12 @@ def build_handler(entry_point: str, output_name: str | None = None) -> None:
if is_main_module: if is_main_module:
args.append("--python-flag=-m") args.append("--python-flag=-m")
# User-provided Nuitka flags are appended last, so they can override
# Argenta's defaults (e.g. --lto=yes, --jobs=1) and add anything else
# Nuitka supports (--include-package, --include-data-files, --enable-plugin, ...).
if extra_nuitka_args:
args.extend(extra_nuitka_args)
args.append(target) args.append(target)
result = subprocess.run(args, check=False) result = subprocess.run(args, check=False)
+3 -3
View File
@@ -14,17 +14,17 @@ from ._templates import (
) )
def init_handler(with_arch: Literal["flat", "src"] = "flat") -> None: def init_handler(arch: Literal["flat", "src"] = "flat") -> None:
cwd = Path.cwd() cwd = Path.cwd()
project_name = cwd.name.lower().replace(" ", "_") project_name = cwd.name.lower().replace(" ", "_")
create_file(cwd / ".gitignore", GITIGNORE_CONTENT) create_file(cwd / ".gitignore", GITIGNORE_CONTENT)
if with_arch == "flat": if arch == "flat":
create_file(cwd / "main.py", FLAT_MAIN_TEMPLATE) create_file(cwd / "main.py", FLAT_MAIN_TEMPLATE)
create_file(cwd / "handlers.py", FLAT_HANDLERS_TEMPLATE) create_file(cwd / "handlers.py", FLAT_HANDLERS_TEMPLATE)
elif with_arch == "src": elif arch == "src":
base_pkg = cwd / "src" / project_name / "application" base_pkg = cwd / "src" / project_name / "application"
create_file(base_pkg / "__main__.py", SRC_MAIN_TEMPLATE) create_file(base_pkg / "__main__.py", SRC_MAIN_TEMPLATE)
+3 -3
View File
@@ -15,7 +15,7 @@ from ._templates import (
) )
def new_handler(project_name: str, with_arch: Literal["flat", "src"] = "flat") -> None: def new_handler(project_name: str, arch: Literal["flat", "src"] = "flat") -> None:
base_dir = Path.cwd() / project_name base_dir = Path.cwd() / project_name
if base_dir.exists(): if base_dir.exists():
@@ -27,11 +27,11 @@ def new_handler(project_name: str, with_arch: Literal["flat", "src"] = "flat") -
create_file(base_dir / ".gitignore", GITIGNORE_CONTENT) create_file(base_dir / ".gitignore", GITIGNORE_CONTENT)
if with_arch == "flat": if arch == "flat":
create_file(base_dir / "main.py", FLAT_MAIN_TEMPLATE) create_file(base_dir / "main.py", FLAT_MAIN_TEMPLATE)
create_file(base_dir / "handlers.py", FLAT_HANDLERS_TEMPLATE) create_file(base_dir / "handlers.py", FLAT_HANDLERS_TEMPLATE)
elif with_arch == "src": elif arch == "src":
pkg_name = project_name.lower().replace(" ", "_").replace("-", "_") pkg_name = project_name.lower().replace(" ", "_").replace("-", "_")
app_pkg = base_dir / "src" / pkg_name / "application" app_pkg = base_dir / "src" / pkg_name / "application"