4 Commits

Author SHA1 Message Date
kolo d30515c1a2 v0.3.9 2025-03-11 20:44:06 +03:00
kolo 5a6fc1d8ca first step 2025-03-08 13:49:29 +03:00
kolo e5d6ead38e v0.3.8 2025-03-06 01:35:28 +03:00
kolo b61c151e1c v0.3.8 2025-03-06 01:35:18 +03:00
21 changed files with 104 additions and 75 deletions
+4 -3
View File
@@ -56,7 +56,7 @@ 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()
@@ -305,6 +305,7 @@ Router(title: str = 'Commands group title:',
- `TooManyTransferredArgsException` - Слишком много зарегистрированных аргументов у обработчика команды - `TooManyTransferredArgsException` - Слишком много зарегистрированных аргументов у обработчика команды
- `RequiredArgumentNotPassedException` - Не зарегистрирован обязательный аргумент у обработчика команды(аргумент, через который будут переданы флаги введённой команды) - `RequiredArgumentNotPassedException` - Не зарегистрирован обязательный аргумент у обработчика команды(аргумент, через который будут переданы флаги введённой команды)
- `IncorrectNumberOfHandlerArgsException` - У обработчика нестандартного поведения зарегистрировано неверное количество аргументов(в большинстве случаев у него должен быть один аргумент) - `IncorrectNumberOfHandlerArgsException` - У обработчика нестандартного поведения зарегистрировано неверное количество аргументов(в большинстве случаев у него должен быть один аргумент)
- `TriggerCannotContainSpacesException` - У регистрируемой команды в триггере содержатся пробелы
--- ---
@@ -363,9 +364,9 @@ Command(trigger: str,
### Конструктор ### Конструктор
```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)
``` ```
--- ---
+1
View File
@@ -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
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
from .params.flag.entity import Flag from argenta.command.flag.entity import Flag
class UnprocessedInputFlagException(Exception): class UnprocessedInputFlagException(Exception):
+18
View File
@@ -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 in self.possible_flag_values:
if input_flag_value.lower() in [x.lower() for x in self.possible_flag_values]: return True
return True
else:
return False
else: else:
if input_flag_value in self.possible_flag_values: return False
return True else:
else: return True
return False
return True
@@ -0,0 +1 @@
from .entity import FlagsGroup
@@ -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]:
View File
+6 -3
View File
@@ -2,13 +2,14 @@ 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:
@@ -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:
+5
View File
@@ -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
View File
@@ -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')
+4 -13
View File
@@ -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 -6
View File
@@ -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
View File
@@ -1,6 +1,6 @@
[project] [project]
name = "argenta" name = "argenta"
version = "0.3.7" 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"
-4
View File
@@ -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
View File
@@ -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)
+2 -2
View File
@@ -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': '--',
+9 -2
View File
@@ -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'