From d30515c1a2d64e1f555533a90ae5a73bb65c5d30 Mon Sep 17 00:00:00 2001 From: kolo Date: Tue, 11 Mar 2025 20:44:06 +0300 Subject: [PATCH] v0.3.9 --- README.md | 2 +- argenta/app/entity.py | 1 + argenta/command/entity.py | 24 ++++++++------- argenta/command/exceptions.py | 2 +- argenta/command/{params => }/flag/__init__.py | 0 argenta/command/flag/defaults.py | 18 +++++++++++ argenta/command/{params => }/flag/entity.py | 30 +++++++++---------- argenta/command/flag/flags_group/__init__.py | 1 + .../{params => }/flag/flags_group/entity.py | 4 +-- argenta/command/params/__init__.py | 0 .../params/flag/flags_group/__init__.py | 0 argenta/router/entity.py | 4 +-- mock/local_test.py | 18 ++--------- mock/mock_app/handlers/routers.py | 17 +++-------- mock/mock_app/main.py | 9 ++---- pyproject.toml | 2 +- tests/test_command.py | 4 --- tests/test_flag.py | 18 ++++++++++- tests/test_flagsgroup.py | 4 +-- tests/test_router.py | 2 +- 20 files changed, 83 insertions(+), 77 deletions(-) rename argenta/command/{params => }/flag/__init__.py (100%) create mode 100644 argenta/command/flag/defaults.py rename argenta/command/{params => }/flag/entity.py (57%) create mode 100644 argenta/command/flag/flags_group/__init__.py rename argenta/command/{params => }/flag/flags_group/entity.py (89%) delete mode 100644 argenta/command/params/__init__.py delete mode 100644 argenta/command/params/flag/flags_group/__init__.py diff --git a/README.md b/README.md index db7e4b9..97207c7 100644 --- a/README.md +++ b/README.md @@ -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() diff --git a/argenta/app/entity.py b/argenta/app/entity.py index b9c5e98..07489d6 100644 --- a/argenta/app/entity.py +++ b/argenta/app/entity.py @@ -1,3 +1,4 @@ +from pprint import pprint from typing import Callable from inspect import getfullargspec import re diff --git a/argenta/command/entity.py b/argenta/command/entity.py index dea5b95..41d044f 100644 --- a/argenta/command/entity.py +++ b/argenta/command/entity.py @@ -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()] diff --git a/argenta/command/exceptions.py b/argenta/command/exceptions.py index 70d7b66..5fa0ac8 100644 --- a/argenta/command/exceptions.py +++ b/argenta/command/exceptions.py @@ -1,4 +1,4 @@ -from .params.flag.entity import Flag +from argenta.command.flag.entity import Flag class UnprocessedInputFlagException(Exception): diff --git a/argenta/command/params/flag/__init__.py b/argenta/command/flag/__init__.py similarity index 100% rename from argenta/command/params/flag/__init__.py rename to argenta/command/flag/__init__.py diff --git a/argenta/command/flag/defaults.py b/argenta/command/flag/defaults.py new file mode 100644 index 0000000..17e92aa --- /dev/null +++ b/argenta/command/flag/defaults.py @@ -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}$')) diff --git a/argenta/command/params/flag/entity.py b/argenta/command/flag/entity.py similarity index 57% rename from argenta/command/params/flag/entity.py rename to argenta/command/flag/entity.py index 34c9be1..bd598a0 100644 --- a/argenta/command/params/flag/entity.py +++ b/argenta/command/flag/entity.py @@ -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 + elif isinstance(self.possible_flag_values, list): + if input_flag_value in self.possible_flag_values: + return True else: - if input_flag_value in self.possible_flag_values: - return True - else: - return False - return True + return False + else: + return True diff --git a/argenta/command/flag/flags_group/__init__.py b/argenta/command/flag/flags_group/__init__.py new file mode 100644 index 0000000..175b019 --- /dev/null +++ b/argenta/command/flag/flags_group/__init__.py @@ -0,0 +1 @@ +from .entity import FlagsGroup \ No newline at end of file diff --git a/argenta/command/params/flag/flags_group/entity.py b/argenta/command/flag/flags_group/entity.py similarity index 89% rename from argenta/command/params/flag/flags_group/entity.py rename to argenta/command/flag/flags_group/entity.py index 8a3fb8c..0c9960a 100644 --- a/argenta/command/params/flag/flags_group/entity.py +++ b/argenta/command/flag/flags_group/entity.py @@ -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]: diff --git a/argenta/command/params/__init__.py b/argenta/command/params/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/argenta/command/params/flag/flags_group/__init__.py b/argenta/command/params/flag/flags_group/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/argenta/router/entity.py b/argenta/router/entity.py index 2c6f5e5..696d731 100644 --- a/argenta/router/entity.py +++ b/argenta/router/entity.py @@ -2,8 +2,8 @@ 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, diff --git a/mock/local_test.py b/mock/local_test.py index e11f7d6..3f2b16e 100644 --- a/mock/local_test.py +++ b/mock/local_test.py @@ -1,17 +1,3 @@ -import readline +from typing import cast, Literal -def startup_hook(): - readline.insert_text('from startup_hook') - -def pre_input_hook(): - readline.insert_text('from pre_input_hook') - readline.redisplay() - -readline.set_startup_hook(startup_hook) -readline.set_pre_input_hook(pre_input_hook) -readline.parse_and_bind('tab: complete') - -line = '' -while line != 'stop': - line = input('!("stop" to quit) Ввод текста: => ') - print (f'Отправка: {line}') \ No newline at end of file +print(cast(Literal['-', '--', '---'], '----')) \ No newline at end of file diff --git a/mock/mock_app/handlers/routers.py b/mock/mock_app/handlers/routers.py index 1e16896..3f9be87 100644 --- a/mock/mock_app/handlers/routers.py +++ b/mock/mock_app/handlers/routers.py @@ -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='--gbP', 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) diff --git a/mock/mock_app/main.py b/mock/mock_app/main.py index 5dede10..56a1586 100644 --- a/mock/mock_app/main.py +++ b/mock/mock_app/main.py @@ -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}') diff --git a/pyproject.toml b/pyproject.toml index 016b9b1..7fec07e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "argenta" -version = "0.3.8" +version = "0.3.9" description = "python library for creating custom shells" authors = [ {name = "kolo", email = "kolo.is.main@gmail.com"} diff --git a/tests/test_command.py b/tests/test_command.py index c58e9ca..b3b0870 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -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') diff --git a/tests/test_flag.py b/tests/test_flag.py index 6f6e0ef..5537c7f 100644 --- a/tests/test_flag.py +++ b/tests/test_flag.py @@ -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) + diff --git a/tests/test_flagsgroup.py b/tests/test_flagsgroup.py index 324f94f..f471288 100644 --- a/tests/test_flagsgroup.py +++ b/tests/test_flagsgroup.py @@ -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': '--', diff --git a/tests/test_router.py b/tests/test_router.py index c3fdb3f..5e5d42c 100644 --- a/tests/test_router.py +++ b/tests/test_router.py @@ -1,4 +1,4 @@ -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, TriggerCannotContainSpacesException