mirror of
https://github.com/koloideal/Argenta.git
synced 2026-06-10 18:15:28 +03:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d30515c1a2 | |||
| 5a6fc1d8ca | |||
| e5d6ead38e | |||
| b61c151e1c |
@@ -56,7 +56,7 @@ if __name__ == '__main__':
|
||||
import re
|
||||
from argenta.router import Router
|
||||
from argenta.command import Command
|
||||
from argenta.command.params.flag import FlagsGroup, Flag
|
||||
from argenta.command.flag import FlagsGroup, Flag
|
||||
|
||||
router = Router()
|
||||
|
||||
@@ -305,6 +305,7 @@ Router(title: str = 'Commands group title:',
|
||||
- `TooManyTransferredArgsException` - Слишком много зарегистрированных аргументов у обработчика команды
|
||||
- `RequiredArgumentNotPassedException` - Не зарегистрирован обязательный аргумент у обработчика команды(аргумент, через который будут переданы флаги введённой команды)
|
||||
- `IncorrectNumberOfHandlerArgsException` - У обработчика нестандартного поведения зарегистрировано неверное количество аргументов(в большинстве случаев у него должен быть один аргумент)
|
||||
- `TriggerCannotContainSpacesException` - У регистрируемой команды в триггере содержатся пробелы
|
||||
|
||||
---
|
||||
|
||||
@@ -363,9 +364,9 @@ Command(trigger: str,
|
||||
### Конструктор
|
||||
```python
|
||||
Flag(flag_name: str,
|
||||
flag_prefix: Literal['-', '--', '---'] = '-',
|
||||
flag_prefix: typing.Literal['-', '--', '---'] = '-',
|
||||
ignore_flag_value_register: bool = False,
|
||||
possible_flag_values: list[str] | Pattern[str] = False)
|
||||
possible_flag_values: list[str] | typing.Pattern[str] = False)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from pprint import pprint
|
||||
from typing import Callable
|
||||
from inspect import getfullargspec
|
||||
import re
|
||||
|
||||
+13
-11
@@ -1,16 +1,15 @@
|
||||
from .params.flag.entity import Flag
|
||||
from .params.flag.flags_group.entity import FlagsGroup
|
||||
from argenta.command.flag.entity import Flag
|
||||
from argenta.command.flag.flags_group import FlagsGroup
|
||||
from .exceptions import (UnprocessedInputFlagException,
|
||||
RepeatedInputFlagsException,
|
||||
EmptyInputCommandException)
|
||||
|
||||
from typing import Generic, TypeVar
|
||||
from typing import Generic, TypeVar, cast, Literal
|
||||
|
||||
CommandType = TypeVar('CommandType')
|
||||
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
|
||||
class Command(Generic[T]):
|
||||
class Command(Generic[CommandType]):
|
||||
def __init__(self, trigger: str,
|
||||
description: str = None,
|
||||
flags: Flag | FlagsGroup = None):
|
||||
@@ -57,7 +56,7 @@ class Command(Generic[T]):
|
||||
return self._input_flags
|
||||
|
||||
@staticmethod
|
||||
def parse_input_command(raw_command: str) -> 'Command[T]':
|
||||
def parse_input_command(raw_command: str) -> 'Command[CommandType]':
|
||||
if not raw_command:
|
||||
raise EmptyInputCommandException()
|
||||
list_of_tokens = raw_command.split()
|
||||
@@ -67,7 +66,7 @@ class Command(Generic[T]):
|
||||
flags: FlagsGroup = FlagsGroup()
|
||||
current_flag_name = None
|
||||
current_flag_value = None
|
||||
for _ in list_of_tokens:
|
||||
for k, _ in enumerate(list_of_tokens):
|
||||
if _.startswith('-'):
|
||||
flag_prefix_last_symbol_index = _.rfind('-')
|
||||
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()
|
||||
else:
|
||||
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 = 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,
|
||||
flag_prefix=flag_prefix)
|
||||
flag_prefix=cast(Literal['-', '--', '---'], flag_prefix))
|
||||
input_flag.set_value(current_flag_value)
|
||||
|
||||
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):
|
||||
|
||||
@@ -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:
|
||||
def __init__(self, flag_name: str,
|
||||
flag_prefix: Literal['-', '--', '---'] = '--',
|
||||
ignore_flag_value_register: bool = False,
|
||||
possible_flag_values: list[str] | Pattern[str] = False):
|
||||
possible_flag_values: list[str] | Pattern[str] | False = True):
|
||||
self._flag_name = flag_name
|
||||
self._flag_prefix = flag_prefix
|
||||
self.possible_flag_values = possible_flag_values
|
||||
self.ignore_flag_value_register = ignore_flag_value_register
|
||||
|
||||
self._flag_value = None
|
||||
|
||||
@@ -29,23 +27,23 @@ class Flag:
|
||||
def set_value(self, value):
|
||||
self._flag_value = value
|
||||
|
||||
def validate_input_flag_value(self, input_flag_value: str):
|
||||
if isinstance(self.possible_flag_values, Pattern):
|
||||
def validate_input_flag_value(self, input_flag_value: str | None):
|
||||
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))
|
||||
if bool(is_valid):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
if 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:
|
||||
elif isinstance(self.possible_flag_values, list):
|
||||
if input_flag_value in self.possible_flag_values:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
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:
|
||||
def __init__(self, flags: list[Flag] = None):
|
||||
def __init__(self, *flags: Flag):
|
||||
self._flags: list[Flag] = [] if not flags else flags
|
||||
|
||||
def get_flags(self) -> list[Flag]:
|
||||
@@ -2,13 +2,14 @@ from typing import Callable, Any
|
||||
from inspect import getfullargspec
|
||||
|
||||
from ..command.entity import Command
|
||||
from ..command.params.flag.entity import Flag
|
||||
from ..command.params.flag.flags_group.entity import FlagsGroup
|
||||
from argenta.command.flag.entity import Flag
|
||||
from argenta.command.flag.flags_group import FlagsGroup
|
||||
from ..router.exceptions import (RepeatedCommandException,
|
||||
RepeatedFlagNameException,
|
||||
TooManyTransferredArgsException,
|
||||
RequiredArgumentNotPassedException,
|
||||
IncorrectNumberOfHandlerArgsException)
|
||||
IncorrectNumberOfHandlerArgsException,
|
||||
TriggerCannotContainSpacesException)
|
||||
|
||||
|
||||
class Router:
|
||||
@@ -71,6 +72,8 @@ class Router:
|
||||
|
||||
def _validate_command(self, command: Command):
|
||||
command_name: str = command.get_trigger()
|
||||
if command_name.find(' ') != -1:
|
||||
raise TriggerCannotContainSpacesException()
|
||||
if command_name in self.get_all_commands():
|
||||
raise RepeatedCommandException()
|
||||
if self._ignore_command_register:
|
||||
|
||||
@@ -21,3 +21,8 @@ class RequiredArgumentNotPassedException(Exception):
|
||||
class IncorrectNumberOfHandlerArgsException(Exception):
|
||||
def __str__(self):
|
||||
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
|
||||
|
||||
|
||||
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')
|
||||
print(cast(Literal['-', '--', '---'], '----'))
|
||||
@@ -2,9 +2,9 @@ import re
|
||||
from pprint import pprint
|
||||
from rich.console import Console
|
||||
|
||||
from argenta.command.entity import Command
|
||||
from argenta.command.params.flag.entity import Flag
|
||||
from argenta.command.params.flag.flags_group.entity import FlagsGroup
|
||||
from argenta.command import Command
|
||||
from argenta.command.flag import Flag, FlagsGroup
|
||||
from argenta.command.flag.defaults import host_flag, port_flag
|
||||
from argenta.router import Router
|
||||
from .handlers_implementation.help_command import help_command
|
||||
|
||||
@@ -18,21 +18,12 @@ settings_router: Router = Router(title='Settings points:')
|
||||
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'))
|
||||
def command_help():
|
||||
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):
|
||||
print('Solving...')
|
||||
pprint(args)
|
||||
|
||||
@@ -3,16 +3,13 @@ from art import text2art
|
||||
from rich.console import Console
|
||||
|
||||
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)?',
|
||||
line_separate=f'\n{"[bold green]-[/bold green][bold red]-[/bold red]"*25}\n',
|
||||
print_func=Console().print,
|
||||
command_group_description_separate='',
|
||||
repeat_command_groups=True)
|
||||
repeat_command_groups=True,
|
||||
ignore_exit_command_register=False)
|
||||
|
||||
|
||||
def main():
|
||||
@@ -29,7 +26,7 @@ def main():
|
||||
app.set_farewell_message(goodbye_message)
|
||||
|
||||
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_description_message_pattern('[bold red][{command}][/bold red] [blue]*=*=*[/blue] [bold yellow italic]{description}')
|
||||
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "argenta"
|
||||
version = "0.3.7"
|
||||
version = "0.3.9"
|
||||
description = "python library for creating custom shells"
|
||||
authors = [
|
||||
{name = "kolo", email = "kolo.is.main@gmail.com"}
|
||||
@@ -33,4 +33,5 @@ numpy = "^2.2.2"
|
||||
word2number = "^1.1"
|
||||
numexpr = "^2.10.2"
|
||||
requests = "^2.32.3"
|
||||
pyreadline3 = "^3.5.4"
|
||||
|
||||
|
||||
@@ -10,10 +10,6 @@ class TestCommand(unittest.TestCase):
|
||||
def test_parse_correct_raw_command(self):
|
||||
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):
|
||||
with self.assertRaises(UnprocessedInputFlagException):
|
||||
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 re
|
||||
@@ -52,6 +52,22 @@ class TestFlag(unittest.TestCase):
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
@@ -31,7 +31,7 @@ class TestFlagsGroup(unittest.TestCase):
|
||||
Flag('test2'),
|
||||
Flag('test3'),
|
||||
]
|
||||
flags = FlagsGroup(list_of_flags)
|
||||
flags = FlagsGroup(*list_of_flags)
|
||||
serialized_flags = flags.unparse_to_dict()
|
||||
needed_result = {'test1': {'name': 'test1',
|
||||
'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.command import Command
|
||||
from argenta.router.exceptions import RepeatedCommandException
|
||||
from argenta.router.exceptions import RepeatedCommandException, TriggerCannotContainSpacesException
|
||||
|
||||
import unittest
|
||||
|
||||
@@ -109,6 +109,13 @@ class TestRouter(unittest.TestCase):
|
||||
def test():
|
||||
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