mirror of
https://github.com/koloideal/Argenta.git
synced 2026-06-10 18:15:28 +03:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d30515c1a2 | |||
| 5a6fc1d8ca | |||
| e5d6ead38e | |||
| b61c151e1c | |||
| a57ce490c1 | |||
| edbd45f0bf |
@@ -20,7 +20,7 @@ poetry add argenta
|
|||||||
|
|
||||||
# Быстрый старт
|
# Быстрый старт
|
||||||
|
|
||||||
Пример простейшей оболочки с командой без флагов
|
Пример простейшей оболочки с командой без зарегистрированных флагов
|
||||||
```python
|
```python
|
||||||
# routers.py
|
# routers.py
|
||||||
from argenta.router import Router
|
from argenta.router import Router
|
||||||
@@ -56,18 +56,16 @@ if __name__ == '__main__':
|
|||||||
import re
|
import re
|
||||||
from argenta.router import Router
|
from argenta.router import Router
|
||||||
from argenta.command import Command
|
from argenta.command import Command
|
||||||
from argenta.command.params.flag import FlagsGroup, Flag
|
from argenta.command.flag import FlagsGroup, Flag
|
||||||
|
|
||||||
router = Router()
|
router = Router()
|
||||||
|
|
||||||
list_of_flags = [
|
registered_flags = FlagsGroup([
|
||||||
Flag(flag_name='host',
|
Flag(flag_name='host',
|
||||||
flag_prefix='--',
|
flag_prefix='--',
|
||||||
possible_flag_values=re.compile(r'^192.168.\d{1,3}.\d{1,3}$')),
|
possible_flag_values=re.compile(r'^192.168.\d{1,3}.\d{1,3}$')),
|
||||||
Flag(flag_name='port',
|
Flag('port', '---', re.compile(r'^[0-9]{1,4}$'))
|
||||||
flag_prefix='---',
|
])
|
||||||
possible_flag_values=re.compile(r'^[0-9]{1,4}$'))
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
@router.command(Command("hello"))
|
@router.command(Command("hello"))
|
||||||
@@ -77,10 +75,10 @@ def handler():
|
|||||||
|
|
||||||
@router.command(Command(trigger="ssh",
|
@router.command(Command(trigger="ssh",
|
||||||
description='connect via ssh',
|
description='connect via ssh',
|
||||||
flags=FlagsGroup(list_of_flags)))
|
flags=registered_flags))
|
||||||
def handler_with_flags(flags: dict):
|
def handler_with_flags(flags: dict):
|
||||||
for flag in flags:
|
for flag in flags:
|
||||||
print(f'Flag name: {flag['name']}\n
|
print(f'Flag name: {flag['name']}\n'
|
||||||
f'Flag value: {flag['value']}')
|
f'Flag value: {flag['value']}')
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -129,52 +127,57 @@ App(prompt: str = 'Enter a command',
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**App().**`start_polling() -> None`
|
#### **.start_polling() -> `None`**
|
||||||
|
|
||||||
*method mean* **::** запускает жизненный цикл приложения
|
*method mean* **::** запускает цикл обработки ввода
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**App().**`include_router(router: Router) -> None`
|
#### **.include_router(router: Router) -> `None`**
|
||||||
|
|
||||||
*param* `router: Router` **::** регистрируемый роутер
|
*param* `router: Router` **::** регистрируемый роутер
|
||||||
|
*required* **::** True
|
||||||
|
|
||||||
*method mean* **::** регистрирует роутер в приложении
|
*method mean* **::** регистрирует роутер в оболочке
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**App().**`set_initial_message(message: str) -> None`
|
#### **.set_initial_message(message: str) -> `None`**
|
||||||
|
|
||||||
*param* `message: str` **::** устанавливаемое приветственное сообщение
|
*param* `message: str` **::** устанавливаемое приветственное сообщение
|
||||||
|
*required* **::** True
|
||||||
*example* **::** `"Hello, I'm a example app"`
|
*example* **::** `"Hello, I'm a example app"`
|
||||||
|
|
||||||
*method mean* **::** устанавливает сообщение, которое будет отображено при запуске программы
|
*method mean* **::** устанавливает сообщение, которое будет отображено при запуске программы
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**App().**`set_farewell_message(message: str) -> None`
|
#### **.set_farewell_message(message: str) -> `None`**
|
||||||
|
|
||||||
*param* `message: str` **::** устанавливаемое сообщение при выходе
|
*param* `message: str` **::** устанавливаемое сообщение при выходе
|
||||||
|
*required* **::** True
|
||||||
*example* **::** `"GoodBye !"`
|
*example* **::** `"GoodBye !"`
|
||||||
|
|
||||||
*method mean* **::** устанавливает сообщение, которое будет отображено при выходе
|
*method mean* **::** устанавливает сообщение, которое будет отображено при выходе
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**App().**`set_description_message_pattern(pattern: str) -> None`
|
#### **.set_description_message_pattern(pattern: str) -> `None`**
|
||||||
|
|
||||||
*param* `pattern: str` **::** паттерн описания команды при её выводе в консоль
|
*param* `pattern: str` **::** паттерн описания команды при её выводе в консоль
|
||||||
|
*required* **::** True
|
||||||
*example* **::** `"[{command}] *=*=* {description}"`
|
*example* **::** `"[{command}] *=*=* {description}"`
|
||||||
|
|
||||||
*method mean* **::** устанавливает паттерн описания команд, который будет использован
|
*method mean* **::** устанавливает паттерн описания команд, который будет использован
|
||||||
при выводе в консоль
|
при выводе в консоль
|
||||||
|
|
||||||
---
|
---
|
||||||
|
<a name="custom_handler"></a>
|
||||||
**App().**`set_repeated_input_flags_handler(handler: Callable[[str], None]) -> None`
|
#### **.set_repeated_input_flags_handler(handler: Callable[[str], None]) -> `None`**
|
||||||
|
|
||||||
*param* `handler: Callable[[str], None]` **::** функция или лямбда функция, которой будет передано управление при
|
*param* `handler: Callable[[str], None]` **::** функция или лямбда функция, которой будет передано управление при
|
||||||
вводе юзером повторяющихся флагов
|
вводе юзером повторяющихся флагов
|
||||||
|
*required* **::** True
|
||||||
*example* **::** `lambda raw_command: print_func(f'Repeated input flags: "{raw_command}"')`
|
*example* **::** `lambda raw_command: print_func(f'Repeated input flags: "{raw_command}"')`
|
||||||
|
|
||||||
*method mean* **::** устанавливает функцию, которой будет передано управление при
|
*method mean* **::** устанавливает функцию, которой будет передано управление при
|
||||||
@@ -182,10 +185,11 @@ App(prompt: str = 'Enter a command',
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**App().**`set_invalid_input_flags_handler(self, handler: Callable[[str], None]) -> None`
|
#### **.set_invalid_input_flags_handler(self, handler: Callable[[str], None]) -> `None`**
|
||||||
|
|
||||||
*param* `handler: Callable[[str], None]` **::** функция или лямбда функция, которой будет передано управление при
|
*param* `handler: Callable[[str], None]` **::** функция или лямбда функция, которой будет передано управление при
|
||||||
вводе юзером команды с некорректным синтаксисом флагов
|
вводе юзером команды с некорректным синтаксисом флагов
|
||||||
|
*required* **::** True
|
||||||
*example* **::** `lambda raw_command: print_func(f'Incorrect flag syntax: "{raw_command}"')`
|
*example* **::** `lambda raw_command: print_func(f'Incorrect flag syntax: "{raw_command}"')`
|
||||||
|
|
||||||
*method mean* **::** устанавливает функцию, которой будет передано управление при
|
*method mean* **::** устанавливает функцию, которой будет передано управление при
|
||||||
@@ -193,10 +197,11 @@ App(prompt: str = 'Enter a command',
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**App().**`set_unknown_command_handler(self, handler: Callable[[str], None]) -> None`
|
#### **.set_unknown_command_handler(self, handler: Callable[[str], None]) -> `None`**
|
||||||
|
|
||||||
*param* `handler: Callable[[str], None]` **::** функция или лямбда функция, которой будет передано управление при
|
*param* `handler: Callable[[str], None]` **::** функция или лямбда функция, которой будет передано управление при
|
||||||
вводе юзером неизвестной команды
|
вводе юзером неизвестной команды
|
||||||
|
*required* **::** True
|
||||||
*example* **::** `lambda command: print_func(f"Unknown command: {command.get_string_entity()}")`
|
*example* **::** `lambda command: print_func(f"Unknown command: {command.get_string_entity()}")`
|
||||||
|
|
||||||
*method mean* **::** устанавливает функцию, которой будет передано управление при
|
*method mean* **::** устанавливает функцию, которой будет передано управление при
|
||||||
@@ -204,10 +209,11 @@ App(prompt: str = 'Enter a command',
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**App().**`set_empty_command_handler(self, handler: Callable[[str], None]) -> None`
|
#### **.set_empty_command_handler(self, handler: Callable[[str], None]) -> `None`**
|
||||||
|
|
||||||
*param* `handler: Callable[[str], None]` **::** функция или лямбда функция, которой будет передано управление при
|
*param* `handler: Callable[[str], None]` **::** функция или лямбда функция, которой будет передано управление при
|
||||||
вводе юзером пустой команды
|
вводе юзером пустой команды
|
||||||
|
*required* **::** True
|
||||||
*example* **::** `lambda: print_func(f'Empty input command')`
|
*example* **::** `lambda: print_func(f'Empty input command')`
|
||||||
|
|
||||||
*method mean* **::** устанавливает функцию, которой будет передано управление при
|
*method mean* **::** устанавливает функцию, которой будет передано управление при
|
||||||
@@ -219,10 +225,10 @@ App(prompt: str = 'Enter a command',
|
|||||||
|
|
||||||
- В устанавливаемом паттерне сообщения описания команды необходимы быть два ключевых слова:
|
- В устанавливаемом паттерне сообщения описания команды необходимы быть два ключевых слова:
|
||||||
`command` и `description`, каждое из которых должно быть заключено в фигурные скобки, после обработки
|
`command` и `description`, каждое из которых должно быть заключено в фигурные скобки, после обработки
|
||||||
паттерна на места этих ключевых слов будут подставлены соответствующие значения команды, при отсутствии
|
паттерна на места этих ключевых слов будут подставлены соответствующие атрибуты команды, при отсутствии
|
||||||
этих двух ключевых слов будет вызвано исключение `InvalidDescriptionMessagePatternException`
|
этих двух ключевых слов будет вызвано исключение `InvalidDescriptionMessagePatternException`
|
||||||
|
|
||||||
- Команды приложения не должны повторяться, при значении атрибута `ignore_command_register` равным `True`
|
- Команды оболочки не должны повторяться, при значении атрибута `ignore_command_register` равным `True`
|
||||||
допускается создание обработчиков для разных регистров одинаковых символов в команде, для примера `u` и `U`,
|
допускается создание обработчиков для разных регистров одинаковых символов в команде, для примера `u` и `U`,
|
||||||
при значении атрибута `ignore_command_register` класса `App` равным `False` тот же пример вызывает исключение
|
при значении атрибута `ignore_command_register` класса `App` равным `False` тот же пример вызывает исключение
|
||||||
`RepeatedCommandInDifferentRoutersException`. Исключение вызывается только при наличии пересекающихся команд
|
`RepeatedCommandInDifferentRoutersException`. Исключение вызывается только при наличии пересекающихся команд
|
||||||
@@ -248,7 +254,7 @@ App(prompt: str = 'Enter a command',
|
|||||||
### Конструктор
|
### Конструктор
|
||||||
```python
|
```python
|
||||||
Router(title: str = 'Commands group title:',
|
Router(title: str = 'Commands group title:',
|
||||||
name: str = 'subordinate')
|
name: str = 'Default')
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@@ -264,29 +270,30 @@ Router(title: str = 'Commands group title:',
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**`@`Router().**`command(command: Command)`
|
#### **command(command: Command)**
|
||||||
|
|
||||||
*param* `command: Command` **::** экземпляр класса `Command`, который определяет строковый триггер команды,
|
*param* `command: Command` **::** экземпляр класса `Command`, который определяет строковый триггер команды,
|
||||||
допустимые флаги команды и другое
|
допустимые флаги команды и другое
|
||||||
|
*required* **::** True
|
||||||
*example* **::** `Command(command='ssh', description='connect via ssh')`
|
*example* **::** `Command(command='ssh', description='connect via ssh')`
|
||||||
|
|
||||||
*method mean* **::** декоратор, который регистрирует функцию как обработчик команды
|
*method mean* **::** декоратор, который регистрирует функцию как обработчик команды
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Router().**`get_name() -> str`
|
#### **.get_name() -> `str`**
|
||||||
|
|
||||||
*method mean* **::** возвращает установленное название роутера
|
*method mean* **::** возвращает установленное название роутера
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Router().**`get_title() -> str`
|
#### **.get_title() -> `str`**
|
||||||
|
|
||||||
*method mean* **::** возвращает установленный заголовок группы команд данного роутера
|
*method mean* **::** возвращает установленный заголовок группы команд данного роутера
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Router().**`get_all_commands() -> list[str]`
|
#### **.get_all_commands() -> `list[str]`**
|
||||||
|
|
||||||
*method mean* **::** возвращает все зарегистрированные команды для данного роутера
|
*method mean* **::** возвращает все зарегистрированные команды для данного роутера
|
||||||
|
|
||||||
@@ -298,6 +305,7 @@ Router(title: str = 'Commands group title:',
|
|||||||
- `TooManyTransferredArgsException` - Слишком много зарегистрированных аргументов у обработчика команды
|
- `TooManyTransferredArgsException` - Слишком много зарегистрированных аргументов у обработчика команды
|
||||||
- `RequiredArgumentNotPassedException` - Не зарегистрирован обязательный аргумент у обработчика команды(аргумент, через который будут переданы флаги введённой команды)
|
- `RequiredArgumentNotPassedException` - Не зарегистрирован обязательный аргумент у обработчика команды(аргумент, через который будут переданы флаги введённой команды)
|
||||||
- `IncorrectNumberOfHandlerArgsException` - У обработчика нестандартного поведения зарегистрировано неверное количество аргументов(в большинстве случаев у него должен быть один аргумент)
|
- `IncorrectNumberOfHandlerArgsException` - У обработчика нестандартного поведения зарегистрировано неверное количество аргументов(в большинстве случаев у него должен быть один аргумент)
|
||||||
|
- `TriggerCannotContainSpacesException` - У регистрируемой команды в триггере содержатся пробелы
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -319,19 +327,19 @@ Command(trigger: str,
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Command().**`get_trigger() -> str`
|
#### **.get_trigger() -> `str`**
|
||||||
|
|
||||||
*method mean* **::** возвращает строковый триггер экземпляра
|
*method mean* **::** возвращает строковый триггер экземпляра
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Command().**`get_description() -> str`
|
#### **.get_description() -> `str`**
|
||||||
|
|
||||||
*method mean* **::** возвращает описание команды
|
*method mean* **::** возвращает описание команды
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Command().**`get_registered_flags() -> FlagsGroup | None`
|
#### **.get_registered_flags() -> `FlagsGroup | None`**
|
||||||
|
|
||||||
*method mean* **::** возвращает зарегистрированные флаги экземпляра
|
*method mean* **::** возвращает зарегистрированные флаги экземпляра
|
||||||
|
|
||||||
@@ -345,20 +353,20 @@ Command(trigger: str,
|
|||||||
**Примечание**
|
**Примечание**
|
||||||
Все вышеуказанные исключения класса `Command` вызываются в рантайме запущенным экземпляром класса
|
Все вышеуказанные исключения класса `Command` вызываются в рантайме запущенным экземпляром класса
|
||||||
`App`, а также по дефолту обрабатываются, при желании можно задать пользовательские
|
`App`, а также по дефолту обрабатываются, при желании можно задать пользовательские
|
||||||
обработчики для этих исключений ([подробнее см.](#methods-))
|
обработчики для этих исключений ([подробнее см.](#custom_handler))
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## *class* :: `Flag`
|
## *class* :: `Flag`
|
||||||
Класс, экземпляры которого в большинстве случаев должны передаваться при создании
|
Класс, экземпляры которого в большинстве случаев передаются при создании
|
||||||
экземпляра класса `Command` для регистрации допустимого флага при вводе юзером команды
|
экземпляра класса `Command` для регистрации допустимого флага при вводе юзером команды
|
||||||
|
|
||||||
### Конструктор
|
### Конструктор
|
||||||
```python
|
```python
|
||||||
Flag(flag_name: str,
|
Flag(flag_name: str,
|
||||||
flag_prefix: Literal['-', '--', '---'] = '-',
|
flag_prefix: typing.Literal['-', '--', '---'] = '-',
|
||||||
ignore_flag_value_register: bool = False,
|
ignore_flag_value_register: bool = False,
|
||||||
possible_flag_values: list[str] | Pattern[str] = False)
|
possible_flag_values: list[str] | typing.Pattern[str] = False)
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -377,19 +385,19 @@ Flag(flag_name: str,
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Flag().**`get_sring_entity() -> str`
|
#### **.get_string_entity() -> `str`**
|
||||||
|
|
||||||
*method mean* **::** возвращает строковое представление флага(префикс + имя)
|
*method mean* **::** возвращает строковое представление флага(префикс + имя)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Flag().**`get_flag_name() -> str`
|
#### **.get_flag_name() -> `str`**
|
||||||
|
|
||||||
*method mean* **::** возвращает имя флага
|
*method mean* **::** возвращает имя флага
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Flag().**`get_flag_prefix() -> str`
|
#### **.get_flag_prefix() -> `str`**
|
||||||
|
|
||||||
*method mean* **::** возвращает префикс флага
|
*method mean* **::** возвращает префикс флага
|
||||||
|
|
||||||
@@ -417,7 +425,7 @@ FlagsGroup(flags: list[Flag] = None)
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**FlagsGroup().**`get_flags() -> list[Flag]`
|
#### **.get_flags() -> `list[Flag]`**
|
||||||
|
|
||||||
*method mean* **::** возвращает зарегистрированные флаги
|
*method mean* **::** возвращает зарегистрированные флаги
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from pprint import pprint
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
from inspect import getfullargspec
|
from inspect import getfullargspec
|
||||||
import re
|
import re
|
||||||
|
|||||||
+13
-11
@@ -1,16 +1,15 @@
|
|||||||
from .params.flag.entity import Flag
|
from argenta.command.flag.entity import Flag
|
||||||
from .params.flag.flags_group.entity import FlagsGroup
|
from argenta.command.flag.flags_group import FlagsGroup
|
||||||
from .exceptions import (UnprocessedInputFlagException,
|
from .exceptions import (UnprocessedInputFlagException,
|
||||||
RepeatedInputFlagsException,
|
RepeatedInputFlagsException,
|
||||||
EmptyInputCommandException)
|
EmptyInputCommandException)
|
||||||
|
|
||||||
from typing import Generic, TypeVar
|
from typing import Generic, TypeVar, cast, Literal
|
||||||
|
|
||||||
|
CommandType = TypeVar('CommandType')
|
||||||
|
|
||||||
|
|
||||||
T = TypeVar('T')
|
class Command(Generic[CommandType]):
|
||||||
|
|
||||||
|
|
||||||
class Command(Generic[T]):
|
|
||||||
def __init__(self, trigger: str,
|
def __init__(self, trigger: str,
|
||||||
description: str = None,
|
description: str = None,
|
||||||
flags: Flag | FlagsGroup = None):
|
flags: Flag | FlagsGroup = None):
|
||||||
@@ -57,7 +56,7 @@ class Command(Generic[T]):
|
|||||||
return self._input_flags
|
return self._input_flags
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_input_command(raw_command: str) -> 'Command[T]':
|
def parse_input_command(raw_command: str) -> 'Command[CommandType]':
|
||||||
if not raw_command:
|
if not raw_command:
|
||||||
raise EmptyInputCommandException()
|
raise EmptyInputCommandException()
|
||||||
list_of_tokens = raw_command.split()
|
list_of_tokens = raw_command.split()
|
||||||
@@ -67,7 +66,7 @@ class Command(Generic[T]):
|
|||||||
flags: FlagsGroup = FlagsGroup()
|
flags: FlagsGroup = FlagsGroup()
|
||||||
current_flag_name = None
|
current_flag_name = None
|
||||||
current_flag_value = None
|
current_flag_value = None
|
||||||
for _ in list_of_tokens:
|
for k, _ in enumerate(list_of_tokens):
|
||||||
if _.startswith('-'):
|
if _.startswith('-'):
|
||||||
flag_prefix_last_symbol_index = _.rfind('-')
|
flag_prefix_last_symbol_index = _.rfind('-')
|
||||||
if current_flag_name or len(_) < 2 or len(_[:flag_prefix_last_symbol_index]) > 3:
|
if current_flag_name or len(_) < 2 or len(_[:flag_prefix_last_symbol_index]) > 3:
|
||||||
@@ -79,12 +78,15 @@ class Command(Generic[T]):
|
|||||||
raise UnprocessedInputFlagException()
|
raise UnprocessedInputFlagException()
|
||||||
else:
|
else:
|
||||||
current_flag_value = _
|
current_flag_value = _
|
||||||
if current_flag_name and current_flag_value:
|
if current_flag_name:
|
||||||
|
if not len(list_of_tokens) == k+1:
|
||||||
|
if not list_of_tokens[k+1].startswith('-'):
|
||||||
|
continue
|
||||||
flag_prefix_last_symbol_index = current_flag_name.rfind('-')
|
flag_prefix_last_symbol_index = current_flag_name.rfind('-')
|
||||||
flag_prefix = current_flag_name[:flag_prefix_last_symbol_index+1]
|
flag_prefix = current_flag_name[:flag_prefix_last_symbol_index+1]
|
||||||
flag_name = current_flag_name[flag_prefix_last_symbol_index+1:]
|
flag_name = current_flag_name[flag_prefix_last_symbol_index+1:]
|
||||||
input_flag = Flag(flag_name=flag_name,
|
input_flag = Flag(flag_name=flag_name,
|
||||||
flag_prefix=flag_prefix)
|
flag_prefix=cast(Literal['-', '--', '---'], flag_prefix))
|
||||||
input_flag.set_value(current_flag_value)
|
input_flag.set_value(current_flag_value)
|
||||||
|
|
||||||
all_flags = [x.get_string_entity() for x in flags.get_flags()]
|
all_flags = [x.get_string_entity() for x in flags.get_flags()]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from .params.flag.entity import Flag
|
from argenta.command.flag.entity import Flag
|
||||||
|
|
||||||
|
|
||||||
class UnprocessedInputFlagException(Exception):
|
class UnprocessedInputFlagException(Exception):
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
from argenta.command.flag import Flag
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
help_flag = Flag(flag_name='help', possible_flag_values=False)
|
||||||
|
short_help_flag = Flag(flag_name='h', flag_prefix='-', possible_flag_values=False)
|
||||||
|
|
||||||
|
info_flag = Flag(flag_name='info', possible_flag_values=False)
|
||||||
|
short_info_flag = Flag(flag_name='i', flag_prefix='-', possible_flag_values=False)
|
||||||
|
|
||||||
|
all_flag = Flag(flag_name='all', possible_flag_values=False)
|
||||||
|
short_all_flag = Flag(flag_name='a', flag_prefix='-', possible_flag_values=False)
|
||||||
|
|
||||||
|
host_flag = Flag(flag_name='host', possible_flag_values=re.compile(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'))
|
||||||
|
short_host_flag = Flag(flag_name='h', flag_prefix='-', possible_flag_values=re.compile(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$'))
|
||||||
|
|
||||||
|
port_flag = Flag(flag_name='port', possible_flag_values=re.compile(r'^\d{1,5}$'))
|
||||||
|
short_port_flag = Flag(flag_name='p', flag_prefix='-', possible_flag_values=re.compile(r'^\d{1,5}$'))
|
||||||
@@ -4,12 +4,10 @@ from typing import Literal, Pattern
|
|||||||
class Flag:
|
class Flag:
|
||||||
def __init__(self, flag_name: str,
|
def __init__(self, flag_name: str,
|
||||||
flag_prefix: Literal['-', '--', '---'] = '--',
|
flag_prefix: Literal['-', '--', '---'] = '--',
|
||||||
ignore_flag_value_register: bool = False,
|
possible_flag_values: list[str] | Pattern[str] | False = True):
|
||||||
possible_flag_values: list[str] | Pattern[str] = False):
|
|
||||||
self._flag_name = flag_name
|
self._flag_name = flag_name
|
||||||
self._flag_prefix = flag_prefix
|
self._flag_prefix = flag_prefix
|
||||||
self.possible_flag_values = possible_flag_values
|
self.possible_flag_values = possible_flag_values
|
||||||
self.ignore_flag_value_register = ignore_flag_value_register
|
|
||||||
|
|
||||||
self._flag_value = None
|
self._flag_value = None
|
||||||
|
|
||||||
@@ -29,23 +27,23 @@ class Flag:
|
|||||||
def set_value(self, value):
|
def set_value(self, value):
|
||||||
self._flag_value = value
|
self._flag_value = value
|
||||||
|
|
||||||
def validate_input_flag_value(self, input_flag_value: str):
|
def validate_input_flag_value(self, input_flag_value: str | None):
|
||||||
if isinstance(self.possible_flag_values, Pattern):
|
if self.possible_flag_values is False:
|
||||||
|
if input_flag_value is None:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
elif isinstance(self.possible_flag_values, Pattern):
|
||||||
is_valid = bool(self.possible_flag_values.match(input_flag_value))
|
is_valid = bool(self.possible_flag_values.match(input_flag_value))
|
||||||
if bool(is_valid):
|
if bool(is_valid):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if isinstance(self.possible_flag_values, list):
|
elif isinstance(self.possible_flag_values, list):
|
||||||
if self.ignore_flag_value_register:
|
|
||||||
if input_flag_value.lower() in [x.lower() for x in self.possible_flag_values]:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
if input_flag_value in self.possible_flag_values:
|
if input_flag_value in self.possible_flag_values:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
else:
|
||||||
return True
|
return True
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
from .entity import FlagsGroup
|
||||||
+2
-2
@@ -1,8 +1,8 @@
|
|||||||
from argenta.command.params.flag.entity import Flag
|
from argenta.command.flag.entity import Flag
|
||||||
|
|
||||||
|
|
||||||
class FlagsGroup:
|
class FlagsGroup:
|
||||||
def __init__(self, flags: list[Flag] = None):
|
def __init__(self, *flags: Flag):
|
||||||
self._flags: list[Flag] = [] if not flags else flags
|
self._flags: list[Flag] = [] if not flags else flags
|
||||||
|
|
||||||
def get_flags(self) -> list[Flag]:
|
def get_flags(self) -> list[Flag]:
|
||||||
@@ -2,19 +2,20 @@ from typing import Callable, Any
|
|||||||
from inspect import getfullargspec
|
from inspect import getfullargspec
|
||||||
|
|
||||||
from ..command.entity import Command
|
from ..command.entity import Command
|
||||||
from ..command.params.flag.entity import Flag
|
from argenta.command.flag.entity import Flag
|
||||||
from ..command.params.flag.flags_group.entity import FlagsGroup
|
from argenta.command.flag.flags_group import FlagsGroup
|
||||||
from ..router.exceptions import (RepeatedCommandException,
|
from ..router.exceptions import (RepeatedCommandException,
|
||||||
RepeatedFlagNameException,
|
RepeatedFlagNameException,
|
||||||
TooManyTransferredArgsException,
|
TooManyTransferredArgsException,
|
||||||
RequiredArgumentNotPassedException,
|
RequiredArgumentNotPassedException,
|
||||||
IncorrectNumberOfHandlerArgsException)
|
IncorrectNumberOfHandlerArgsException,
|
||||||
|
TriggerCannotContainSpacesException)
|
||||||
|
|
||||||
|
|
||||||
class Router:
|
class Router:
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
title: str = 'Commands group title:',
|
title: str = 'Commands group title:',
|
||||||
name: str = 'subordinate'):
|
name: str = 'Default'):
|
||||||
|
|
||||||
self._title = title
|
self._title = title
|
||||||
self._name = name
|
self._name = name
|
||||||
@@ -71,6 +72,8 @@ class Router:
|
|||||||
|
|
||||||
def _validate_command(self, command: Command):
|
def _validate_command(self, command: Command):
|
||||||
command_name: str = command.get_trigger()
|
command_name: str = command.get_trigger()
|
||||||
|
if command_name.find(' ') != -1:
|
||||||
|
raise TriggerCannotContainSpacesException()
|
||||||
if command_name in self.get_all_commands():
|
if command_name in self.get_all_commands():
|
||||||
raise RepeatedCommandException()
|
raise RepeatedCommandException()
|
||||||
if self._ignore_command_register:
|
if self._ignore_command_register:
|
||||||
|
|||||||
@@ -21,3 +21,8 @@ class RequiredArgumentNotPassedException(Exception):
|
|||||||
class IncorrectNumberOfHandlerArgsException(Exception):
|
class IncorrectNumberOfHandlerArgsException(Exception):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Handler has incorrect number of arguments"
|
return "Handler has incorrect number of arguments"
|
||||||
|
|
||||||
|
|
||||||
|
class TriggerCannotContainSpacesException(Exception):
|
||||||
|
def __str__(self):
|
||||||
|
return "Command trigger cannot contain spaces"
|
||||||
|
|||||||
+2
-10
@@ -1,11 +1,3 @@
|
|||||||
import re
|
from typing import cast, Literal
|
||||||
|
|
||||||
|
print(cast(Literal['-', '--', '---'], '----'))
|
||||||
def set_description_message_pattern(pattern: str) -> None:
|
|
||||||
first_check = re.match(r'.*command.*', pattern)
|
|
||||||
second_check = re.match(r'.*{description}.*', pattern)
|
|
||||||
if bool(first_check) and bool(second_check):
|
|
||||||
print('Success')
|
|
||||||
|
|
||||||
|
|
||||||
set_description_message_pattern('Invalid des{ommand}cription pattern')
|
|
||||||
@@ -2,9 +2,9 @@ import re
|
|||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
|
|
||||||
from argenta.command.entity import Command
|
from argenta.command import Command
|
||||||
from argenta.command.params.flag.entity import Flag
|
from argenta.command.flag import Flag, FlagsGroup
|
||||||
from argenta.command.params.flag.flags_group.entity import FlagsGroup
|
from argenta.command.flag.defaults import host_flag, port_flag
|
||||||
from argenta.router import Router
|
from argenta.router import Router
|
||||||
from .handlers_implementation.help_command import help_command
|
from .handlers_implementation.help_command import help_command
|
||||||
|
|
||||||
@@ -18,21 +18,12 @@ settings_router: Router = Router(title='Settings points:')
|
|||||||
console = Console()
|
console = Console()
|
||||||
|
|
||||||
|
|
||||||
flags = FlagsGroup(flags=[
|
|
||||||
Flag(flag_name='host',
|
|
||||||
flag_prefix='--',
|
|
||||||
possible_flag_values=re.compile(r'^192.168.\d{1,3}.\d{1,3}$')),
|
|
||||||
Flag(flag_name='port',
|
|
||||||
flag_prefix='--', )
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
@work_router.command(Command(trigger='0', description='Get Help'))
|
@work_router.command(Command(trigger='0', description='Get Help'))
|
||||||
def command_help():
|
def command_help():
|
||||||
help_command()
|
help_command()
|
||||||
|
|
||||||
|
|
||||||
@work_router.command(Command(trigger='P', description='Start Solving', flags=flags))
|
@work_router.command(Command(trigger='j', description='Start Solving', flags=FlagsGroup(host_flag, port_flag)))
|
||||||
def command_start_solving(args: dict):
|
def command_start_solving(args: dict):
|
||||||
print('Solving...')
|
print('Solving...')
|
||||||
pprint(args)
|
pprint(args)
|
||||||
|
|||||||
@@ -3,16 +3,13 @@ from art import text2art
|
|||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
|
|
||||||
from argenta.app import App
|
from argenta.app import App
|
||||||
from argenta.router import Router
|
|
||||||
from argenta.command import Command
|
|
||||||
from argenta.command.params.flag import Flag, FlagsGroup
|
|
||||||
|
|
||||||
|
|
||||||
app: App = App(prompt='[italic white bold]What do you want to do(enter number of action)?',
|
app: App = App(prompt='[italic white bold]What do you want to do(enter number of action)?',
|
||||||
line_separate=f'\n{"[bold green]-[/bold green][bold red]-[/bold red]"*25}\n',
|
line_separate=f'\n{"[bold green]-[/bold green][bold red]-[/bold red]"*25}\n',
|
||||||
print_func=Console().print,
|
print_func=Console().print,
|
||||||
command_group_description_separate='',
|
command_group_description_separate='',
|
||||||
repeat_command_groups=True)
|
repeat_command_groups=True,
|
||||||
|
ignore_exit_command_register=False)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -29,7 +26,7 @@ def main():
|
|||||||
app.set_farewell_message(goodbye_message)
|
app.set_farewell_message(goodbye_message)
|
||||||
|
|
||||||
app.set_invalid_input_flags_handler(lambda raw_command: print(f"Invalid input flags: {raw_command}"))
|
app.set_invalid_input_flags_handler(lambda raw_command: print(f"Invalid input flags: {raw_command}"))
|
||||||
app.set_unknown_command_handler(lambda command: print(f"Unknown command: {command.get_string_entity()}"))
|
app.set_unknown_command_handler(lambda command: print(f"Unknown command: {command.get_trigger()}"))
|
||||||
app.set_repeated_input_flags_handler(lambda raw_command: print(f"Repeated input flags: {raw_command}"))
|
app.set_repeated_input_flags_handler(lambda raw_command: print(f"Repeated input flags: {raw_command}"))
|
||||||
|
|
||||||
app.set_description_message_pattern('[bold red][{command}][/bold red] [blue]*=*=*[/blue] [bold yellow italic]{description}')
|
app.set_description_message_pattern('[bold red][{command}][/bold red] [blue]*=*=*[/blue] [bold yellow italic]{description}')
|
||||||
|
|||||||
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "argenta"
|
name = "argenta"
|
||||||
version = "0.3.6"
|
version = "0.3.9"
|
||||||
description = "python library for creating custom shells"
|
description = "python library for creating custom shells"
|
||||||
authors = [
|
authors = [
|
||||||
{name = "kolo", email = "kolo.is.main@gmail.com"}
|
{name = "kolo", email = "kolo.is.main@gmail.com"}
|
||||||
@@ -33,4 +33,5 @@ numpy = "^2.2.2"
|
|||||||
word2number = "^1.1"
|
word2number = "^1.1"
|
||||||
numexpr = "^2.10.2"
|
numexpr = "^2.10.2"
|
||||||
requests = "^2.32.3"
|
requests = "^2.32.3"
|
||||||
|
pyreadline3 = "^3.5.4"
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,6 @@ class TestCommand(unittest.TestCase):
|
|||||||
def test_parse_correct_raw_command(self):
|
def test_parse_correct_raw_command(self):
|
||||||
self.assertEqual(Command.parse_input_command('ssh --host 192.168.0.3').get_trigger(), 'ssh')
|
self.assertEqual(Command.parse_input_command('ssh --host 192.168.0.3').get_trigger(), 'ssh')
|
||||||
|
|
||||||
def test_parse_raw_command_with_flag_name_without_value(self):
|
|
||||||
with self.assertRaises(UnprocessedInputFlagException):
|
|
||||||
Command.parse_input_command('ssh --host')
|
|
||||||
|
|
||||||
def test_parse_raw_command_without_flag_name_with_value(self):
|
def test_parse_raw_command_without_flag_name_with_value(self):
|
||||||
with self.assertRaises(UnprocessedInputFlagException):
|
with self.assertRaises(UnprocessedInputFlagException):
|
||||||
Command.parse_input_command('ssh 192.168.0.3')
|
Command.parse_input_command('ssh 192.168.0.3')
|
||||||
|
|||||||
+17
-1
@@ -1,4 +1,4 @@
|
|||||||
from argenta.command.params.flag import Flag
|
from argenta.command.flag import Flag
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
import re
|
import re
|
||||||
@@ -52,6 +52,22 @@ class TestFlag(unittest.TestCase):
|
|||||||
flag = Flag(flag_name='test', possible_flag_values=re.compile(r'192.168.\d+.\d+'))
|
flag = Flag(flag_name='test', possible_flag_values=re.compile(r'192.168.\d+.\d+'))
|
||||||
self.assertEqual(flag.validate_input_flag_value('192.168.9.8'), True)
|
self.assertEqual(flag.validate_input_flag_value('192.168.9.8'), True)
|
||||||
|
|
||||||
|
def test_validate_correct_empty_flag_value_without_possible_flag_values(self):
|
||||||
|
flag = Flag(flag_name='test', possible_flag_values=False)
|
||||||
|
self.assertEqual(flag.validate_input_flag_value(None), True)
|
||||||
|
|
||||||
|
def test_validate_correct_empty_flag_value_with_possible_flag_values(self):
|
||||||
|
flag = Flag(flag_name='test', possible_flag_values=True)
|
||||||
|
self.assertEqual(flag.validate_input_flag_value(None), True)
|
||||||
|
|
||||||
|
def test_validate_incorrect_random_flag_value_without_possible_flag_values(self):
|
||||||
|
flag = Flag(flag_name='test', possible_flag_values=False)
|
||||||
|
self.assertEqual(flag.validate_input_flag_value('random value'), False)
|
||||||
|
|
||||||
|
def test_validate_correct_random_flag_value_with_possible_flag_values(self):
|
||||||
|
flag = Flag(flag_name='test', possible_flag_values=True)
|
||||||
|
self.assertEqual(flag.validate_input_flag_value('random value'), True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from argenta.command.params.flag import Flag, FlagsGroup
|
from argenta.command.flag import Flag, FlagsGroup
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ class TestFlagsGroup(unittest.TestCase):
|
|||||||
Flag('test2'),
|
Flag('test2'),
|
||||||
Flag('test3'),
|
Flag('test3'),
|
||||||
]
|
]
|
||||||
flags = FlagsGroup(list_of_flags)
|
flags = FlagsGroup(*list_of_flags)
|
||||||
serialized_flags = flags.unparse_to_dict()
|
serialized_flags = flags.unparse_to_dict()
|
||||||
needed_result = {'test1': {'name': 'test1',
|
needed_result = {'test1': {'name': 'test1',
|
||||||
'prefix': '--',
|
'prefix': '--',
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from argenta.command.params.flag import FlagsGroup, Flag
|
from argenta.command.flag import FlagsGroup, Flag
|
||||||
from argenta.router import Router
|
from argenta.router import Router
|
||||||
from argenta.command import Command
|
from argenta.command import Command
|
||||||
from argenta.router.exceptions import RepeatedCommandException
|
from argenta.router.exceptions import RepeatedCommandException, TriggerCannotContainSpacesException
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
@@ -109,6 +109,13 @@ class TestRouter(unittest.TestCase):
|
|||||||
def test():
|
def test():
|
||||||
return 'correct result'
|
return 'correct result'
|
||||||
|
|
||||||
|
def test_register_command_with_spaces_in_trigger(self):
|
||||||
|
router = Router()
|
||||||
|
with self.assertRaises(TriggerCannotContainSpacesException):
|
||||||
|
@router.command(Command(trigger='command with spaces'))
|
||||||
|
def test():
|
||||||
|
return 'correct result'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user