Update documentation and code snippets

This commit is contained in:
2025-12-02 10:51:44 +03:00
parent 2a96dfcabe
commit 19906c1b1b
28 changed files with 85 additions and 531 deletions
+2 -8
View File
@@ -1,17 +1,11 @@
import re import re
from argenta.command import Command, Flag, Flags
from argenta import Command
from argenta.command import Flag, Flags
# Создание коллекции с флагами
flags = Flags( flags = Flags(
[ [
Flag( Flag("host", possible_values=re.compile(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$")),
"host", possible_values=re.compile(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$")
),
Flag("port", possible_values=re.compile(r"^\d{1,5}$")), Flag("port", possible_values=re.compile(r"^\d{1,5}$")),
] ]
) )
# Использование в команде
cmd = Command("start", description="Start the server", flags=flags) cmd = Command("start", description="Start the server", flags=flags)
+1 -3
View File
@@ -1,11 +1,9 @@
from argenta.command import Flag, Flags from argenta.command import Flag, Flags
# Создание коллекции
flags: Flags = Flags() flags: Flags = Flags()
# Динамическое добавление флагов
flags.add_flag(Flag("config")) flags.add_flag(Flag("config"))
flags.add_flag(Flag("debug")) flags.add_flag(Flag("debug"))
flags.add_flag(Flag("log-level", possible_values=["INFO", "DEBUG", "ERROR"])) flags.add_flag(Flag("log-level", possible_values=["INFO", "DEBUG", "ERROR"]))
print(len(flags.flags)) # 3 print(len(flags)) # 3
+1 -4
View File
@@ -1,10 +1,8 @@
from argenta.command import Flag, Flags from argenta.command import Flag, Flags
from argenta.command.flag.defaults import PredefinedFlags from argenta.command.flag.defaults import PredefinedFlags
# Начальная коллекция
flags = Flags([PredefinedFlags.HOST]) flags = Flags([PredefinedFlags.HOST])
# Дополнительные флаги
additional_flags = [ additional_flags = [
PredefinedFlags.PORT, PredefinedFlags.PORT,
Flag("database"), Flag("database"),
@@ -12,7 +10,6 @@ additional_flags = [
Flag("verbose"), Flag("verbose"),
] ]
# Добавление списка флагов
flags.add_flags(additional_flags) flags.add_flags(additional_flags)
print(len(flags.flags)) # 5 print(len(flags)) # 5
+1 -2
View File
@@ -1,14 +1,13 @@
from argenta.command import Flag, Flags from argenta.command import Flag, Flags
from argenta.command.flag.defaults import PredefinedFlags from argenta.command.flag.defaults import PredefinedFlags
flags = Flags([PredefinedFlags.HOST, PredefinedFlags.PORT, Flag("verbose")]) flags = Flags([PredefinedFlags.HOST, PredefinedFlags.PORT, Flag("verbose")])
# Получение флага по имени
host_flag = flags.get_flag_by_name("host") host_flag = flags.get_flag_by_name("host")
if host_flag: if host_flag:
print(f"Found flag: {host_flag.name}") print(f"Found flag: {host_flag.name}")
# Поиск несуществующего флага
unknown_flag = flags.get_flag_by_name("nonexistent") unknown_flag = flags.get_flag_by_name("nonexistent")
if unknown_flag is None: if unknown_flag is None:
print("Flag not found") print("Flag not found")
-12
View File
@@ -1,12 +0,0 @@
from argenta.command import Flag, Flags
from argenta.command.flag.defaults import PredefinedFlags
flags = Flags([PredefinedFlags.HOST, PredefinedFlags.PORT, Flag("verbose")])
# Итерация по всем флагам
for flag in flags:
print(f"Flag: {flag.name} (type: {type(flag).__name__})")
# Использование в list comprehension
flag_names = [flag.name for flag in flags]
print(f"All flags: {flag_names}")
-12
View File
@@ -1,12 +0,0 @@
from argenta.command import Flag, Flags
flags = Flags([Flag("first"), Flag("second"), Flag("third")])
print(flags[0].name)
# first
print(flags[1].name)
# second
print(flags[2].name)
# third
+6 -5
View File
@@ -1,22 +1,23 @@
from argenta import Command, Response, Router from argenta import Command, Response, Router
from argenta.command import Flag, Flags from argenta.command import Flag, Flags
router = Router(title="Example")
router = Router(title="Example")
@router.command( @router.command(
Command( Command(
"example", "example",
description="Example command with flags", description="Example command with flags",
flags=Flags([Flag("name"), Flag("age")]), flags=Flags([
Flag("name"),
Flag("age")
]),
) )
) )
def example_handler(response: Response): def example_handler(response: Response):
# response.input_flags содержит коллекцию InputFlags
input_flags = response.input_flags input_flags = response.input_flags
# Проверяем наличие флагов
if input_flags: if input_flags:
print(f"Received {len(input_flags.flags)} flag(s)") print(f"Received {len(input_flags)} flag(s)")
else: else:
print("No flags provided") print("No flags provided")
+4 -7
View File
@@ -1,5 +1,5 @@
from argenta import Command, Response, Router from argenta import Command, Response, Router
from argenta.command import Flag, Flags from argenta.command import Flag, Flags, InputFlag
from argenta.command.flag import ValidationStatus from argenta.command.flag import ValidationStatus
router = Router(title="Comprehensive Example") router = Router(title="Comprehensive Example")
@@ -21,12 +21,11 @@ router = Router(title="Comprehensive Example")
def validate_handler(response: Response): def validate_handler(response: Response):
input_flags = response.input_flags input_flags = response.input_flags
# Итерируемся по всем флагам и проверяем их статусы
print("Flag validation results:") print("Flag validation results:")
valid_flags = [] valid_flags: list[InputFlag] = []
invalid_flags = [] invalid_flags: list[InputFlag] = []
undefined_flags = [] undefined_flags: list[InputFlag] = []
for flag in input_flags: for flag in input_flags:
if flag.status == ValidationStatus.VALID: if flag.status == ValidationStatus.VALID:
@@ -39,13 +38,11 @@ def validate_handler(response: Response):
undefined_flags.append(flag) undefined_flags.append(flag)
print(f" ? {flag.string_entity}: {flag.input_value} (UNDEFINED)") print(f" ? {flag.string_entity}: {flag.input_value} (UNDEFINED)")
# Выводим сводку
print("\nSummary:") print("\nSummary:")
print(f" Valid flags: {len(valid_flags)}") print(f" Valid flags: {len(valid_flags)}")
print(f" Invalid flags: {len(invalid_flags)}") print(f" Invalid flags: {len(invalid_flags)}")
print(f" Undefined flags: {len(undefined_flags)}") print(f" Undefined flags: {len(undefined_flags)}")
# Обрабатываем только валидные флаги
if valid_flags: if valid_flags:
print("\nProcessing valid flags:") print("\nProcessing valid flags:")
for flag in valid_flags: for flag in valid_flags:
+5 -3
View File
@@ -8,13 +8,16 @@ router = Router(title="Get Flag Example")
Command( Command(
"config", "config",
description="Configure settings", description="Configure settings",
flags=Flags([Flag("host"), Flag("port"), Flag("debug")]), flags=Flags([
Flag("host"),
Flag("port"),
Flag("debug")
]),
) )
) )
def config_handler(response: Response): def config_handler(response: Response):
input_flags = response.input_flags input_flags = response.input_flags
# Получаем флаг по имени
host_flag = input_flags.get_flag_by_name("host") host_flag = input_flags.get_flag_by_name("host")
port_flag = input_flags.get_flag_by_name("port") port_flag = input_flags.get_flag_by_name("port")
debug_flag = input_flags.get_flag_by_name("debug") debug_flag = input_flags.get_flag_by_name("debug")
@@ -28,7 +31,6 @@ def config_handler(response: Response):
if debug_flag: if debug_flag:
print("Debug mode enabled") print("Debug mode enabled")
# Если флаг не найден, get_flag_by_name вернёт None
missing_flag = input_flags.get_flag_by_name("nonexistent") missing_flag = input_flags.get_flag_by_name("nonexistent")
if missing_flag is None: if missing_flag is None:
print("Flag 'nonexistent' not found") print("Flag 'nonexistent' not found")
@@ -1,26 +0,0 @@
from argenta import Command, Response, Router
from argenta.command import Flag, Flags
router = Router(title="Iterate Example")
@router.command(
Command(
"process",
description="Process with multiple flags",
flags=Flags([Flag("file"), Flag("format"), Flag("output")]),
)
)
def process_handler(response: Response):
input_flags = response.input_flags
# Итерируемся по всем введённым флагам
print("All flags:")
for flag in input_flags:
status_str = flag.status.name if flag.status else "None"
print(f" {flag.string_entity}: {flag.input_value} (status: {status_str})")
# Также можно использовать enumerate для получения индексов
print("\nFlags with indices:")
for index, flag in enumerate(input_flags):
print(f" [{index}] {flag.name}: {flag.input_value}")
@@ -1,29 +0,0 @@
from argenta import Command, Response, Router
from argenta.command import Flag, Flags
router = Router(title="Index Access Example")
@router.command(
Command(
"example",
description="Example with indexed access",
flags=Flags([Flag("first"), Flag("second"), Flag("third")]),
)
)
def example_handler(response: Response):
input_flags = response.input_flags
# Получаем флаги по индексу
if len(input_flags.flags) > 0:
first_flag = input_flags[0]
print(f"First flag: {first_flag.name} = {first_flag.input_value}")
if len(input_flags.flags) > 1:
second_flag = input_flags[1]
print(f"Second flag: {second_flag.name} = {second_flag.input_value}")
# Можно использовать срез для получения нескольких флагов
if len(input_flags.flags) >= 2:
first_two = input_flags.flags[:2]
print(f"First two flags: {[f.name for f in first_two]}")
+6 -19
View File
@@ -2,44 +2,32 @@ from argenta import Router, Response, Command, DataBridge
from argenta.command import Flag from argenta.command import Flag
from argenta.di import FromDishka from argenta.di import FromDishka
# 1. Создаём роутер
router = Router(title="Authentication") router = Router(title="Authentication")
# 2. Определяем сервис и обработчики
def authenticate_user(username: str) -> str: def authenticate_user(username: str) -> str:
"""Возвращает фиктивный токен для пользователя."""
return f"token_for_{username}" return f"token_for_{username}"
@router.command(Command("login", flags=Flag("username"))) @router.command(Command("login", flags=Flag("username")))
def login_handler(response: Response, data_bridge: FromDishka[DataBridge]): def login_handler(response: Response, data_bridge: FromDishka[DataBridge]):
"""Обработчик для команды 'login'. Сохраняет токен в хранилище."""
username_flag = response.input_flags.get_flag_by_name("username") username_flag = response.input_flags.get_flag_by_name("username")
if not username_flag or not username_flag.input_value: if not username_flag or not username_flag.input_value:
print( print("Ошибка необходимо указать имя пользователя с помощью флага --username.")
"[red]Ошибка:[/red] необходимо указать имя пользователя с помощью флага --username."
)
return return
username = username_flag.input_value username = username_flag.input_value
token = authenticate_user(username) token = authenticate_user(username)
# Сохраняем токен в общем хранилище сессии
data_bridge.update({"auth_token": token}) data_bridge.update({"auth_token": token})
print(f"[green]Успешный вход![/green] Пользователь '{username}' аутентифицирован.") print(f"Успешный вход! Пользователь '{username}' аутентифицирован.")
@router.command("get-profile") @router.command("get-profile")
def get_profile_handler(response: Response, data_bridge: FromDishka[DataBridge]): def get_profile_handler(response: Response, data_bridge: FromDishka[DataBridge])
"""Обработчик для команды 'get-profile'. Использует токен из хранилища.""" token = data_bridge.get_by_key("auth_token")
session_data = data_bridge.get_all()
token = session_data.get("auth_token")
if not token: if not token:
print( print("Ошибка: вы не аутентифицированы. Сначала выполните команду 'login'.")
"[red]Ошибка:[/red] вы не аутентифицированы. Сначала выполните команду 'login'."
)
return return
print(f"Загрузка профиля с использованием токена: [yellow]{token}[/yellow]") print(f"Загрузка профиля с использованием токена: [yellow]{token}[/yellow]")
@@ -47,9 +35,8 @@ def get_profile_handler(response: Response, data_bridge: FromDishka[DataBridge])
@router.command("logout") @router.command("logout")
def logout_handler(response: Response, data_bridge: FromDishka[DataBridge]): def logout_handler(response: Response, data_bridge: FromDishka[DataBridge]):
"""Обработчик для команды 'logout'. Очищает токен."""
try: try:
data_bridge.delete_by_key("auth_token") data_bridge.delete_by_key("auth_token")
print("[green]Выход выполнен.[/green] Данные сессии очищены.") print("Выход выполнен. Данные сессии очищены.")
except KeyError: except KeyError:
print("Вы и так не были аутентифицированы.") print("Вы и так не были аутентифицированы.")
-4
View File
@@ -6,10 +6,6 @@ router = Router(title="Example")
@router.command(Command("greet", description="Greet the user")) @router.command(Command("greet", description="Greet the user"))
def greet_handler(response: Response): def greet_handler(response: Response):
# response автоматически передаётся в обработчик
# response.status содержит статус валидации флагов
# response.input_flags содержит все введённые флаги
if response.status == ResponseStatus.ALL_FLAGS_VALID: if response.status == ResponseStatus.ALL_FLAGS_VALID:
print("Hello! All flags are valid.") print("Hello! All flags are valid.")
else: else:
+7 -6
View File
@@ -1,5 +1,6 @@
from argenta import Command, Response, Router from argenta import Command, Response, Router
from argenta.command import Flag, Flags from argenta.command import Flag, Flags
from argenta.command.flag import ValidationStatus
from argenta.response import ResponseStatus from argenta.response import ResponseStatus
router = Router(title="Flags Example") router = Router(title="Flags Example")
@@ -9,14 +10,15 @@ router = Router(title="Flags Example")
Command( Command(
"process", "process",
description="Process with flags", description="Process with flags",
flags=Flags([Flag("format", possible_values=["json", "xml"]), Flag("verbose")]), flags=Flags([
Flag("format", possible_values=["json", "xml"]),
Flag("verbose")
]),
) )
) )
def process_handler(response: Response): def process_handler(response: Response):
# Проверяем статус валидации флагов print(f"Status: {response.status}")
print(f"Status: {response.status.value}")
# Работаем с флагами
format_flag = response.input_flags.get_flag_by_name("format") format_flag = response.input_flags.get_flag_by_name("format")
verbose_flag = response.input_flags.get_flag_by_name("verbose") verbose_flag = response.input_flags.get_flag_by_name("verbose")
@@ -27,11 +29,10 @@ def process_handler(response: Response):
if verbose_flag: if verbose_flag:
print("Verbose mode enabled") print("Verbose mode enabled")
# Проверяем валидность флагов
if response.status == ResponseStatus.ALL_FLAGS_VALID: if response.status == ResponseStatus.ALL_FLAGS_VALID:
print("All flags are valid, proceeding...") print("All flags are valid, proceeding...")
elif response.status == ResponseStatus.INVALID_VALUE_FLAGS: elif response.status == ResponseStatus.INVALID_VALUE_FLAGS:
print("Warning: Some flags have invalid values") print("Warning: Some flags have invalid values")
for flag in response.input_flags: for flag in response.input_flags:
if flag.status and flag.status.name == "INVALID": if flag.status == ValidationStatus.INVALID:
print(f" Invalid flag: {flag.string_entity} = {flag.input_value}") print(f" Invalid flag: {flag.string_entity} = {flag.input_value}")
@@ -1,39 +0,0 @@
import re
from argenta.command.flag import Flag, InputFlag, PossibleValues, ValidationStatus
# Создаём различные типы флагов
verbose_flag = Flag("verbose", possible_values=PossibleValues.NEITHER)
output_flag = Flag("output", possible_values=PossibleValues.ALL)
level_flag = Flag("level", possible_values=["1", "2", "3"])
pattern_flag = Flag("pattern", possible_values=re.compile(r"^[a-zA-Z]+$"))
# Создаём входные флаги с различными статусами
input_flags = [
# Валидные флаги
InputFlag("verbose", input_value=None, status=ValidationStatus.VALID),
InputFlag("output", input_value="result.txt", status=ValidationStatus.VALID),
InputFlag("level", input_value="2", status=ValidationStatus.VALID),
InputFlag("pattern", input_value="onlyletters", status=ValidationStatus.VALID),
# Невалидные флаги
InputFlag("verbose", input_value="true", status=ValidationStatus.INVALID),
InputFlag("level", input_value="4", status=ValidationStatus.INVALID),
InputFlag("pattern", input_value="123", status=ValidationStatus.INVALID),
# Неопределённые флаги
InputFlag("unknown", input_value="value", status=ValidationStatus.UNDEFINED),
]
# Обрабатываем все флаги
valid_count = invalid_count = undefined_count = 0
for flag in input_flags:
if flag.status == ValidationStatus.VALID:
valid_count += 1
elif flag.status == ValidationStatus.INVALID:
invalid_count += 1
elif flag.status == ValidationStatus.UNDEFINED:
undefined_count += 1
print(f"Валидных флагов: {valid_count}")
print(f"Невалидных флагов: {invalid_count}")
print(f"Неопределённых флагов: {undefined_count}")
@@ -1,18 +0,0 @@
from argenta import InputFlag, ValidationStatus
# Создание входных флагов с различными статусами
valid_flag = InputFlag(
"output", input_value="/path/to/file.txt", status=ValidationStatus.VALID
)
invalid_flag = InputFlag(
"count", input_value="not-a-number", status=ValidationStatus.INVALID
)
undefined_flag = InputFlag(
"experimental", input_value="test", status=ValidationStatus.UNDEFINED
)
flags = [valid_flag, invalid_flag, undefined_flag]
for flag in flags:
print(f"{flag.string_entity}: {flag.status.value}")
@@ -1,15 +0,0 @@
from argenta.command.flag import Flag, InputFlag, PossibleValues, ValidationStatus
# Создание флага без значения
help_flag = Flag("help", possible_values=PossibleValues.NEITHER)
# Создание некорректного входного флага (передано значение, когда не должно быть)
invalid_input = InputFlag("help", input_value="please", status=ValidationStatus.INVALID)
print(f"Флаг: {invalid_input.string_entity}")
print(f"Значение: {invalid_input.input_value}")
print(f"Статус: {invalid_input.status}") # Выведет: INVALID
# Также невалидным будет флаг с недопустимым значением из списка
mode_flag = Flag("mode", possible_values=["fast", "slow"])
invalid_mode = InputFlag("mode", input_value="medium", status=ValidationStatus.INVALID)
@@ -1,35 +0,0 @@
from argenta import InputFlag, ValidationStatus
def process_input_flag(input_flag: InputFlag) -> None:
"""Обрабатывает входной флаг в зависимости от его статуса валидации"""
if input_flag.status == ValidationStatus.VALID:
print(f"✓ Обрабатываем валидный флаг: {input_flag.string_entity}")
# Выполняем основную логику
execute_flag_logic(input_flag)
elif input_flag.status == ValidationStatus.INVALID:
print(f"✗ Ошибка валидации флага: {input_flag.string_entity}")
# Записываем ошибку и прекращаем выполнение
log_validation_error(input_flag)
elif input_flag.status == ValidationStatus.UNDEFINED:
print(f"? Неопределённый статус флага: {input_flag.string_entity}")
# Пытаемся провести валидацию или пропускаем
attempt_revalidation(input_flag)
def execute_flag_logic(flag: InputFlag) -> None:
"""Выполняет логику для валидного флага"""
pass
def log_validation_error(flag: InputFlag) -> None:
"""Записывает ошибку валидации в лог"""
pass
def attempt_revalidation(flag: InputFlag) -> None:
"""Пытается повторно провести валидацию"""
pass
@@ -1,15 +0,0 @@
from argenta import InputFlag, ValidationStatus
# Создание входного флага без определения статуса
undefined_input = InputFlag(
"unknown-flag", input_value="some-value", status=ValidationStatus.UNDEFINED
)
print(f"Флаг: {undefined_input.string_entity}")
print(f"Значение: {undefined_input.input_value}")
print(f"Статус: {undefined_input.status.value}") # Выведет: UNDEFINED
# Или флаг, для которого валидация ещё не проводилась
pending_input = InputFlag(
"pending", input_value=None, status=ValidationStatus.UNDEFINED
)
@@ -1,13 +0,0 @@
from argenta.command.flag import Flag, InputFlag, ValidationStatus
# Создание флага, который принимает только определённые значения
log_level_flag = Flag(
"log-level", possible_values=["debug", "info", "warning", "error"]
)
# Создание корректного входного флага
valid_input = InputFlag("log-level", input_value="debug", status=ValidationStatus.VALID)
print(f"Флаг: {valid_input.string_entity}")
print(f"Значение: {valid_input.input_value}")
print(f"Статус: {valid_input.status}") # Выведет: VALID
+11 -9
View File
@@ -3,18 +3,20 @@
DataBridge DataBridge
========== ==========
`DataBridge` — это сущность, предоставляющая временное хранилище данных, которое существует в рамках одной сессии приложения (от запуска до выхода). Она предназначена для обмена данными между вызовами разных команд. ``DataBridge`` — это сущность, предоставляющая временное хранилище данных, которое существует в рамках одной сессии приложения (от запуска до выхода). Она предназначена для обмена данными между обработчиками.
Основной способ получения доступа к `DataBridge` — через систему внедрения зависимостей (DI). Основной способ получения доступа к ``DataBridge`` — через ``di``.
.. code-block:: python .. code-block:: python
:linenos: :linenos:
from argenta.di import FromDishka from argenta.di import FromDishka
from argenta import DataBridge, Response from argenta import DataBridge, Response
# ... setting up router and other
def my_handler(response: Response, data_bridge: FromDishka[DataBridge]): def my_handler(response: Response, data_bridge: FromDishka[DataBridge]):
# ... ваш код # ... your code
**Практический пример: Аутентификация** **Практический пример: Аутентификация**
@@ -26,9 +28,9 @@ DataBridge
**Как это работает:** **Как это работает:**
1. При вызове обработчика `dishka` автоматически внедряет экземпляр `DataBridge`. 1. При вызове обработчика ``dishka`` автоматически внедряет экземпляр ``DataBridge``.
2. Команда ``login --username <имя>`` вызывает `login_handler`, который через внедрённый `data_bridge` сохраняет токен. 2. Команда ``login --username <имя>`` вызывает ``login_handler``, который через внедрённый ``data_bridge`` сохраняет токен.
3. Команда `get-profile` вызывает `get_profile_handler`, который так же получает `data_bridge` и извлекает из него токен. 3. Команда ``get-profile`` вызывает ``get_profile_handler``, который так же получает ``data_bridge`` и извлекает из него токен.
API класса API класса
----------- -----------
@@ -37,7 +39,7 @@ API класса
.. py:method:: __init__(self, initial_data: dict | None = None) .. py:method:: __init__(self, initial_data: dict | None = None)
Инициализирует хранилище. При использовании через DI вызывается автоматически. Инициализирует хранилище. При использовании через ``di`` вызывается автоматически.
.. py:method:: update(self, data: dict) -> None .. py:method:: update(self, data: dict) -> None
@@ -49,11 +51,11 @@ API класса
.. py:method:: get_by_key(self, key: str) -> Any .. py:method:: get_by_key(self, key: str) -> Any
Возвращает значение по ключу или `None`, если ключ не найден. Возвращает значение по ключу или ``None``, если ключ не найден.
.. py:method:: delete_by_key(self, key: str) -> None .. py:method:: delete_by_key(self, key: str) -> None
Удаляет значение по ключу. Вызывает `KeyError`, если ключ не найден. Удаляет значение по ключу. Вызывает ``KeyError``, если ключ не найден.
.. py:method:: clear_all(self) -> None .. py:method:: clear_all(self) -> None
+8 -54
View File
@@ -3,9 +3,7 @@
Flags Flags
====== ======
`Flags` — это коллекция флагов команды. Её основная задача — группировать и управлять набором флагов, зарегистрированных для конкретной команды. `Flags` служит контейнером, который позволяет удобно добавлять, извлекать, итерировать флаги и проверять их наличие. ``Flags`` — это коллекция флагов команды. Её основная задача — группировать и управлять набором флагов, зарегистрированных для конкретной команды. ``Flags`` служит контейнером, который позволяет удобно добавлять, извлекать, итерировать флаги и проверять их наличие.
`Flags` наследуется от базового класса `BaseFlags` и специализируется на работе с объектами типа `Flag`. Этот класс используется при создании команд с несколькими флагами и предоставляет интерфейс для управления ими.
.. seealso:: .. seealso::
@@ -27,14 +25,14 @@ Flags
Создаёт новую коллекцию флагов. Создаёт новую коллекцию флагов.
* ``flags``: Необязательный список флагов типа `Flag` для инициализации коллекции. Если не указан, создаётся пустая коллекция. * ``flags``: Необязательный список флагов типа ``Flag`` для инициализации коллекции. Если не указан, создаётся пустая коллекция.
**Атрибуты:** **Атрибуты:**
.. py:attribute:: flags .. py:attribute:: flags
:no-index: :no-index:
Список всех зарегистрированных флагов типа `Flag`. Пуст, если флаги не были переданы при инициализации. Список всех зарегистрированных флагов типа ``Flag``.
**Пример использования:** **Пример использования:**
@@ -57,10 +55,10 @@ add_flag
Добавляет флаг в коллекцию. Добавляет флаг в коллекцию.
:param flag: Флаг типа `Flag` для добавления. :param flag: Флаг типа ``Flag`` для добавления.
:return: None. :return: None.
Метод добавляет флаг в конец списка `flags`. Используется для динамического расширения набора флагов. Используется для динамического расширения набора флагов.
**Пример использования:** **Пример использования:**
@@ -80,7 +78,7 @@ add_flags
Добавляет в коллекцию список флагов. Добавляет в коллекцию список флагов.
:param flags: Список флагов типа `Flag` для добавления. :param flags: Список флагов типа ``Flag`` для добавления.
:return: None. :return: None.
Метод расширяет коллекцию, добавляя в неё все флаги из переданного списка. Эффективен для пакетного добавления. Метод расширяет коллекцию, добавляя в неё все флаги из переданного списка. Эффективен для пакетного добавления.
@@ -104,56 +102,12 @@ get_flag_by_name
Возвращает флаг по имени. Возвращает флаг по имени.
:param name: Имя искомого флага. :param name: Имя искомого флага.
:return: Объект `Flag` или `None`, если флаг не найден. :return: Объект ``Flag`` или ``None``, если флаг не найден.
Метод выполняет поиск по списку `flags` и возвращает первый флаг с соответствующим именем. Если флаг не найден, возвращается `None`. Метод возвращает флаг с соответствующим именем. Если флаг не найден, возвращается ``None``.
**Пример использования:** **Пример использования:**
.. literalinclude:: ../../../code_snippets/flags/snippet4.py .. literalinclude:: ../../../code_snippets/flags/snippet4.py
:linenos: :linenos:
:language: python :language: python
-----
Магические методы
-----------------
__iter__
~~~~~~~~
.. code-block:: python
:linenos:
__iter__(self) -> Iterator[Flag]
Делает коллекцию итерируемой для использования в циклах.
:return: Итератор по списку флагов.
**Пример использования:**
.. literalinclude:: ../../../code_snippets/flags/snippet5.py
:linenos:
:language: python
-----
__getitem__
~~~~~~~~~~~
.. code-block:: python
:linenos:
__getitem__(self, flag_index: int) -> Flag
Позволяет получать флаг по индексу.
:param flag_index: Индекс флага в списке.
:return: Флаг по указанному индексу.
**Пример использования:**
.. literalinclude:: ../../../code_snippets/flags/snippet6.py
:linenos:
:language: python
+7 -127
View File
@@ -3,9 +3,7 @@
InputFlags InputFlags
========== ==========
`InputFlags` — это коллекция флагов, введённых пользователем. Её основная задача — группировать и управлять набором флагов, переданных вместе с командой. `InputFlags` служит контейнером, который позволяет удобно извлекать, итерировать и проверять наличие флагов, а также работать с их значениями и статусами валидации. ``InputFlags`` — это коллекция флагов, введённых пользователем. Её основная задача — группировать и управлять набором флагов, переданных вместе с командой. ``InputFlags`` служит контейнером, который позволяет удобно извлекать, итерировать и проверять наличие флагов, а также работать с их значениями и статусами валидации.
`InputFlags` наследуется от `BaseFlags` и специализируется на работе с объектами типа `InputFlag`. Этот класс создаётся автоматически при обработке пользовательского ввода и передаётся в обработчики команд через объект `Response`.
.. seealso:: .. seealso::
@@ -29,17 +27,17 @@ InputFlags
Создаёт новую коллекцию введённых флагов. Создаёт новую коллекцию введённых флагов.
* ``flags``: Необязательный список флагов типа `InputFlag` для инициализации коллекции. Если не указан, создаётся пустая коллекция. * ``flags``: Необязательный список флагов типа ``InputFlag`` для инициализации коллекции. Если не указан, создаётся пустая коллекция.
.. warning :: .. warning ::
Экземпляры этого класса обычно не создаются напрямую. Они автоматически формируются системой при обработке пользовательского ввода и доступны через атрибут `input_flags` объекта `Response`. Экземпляры этого класса обычно не создаются напрямую. Они автоматически формируются системой при обработке пользовательского ввода и доступны через атрибут ``input_flags`` объекта ``Response``.
**Атрибуты:** **Атрибуты:**
.. py:attribute:: flags .. py:attribute:: flags
:no-index: :no-index:
Список всех введённых флагов типа `InputFlag`. Пуст, если флаги не были переданы при инициализации или пользователь не ввёл их с командой. Список всех введённых флагов типа ``InputFlag``. Пуст, если флаги не были переданы при инициализации или пользователь не ввёл их с командой.
**Пример использования:** **Пример использования:**
@@ -60,12 +58,12 @@ get_flag_by_name
get_flag_by_name(self, name: str) -> InputFlag | None get_flag_by_name(self, name: str) -> InputFlag | None
Возвращает введённый флаг по имени. Возвращает флаг по имени.
:param name: Имя искомого флага (без префикса). :param name: Имя искомого флага (без префикса).
:return: Объект `InputFlag` или `None`, если флаг не найден. :return: Объект ``InputFlag`` или ``None``, если флаг не найден.
Метод выполняет поиск по списку `flags` и возвращает первый флаг с соответствующим именем (без учёта префикса). Метод возвращает первый флаг с соответствующим именем (без учёта префикса).
**Пример использования:** **Пример использования:**
@@ -124,124 +122,6 @@ add_flags
----- -----
Магические методы
-----------------
__iter__
~~~~~~~~
.. code-block:: python
:linenos:
__iter__(self) -> Iterator[InputFlag]
Делает коллекцию итерируемой для использования в циклах.
:return: Итератор по списку введённых флагов.
Позволяет перебирать все введённые флаги, что полезно для проверки их статусов или пакетной обработки.
**Пример использования:**
.. literalinclude:: ../../../code_snippets/input_flags/snippet5.py
:linenos:
:language: python
-----
__getitem__
~~~~~~~~~~~
.. code-block:: python
:linenos:
__getitem__(self, flag_index: int) -> InputFlag
Позволяет получать введённый флаг по индексу.
:param flag_index: Индекс флага в списке.
:return: Флаг по указанному индексу.
Позволяет обращаться к флагам по их позиции, что может быть полезно для их обработки в определённом порядке.
**Пример использования:**
.. literalinclude:: ../../../code_snippets/input_flags/snippet6.py
:linenos:
:language: python
-----
__bool__
~~~~~~~~
.. code-block:: python
:linenos:
__bool__(self) -> bool
Определяет, содержит ли коллекция флаги.
:return: `True`, если в коллекции есть хотя бы один флаг, иначе `False`.
Позволяет проверять наличие флагов в команде для условной логики.
**Пример использования:**
.. literalinclude:: ../../../code_snippets/input_flags/snippet7.py
:linenos:
:language: python
-----
__eq__
~~~~~~
.. code-block:: python
:linenos:
__eq__(self, other: object) -> bool
Сравнивает две коллекции введённых флагов на равенство.
:param other: Объект для сравнения.
:return: `True`, если коллекции равны, иначе `False`.
:raises NotImplementedError: Если `other` не является экземпляром `InputFlags`.
Две коллекции считаются равными, если они содержат одинаковое количество флагов и все соответствующие флаги равны (сравнение по имени, см. `InputFlag.__eq__`).
**Пример использования:**
.. literalinclude:: ../../../code_snippets/input_flags/snippet8.py
:linenos:
:language: python
-----
__contains__
~~~~~~~~~~~~
.. code-block:: python
:linenos:
__contains__(self, ingressable_item: object) -> bool
Проверяет, содержится ли введённый флаг в коллекции.
:param ingressable_item: Объект `InputFlag` для проверки.
:return: `True`, если флаг найден, иначе `False`.
:raises TypeError: Если `ingressable_item` не является экземпляром `InputFlag`.
Позволяет использовать оператор `in` для проверки наличия флага в коллекции.
**Пример использования:**
.. literalinclude:: ../../../code_snippets/input_flags/snippet9.py
:linenos:
:language: python
-----
Практические примеры Практические примеры
-------------------- --------------------
+9 -40
View File
@@ -3,17 +3,17 @@
ValidationStatus ValidationStatus
================ ================
`ValidationStatus` — это перечисление (`Enum`), которое определяет состояние валидации флага. Его задача — предоставить стандартные константы для отображения результата проверки. `ValidationStatus` используется в атрибуте `status` класса `InputFlag`, чтобы сообщить, прошла ли валидация успешно. ``ValidationStatus`` — это перечисление, которое определяет состояние валидации флага. Его задача — предоставить стандартные константы для отображения результата проверки. ``ValidationStatus`` используется в атрибуте ``status`` класса ``InputFlag``.
`ValidationStatus` наследуется от `Enum` и содержит три значения: `VALID` (корректный флаг), `INVALID` (некорректный) и `UNDEFINED` (незарегистрированный). ``ValidationStatus`` содержит три значения: **VALID** (корректный флаг), **INVALID** (некорректный) и **UNDEFINED** (незарегистрированный).
.. note:: .. note::
Статус валидации устанавливается автоматически при создании экземпляра `InputFlag` на основе правил, заданных в соответствующем `Flag`. Статус валидации устанавливается автоматически при создании экземпляра ``InputFlag`` на основе правил, заданных в соответствующем ``Flag``.
.. seealso:: .. seealso::
Документация по :ref:`InputFlag <root_api_command_input_flag>` — класс введённого флага, использующий `ValidationStatus`. Документация по :ref:`InputFlag <root_api_command_input_flag>` — класс введённого флага, использующий ``ValidationStatus``.
Документация по :ref:`Flag <root_api_command_flag>` — класс флага с правилами валидации. Документация по :ref:`Flag <root_api_command_flag>` — класс флага с правилами валидации.
@@ -21,9 +21,6 @@ ValidationStatus
----- -----
Значения enum
-------------
VALID VALID
~~~~~ ~~~~~
@@ -34,21 +31,15 @@ VALID
Указывает, что флаг и его значение **прошли** валидацию. Указывает, что флаг и его значение **прошли** валидацию.
Флаги с этим статусом соответствуют правилам, заданным в `possible_values` соответствующего `Flag`. Их можно безопасно использовать в логике приложения без дополнительных проверок. Флаги с этим статусом соответствуют правилам, заданным в ``possible_values`` соответствующего ``Flag``. Их можно безопасно использовать в логике приложения без дополнительных проверок.
**Условия получения статуса** ``VALID``: **Условия получения статуса** ``VALID``:
* Флаг с `PossibleValues.NEITHER` передан без значения. * Флаг с ``PossibleValues.NEITHER`` передан без значения.
* Флаг с `PossibleValues.ALL` передан с любым значением или без него. * Флаг с ``PossibleValues.ALL`` передан с любым значением или без него.
* Значение флага входит в список разрешённых. * Значение флага входит в список разрешённых.
* Значение флага соответствует регулярному выражению. * Значение флага соответствует регулярному выражению.
**Пример использования:**
.. literalinclude:: ../../../code_snippets/validation_status/valid.py
:linenos:
:language: python
----- -----
INVALID INVALID
@@ -61,21 +52,15 @@ INVALID
Указывает, что флаг или его значение **не прошли** валидацию. Указывает, что флаг или его значение **не прошли** валидацию.
Флаги с этим статусом нарушают правила, заданные в `possible_values` соответствующего `Flag`. Их следует обрабатывать как ошибочные. Флаги с этим статусом нарушают правила, заданные в ``possible_values`` соответствующего ``Flag``. Их следует обрабатывать как ошибочные.
**Условия получения статуса** ``INVALID``: **Условия получения статуса** ``INVALID``:
* Флаг с `PossibleValues.NEITHER` передан со значением. * Флаг с ``PossibleValues.NEITHER`` передан со значением.
* Значение флага не входит в список разрешённых. * Значение флага не входит в список разрешённых.
* Значение флага не соответствует регулярному выражению. * Значение флага не соответствует регулярному выражению.
* Флаг требует значение, но передан без него. * Флаг требует значение, но передан без него.
**Пример использования:**
.. literalinclude:: ../../../code_snippets/validation_status/invalid.py
:linenos:
:language: python
----- -----
UNDEFINED UNDEFINED
@@ -91,19 +76,3 @@ UNDEFINED
**Условия получения статуса** ``UNDEFINED``: **Условия получения статуса** ``UNDEFINED``:
* Введённый флаг не найден среди зарегистрированных для данной команды. * Введённый флаг не найден среди зарегистрированных для данной команды.
-----
Практические примеры
--------------------
Комплексный пример валидации
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Пример демонстрирует использование всех статусов в реальном сценарии.
.. literalinclude:: ../../../code_snippets/validation_status/comprehensive.py
:linenos:
:language: python
+8 -12
View File
@@ -3,7 +3,7 @@
Response Response
======== ========
`Response` — это объект, который передаётся в обработчик команды. Он создаётся автоматически при обработке пользовательского ввода и содержит статус валидации, введённые флаги. ``Response`` — это объект, который передаётся в обработчик команды. Он создаётся автоматически при обработке пользовательского ввода и содержит статус валидации, введённые флаги.
.. seealso:: .. seealso::
@@ -23,15 +23,14 @@ Response
:linenos: :linenos:
__init__( __init__(
self, self, status: ResponseStatus,
status: ResponseStatus,
input_flags: InputFlags = EMPTY_INPUT_FLAGS, input_flags: InputFlags = EMPTY_INPUT_FLAGS,
) )
Создаёт новый объект ответа. Создаёт новый объект ответа.
* ``status``: Общий статус валидации флагов из перечисления `ResponseStatus`. * ``status``: Общий статус валидации флагов из перечисления ``ResponseStatus``.
* ``input_flags``: Коллекция введённых флагов (`InputFlags`). По умолчанию — пустая. * ``input_flags``: Коллекция введённых флагов (``InputFlags``). По умолчанию — пустая.
.. warning :: .. warning ::
Экземпляры этого класса не предназначены для прямого создания. Они автоматически формируются системой и передаются в обработчик команды в качестве первого обязательного аргумента. Экземпляры этого класса не предназначены для прямого создания. Они автоматически формируются системой и передаются в обработчик команды в качестве первого обязательного аргумента.
@@ -41,12 +40,12 @@ Response
.. py:attribute:: status .. py:attribute:: status
:no-index: :no-index:
Общий статус валидации всех флагов команды (`ResponseStatus`). Указывает, были ли среди введённых флагов некорректные или незарегистрированные. Общий статус валидации всех флагов команды (``ResponseStatus``). Указывает, были ли среди введённых флагов некорректные или незарегистрированные.
.. py:attribute:: input_flags .. py:attribute:: input_flags
:no-index: :no-index:
Коллекция всех флагов, переданных с командой (`InputFlags`). Содержит все обработанные флаги с их значениями и статусами валидации. Коллекция всех флагов, переданных с командой (``InputFlags``). Содержит все обработанные флаги с их значениями и статусами валидации.
**Пример использования:** **Пример использования:**
@@ -59,7 +58,7 @@ Response
Работа с флагами Работа с флагами
---------------- ----------------
`Response` предоставляет доступ к введённым флагам через атрибут `input_flags`. Вы можете проверять их наличие, получать значения и статусы валидации. ``Response`` предоставляет доступ к введённым флагам через атрибут ``input_flags``. Вы можете проверять их наличие, получать значения и статусы валидации.
**Пример работы с флагами:** **Пример работы с флагами:**
@@ -74,10 +73,7 @@ Response
ResponseStatus ResponseStatus
-------------- --------------
`ResponseStatus` — это перечисление (`Enum`), которое определяет общий статус валидации всех флагов команды. Используется в атрибуте `status` объекта `Response`. ``ResponseStatus`` — это перечисление, которое определяет общий статус валидации всех флагов команды. Используется в атрибуте ``status`` объекта ``Response``.
Значения enum
~~~~~~~~~~~~~
ALL_FLAGS_VALID ALL_FLAGS_VALID
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
+5 -13
View File
@@ -1,18 +1,10 @@
from argenta import Router, Response, Command from argenta import Command, Response, Router
from argenta.command import Flags, Flag from argenta.command import Flag, Flags
work_router: Router = Router(title="Base points:", disable_redirect_stdout=True) work_router: Router = Router(title="Base points:", disable_redirect_stdout=True)
@work_router.command(Command @work_router.command(Command("hello", flags=Flags(Flag("test")), description="Hello, world!"))
(
'hello',
flags=Flags(
Flag('test')
),
description="Hello, world!"
)
)
def command_help(response: Response): def command_help(response: Response):
c = input("Enter your name: ") c = input("Enter your name: ")
print(f"Hello, {c}!") print(f"Hello, {c}!")
+1 -1
View File
@@ -45,7 +45,7 @@ exclude = [
".__pycache__", ".__pycache__",
"tests" "tests"
] ]
line-length=100 line-length=90
[tool.pyright] [tool.pyright]
typeCheckingMode = "strict" typeCheckingMode = "strict"
+3
View File
@@ -32,6 +32,9 @@ class BaseFlags(Generic[FlagType]):
:return: None :return: None
""" """
self.flags.extend(flags) self.flags.extend(flags)
def __len__(self) -> int:
return len(self.flags)
def __iter__(self) -> Iterator[FlagType]: def __iter__(self) -> Iterator[FlagType]:
return iter(self.flags) return iter(self.flags)