diff --git a/argenta/app/entity.py b/argenta/app/entity.py index 28992c3..6e42047 100644 --- a/argenta/app/entity.py +++ b/argenta/app/entity.py @@ -1,5 +1,8 @@ from typing import Callable +from ..command.entity import Command +from argenta.command.parse_input_command.entity import ParseInputCommand from ..router.entity import Router +from ..command.parse_input_command.exceptions import InvalidInputFlagsException from .exceptions import (InvalidRouterInstanceException, InvalidDescriptionMessagePatternException, OnlyOneMainRouterIsAllowedException, @@ -16,6 +19,7 @@ class App: prompt: str = 'Enter a command', initial_message: str = '\nHello, I am Argenta\n', farewell_message: str = '\nGoodBye\n', + invalid_input_flags_message: str = 'Invalid input flags', exit_command: str = 'Q', exit_command_description: str = 'Exit command', exit_command_title: str = 'System points:', @@ -33,13 +37,14 @@ class App: self.ignore_exit_command_register = ignore_exit_command_register self.farewell_message = farewell_message self.initial_message = initial_message + self.invalid_input_flags_message = invalid_input_flags_message self.line_separate = line_separate self.command_group_description_separate = command_group_description_separate self.ignore_command_register = ignore_command_register self.repeat_command_groups = repeat_command_groups self._routers: list[Router] = [] - self._registered_router_entities: list[dict[str, str | list[dict[str, Callable[[], None] | str]] | Router]] = [] + self._registered_router_entities: list[dict[str, str | list[dict[str, Callable[[], None] | Command]] | Router]] = [] self._app_main_router: Router | None = None self._description_message_pattern: str = '[{command}] *=*=* {description}' @@ -61,12 +66,21 @@ class App: self._print_command_group_description() self.print_func(self.prompt) - command: str = input() + raw_command: str = input() + try: + command: Command = ParseInputCommand(raw_command=raw_command) + except InvalidInputFlagsException: + self.print_func(self.line_separate) + self.print_func(self.command_group_description_separate) + if not self.repeat_command_groups: + self.print_func(self.prompt) + continue - self._checking_command_for_exit_command(command) + + self._checking_command_for_exit_command(command.get_string_entity()) self.print_func(self.line_separate) - is_unknown_command: bool = self._check_is_command_unknown(command) + is_unknown_command: bool = self._check_is_command_unknown(command.get_string_entity()) if is_unknown_command: if not self.repeat_command_groups: self.print_func(self.prompt) @@ -124,7 +138,7 @@ class App: router.set_ignore_command_register(self.ignore_command_register) self._routers.append(router) - command_entities: list[dict[str, Callable[[], None] | str]] = router.get_command_entities() + command_entities: list[dict[str, Callable[[], None] | Command]] = router.get_command_entities() self._registered_router_entities.append({'name': router.get_name(), 'title': router.get_title(), 'entity': router, @@ -187,10 +201,10 @@ class App: def _check_is_command_unknown(self, command: str): - registered_router_entities: list[dict[str, str | list[dict[str, Callable[[], None] | str]] | Router]] = self._registered_router_entities + registered_router_entities: list[dict[str, str | list[dict[str, Callable[[], None] | Command]] | Router]] = self._registered_router_entities for router_entity in registered_router_entities: for command_entity in router_entity['commands']: - if command_entity['command'].lower() == command.lower(): + if command_entity['command'].get_string_entity().lower() == command.lower(): if self.ignore_command_register: return False else: @@ -207,8 +221,8 @@ class App: self.print_func(router_entity['title']) for command_entity in router_entity['commands']: self.print_func(self._description_message_pattern.format( - command=command_entity['command'], - description=command_entity['description'] + command=command_entity['command'].get_string_entity(), + description=command_entity['command'].get_description() ) ) self.print_func(self.command_group_description_separate) diff --git a/argenta/command/__pycache__/__init__.cpython-313.pyc b/argenta/command/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..26ac58c Binary files /dev/null and b/argenta/command/__pycache__/__init__.cpython-313.pyc differ diff --git a/argenta/command/__pycache__/entity.cpython-313.pyc b/argenta/command/__pycache__/entity.cpython-313.pyc new file mode 100644 index 0000000..b4af686 Binary files /dev/null and b/argenta/command/__pycache__/entity.cpython-313.pyc differ diff --git a/argenta/command/__pycache__/exceptions.cpython-313.pyc b/argenta/command/__pycache__/exceptions.cpython-313.pyc new file mode 100644 index 0000000..83cd0ea Binary files /dev/null and b/argenta/command/__pycache__/exceptions.cpython-313.pyc differ diff --git a/argenta/command/entity.py b/argenta/command/entity.py index fa7fd8b..61b8fb6 100644 --- a/argenta/command/entity.py +++ b/argenta/command/entity.py @@ -26,11 +26,14 @@ class Command: def get_flags(self): return self._flags + def set_command(self, command: str): + self._command = command + def validate_commands_params(self): if not isinstance(self._command, str): raise InvalidCommandInstanceException(self._command) - if isinstance(self._description, str): + if not isinstance(self._description, str): raise InvalidDescriptionInstanceException() - if isinstance(self._flags, Flag) or isinstance(self._flags, FlagsGroup): + if not (isinstance(self._flags, Flag) or isinstance(self._flags, FlagsGroup)): raise InvalidFlagsInstanceException diff --git a/argenta/command/params/__pycache__/__init__.cpython-313.pyc b/argenta/command/params/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..f90c4e8 Binary files /dev/null and b/argenta/command/params/__pycache__/__init__.cpython-313.pyc differ diff --git a/argenta/command/params/flag/__pycache__/__init__.cpython-313.pyc b/argenta/command/params/flag/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..65a5e01 Binary files /dev/null and b/argenta/command/params/flag/__pycache__/__init__.cpython-313.pyc differ diff --git a/argenta/command/params/flag/__pycache__/entity.cpython-313.pyc b/argenta/command/params/flag/__pycache__/entity.cpython-313.pyc new file mode 100644 index 0000000..44ef5fe Binary files /dev/null and b/argenta/command/params/flag/__pycache__/entity.cpython-313.pyc differ diff --git a/argenta/command/params/flag/entity.py b/argenta/command/params/flag/entity.py index ca45eca..c772a4d 100644 --- a/argenta/command/params/flag/entity.py +++ b/argenta/command/params/flag/entity.py @@ -11,6 +11,8 @@ class Flag: self.possible_flag_values = possible_flag_values self.ignore_flag_value_register = ignore_flag_value_register + self._value = None + def get_string_entity(self): if self.ignore_flag_value_register: string_entity: str = self.flag_prefix + self.flag_name.lower() @@ -18,6 +20,12 @@ class Flag: string_entity: str = self.flag_prefix + self.flag_name return string_entity + def get_value(self): + return self._value + + def set_value(self, value): + self._value = value + def validate_input_flag_value(self, input_flag_value: str): if self.possible_flag_values: if self.ignore_flag_value_register: @@ -32,9 +40,3 @@ class Flag: return False else: return True - - - - -c = Flag('s', flag_prefix='---kinn', ignore_flag_value_register=False, possible_flag_values=['abc', 'ASW', 'eBc']) -print(c.get_string_entity()) diff --git a/argenta/command/params/flags_group/__pycache__/__init__.cpython-313.pyc b/argenta/command/params/flags_group/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..e0f1d5f Binary files /dev/null and b/argenta/command/params/flags_group/__pycache__/__init__.cpython-313.pyc differ diff --git a/argenta/command/params/flags_group/__pycache__/entity.cpython-313.pyc b/argenta/command/params/flags_group/__pycache__/entity.cpython-313.pyc new file mode 100644 index 0000000..f51981b Binary files /dev/null and b/argenta/command/params/flags_group/__pycache__/entity.cpython-313.pyc differ diff --git a/argenta/command/params/flags_group/entity.py b/argenta/command/params/flags_group/entity.py index e8c798d..14e5150 100644 --- a/argenta/command/params/flags_group/entity.py +++ b/argenta/command/params/flags_group/entity.py @@ -1,3 +1,6 @@ +from argenta.command.params.flag.entity import Flag + + class FlagsGroup: - def __init__(self, flags): + def __init__(self, flags: list[Flag]): self.flags = flags diff --git a/argenta/input_command/__init__.py b/argenta/command/parse_input_command/__init__.py similarity index 100% rename from argenta/input_command/__init__.py rename to argenta/command/parse_input_command/__init__.py diff --git a/argenta/command/parse_input_command/__pycache__/__init__.cpython-313.pyc b/argenta/command/parse_input_command/__pycache__/__init__.cpython-313.pyc new file mode 100644 index 0000000..e4c8bb6 Binary files /dev/null and b/argenta/command/parse_input_command/__pycache__/__init__.cpython-313.pyc differ diff --git a/argenta/command/parse_input_command/__pycache__/entity.cpython-313.pyc b/argenta/command/parse_input_command/__pycache__/entity.cpython-313.pyc new file mode 100644 index 0000000..0ae991d Binary files /dev/null and b/argenta/command/parse_input_command/__pycache__/entity.cpython-313.pyc differ diff --git a/argenta/command/parse_input_command/entity.py b/argenta/command/parse_input_command/entity.py new file mode 100644 index 0000000..5e463a3 --- /dev/null +++ b/argenta/command/parse_input_command/entity.py @@ -0,0 +1,38 @@ +from typing import Literal, LiteralString +from argenta.command.entity import Command +from argenta.command.params.flag.entity import Flag +from argenta.command.params.flags_group.entity import FlagsGroup +from .exceptions import InvalidInputFlagsException + + +class ParseInputCommand: + def __new__(cls, *args, **kwargs): + raw_command = kwargs['raw_command'] + return ParseInputCommand.parse(raw_command) + + @staticmethod + def parse(raw_command: str) -> Command: + list_of__ = raw_command.split() + command = list_of__[0] + list_of__.pop(0) + + flags = [] + for k, _ in enumerate(list_of__): + if not _.startswith('-') or len( _[:len(_.lstrip('-'))]) > 3: + raise InvalidInputFlagsException() + else: + flag_name: str = _.lstrip('-') + flag_prefix = _[:len(flag_name)] + + parse_flag = Flag(flag_name=flag_name, + flag_prefix=flag_prefix) + + flags.append(parse_flag) + + if len(flags) == 0: + return Command(command=command) + elif len(flags) == 1: + return Command(command=command, flags=flags[0]) + else: + flags = FlagsGroup(flags=flags) + return Command(command=command, flags=flags) diff --git a/argenta/command/parse_input_command/exceptions.py b/argenta/command/parse_input_command/exceptions.py new file mode 100644 index 0000000..7dd5ebd --- /dev/null +++ b/argenta/command/parse_input_command/exceptions.py @@ -0,0 +1,3 @@ +class InvalidInputFlagsException(Exception): + def __str__(self): + return "Invalid Input Flags" diff --git a/argenta/input_command/entity.py b/argenta/input_command/entity.py deleted file mode 100644 index 5b90617..0000000 --- a/argenta/input_command/entity.py +++ /dev/null @@ -1,3 +0,0 @@ -class InputCommand: - pass - diff --git a/argenta/router/entity.py b/argenta/router/entity.py index 88515d5..31e910d 100644 --- a/argenta/router/entity.py +++ b/argenta/router/entity.py @@ -1,4 +1,5 @@ from typing import Callable, Any +from ..command.entity import Command from ..router.exceptions import (UnknownCommandHandlerHasAlreadyBeenCreatedException, RepeatedCommandException) @@ -11,19 +12,19 @@ class Router: self.title = title self.name = name - self._command_entities: list[dict[str, Callable[[], None] | str]] = [] + self._command_entities: list[dict[str, Callable[[], None] | Command]] = [] self.unknown_command_func: Callable[[str], None] | None = None self._is_main_router: bool = False self.ignore_command_register: bool = False - def command(self, command: str, description: str = None) -> Callable[[Any], Any]: + def command(self, command: Command) -> Callable[[Any], Any]: + command.validate_commands_params() self._validate_command(command) def command_decorator(func): self._command_entities.append({'handler_func': func, - 'command': command, - 'description': description}) + 'command': command}) def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper @@ -42,9 +43,10 @@ class Router: return wrapper - def input_command_handler(self, input_command): + def input_command_handler(self, input_command: Command): + input_command_name: str = input_command.get_string_entity() for command_entity in self._command_entities: - if input_command.lower() == command_entity['command'].lower(): + if input_command_name.lower() == command_entity['command'].get_string_entity(): if self.ignore_command_register: return command_entity['handler_func']() else: @@ -56,11 +58,12 @@ class Router: self.unknown_command_func(unknown_command) - def _validate_command(self, command: str): + def _validate_command(self, command: Command): + command_name: str = command.get_string_entity() if command in self.get_all_commands(): raise RepeatedCommandException() if self.ignore_command_register: - if command.lower() in [x.lower() for x in self.get_all_commands()]: + if command_name.lower() in [x.lower() for x in self.get_all_commands()]: raise RepeatedCommandException() @@ -74,7 +77,7 @@ class Router: self.ignore_command_register = ignore_command_register - def get_command_entities(self) -> list[dict[str, Callable[[], None] | str]]: + def get_command_entities(self) -> list[dict[str, Callable[[], None] | Command]]: return self._command_entities @@ -103,6 +106,6 @@ class Router: def get_all_commands(self) -> list[str]: all_commands: list[str] = [] for command_entity in self._command_entities: - all_commands.append(command_entity['command']) + all_commands.append(command_entity['command'].get_string_entity()) return all_commands diff --git a/tests/mock_app/handlers/routers.py b/tests/mock_app/handlers/routers.py index d927fbf..6f0f4d0 100644 --- a/tests/mock_app/handlers/routers.py +++ b/tests/mock_app/handlers/routers.py @@ -1,4 +1,6 @@ from rich.console import Console + +from argenta.command.entity import Command from argenta.router import Router from ..handlers.handlers_implementation.help_command import help_command @@ -12,19 +14,19 @@ settings_router: Router = Router(title='Settings points:') console = Console() -@work_router.command(command='0', description='Get Help') +@work_router.command(command=Command(command='0', description='Get Help')) def command_help(): help_command() -@work_router.command(command='1', description='Start Solving') +'''@work_router.command(command='1', description='Start Solving') def command_start_solving(): start_solving_command() @settings_router.command(command='U', description='Update WordMath') def command_update(): - upgrade_command() + upgrade_command()''' @work_router.unknown_command diff --git a/tests/mock_app/main.py b/tests/mock_app/main.py index 32937fd..810fb7a 100644 --- a/tests/mock_app/main.py +++ b/tests/mock_app/main.py @@ -19,14 +19,14 @@ def main(): goodbye_message: str = f'[bold red]\n{ascii_goodbye_message}{' '*12}made by kolo\n' app.include_router(work_router, is_main=True) - app.include_router(settings_router) + #app.include_router(settings_router) app.set_initial_message(initial_greeting) app.set_farewell_message(goodbye_message) app.set_description_message_pattern('[bold red][{command}][/bold red] [blue]*=*=*[/blue] [bold yellow italic]{description}') - #app.start_polling() + app.start_polling() if __name__ == "__main__": main()