diff --git a/argenta/app/entity.py b/argenta/app/entity.py index e44781c..6861cae 100644 --- a/argenta/app/entity.py +++ b/argenta/app/entity.py @@ -4,10 +4,12 @@ from inspect import getfullargspec from ..command.entity import Command from ..router.entity import Router from ..command.input_comand.entity import InputCommand -from ..command.input_comand.exceptions import (IncorrectInputFlagException, +from ..command.input_comand.exceptions import (UnprocessedInputFlagException, InvalidInputFlagsHandlerHasBeenAlreadyCreatedException, - IncorrectNumberArgsHandlerException, - UnknownCommandHandlerHasBeenAlreadyCreatedException) + IncorrectNumberOfHandlerArgsException, + UnknownCommandHandlerHasBeenAlreadyCreatedException, + RepeatedInputFlagsException, + RepeatedInputFlagsHandlerHasBeenAlreadyCreatedException) from .exceptions import (InvalidRouterInstanceException, InvalidDescriptionMessagePatternException, NoRegisteredRoutersException, @@ -46,6 +48,7 @@ class App: self._routers: list[Router] = [] self._invalid_input_flags_handler: Callable[[str], None] | None = None + self._repeated_input_flags_handler: Callable[[str], None] | None = None self._unknown_command_handler: Callable[[Command], None] | None = None self._registered_router_entities: list[dict[str, str | list[dict[str, Callable[[], None] | Command]] | Router]] = [] self._app_main_router: Router | None = None @@ -72,7 +75,7 @@ class App: try: input_command: InputCommand = InputCommand.parse(raw_command=raw_command) - except IncorrectInputFlagException: + except UnprocessedInputFlagException: self.print_func(self.line_separate) if self._invalid_input_flags_handler: self._invalid_input_flags_handler(raw_command) @@ -82,6 +85,16 @@ class App: if not self.repeat_command_groups: self.print_func(self.prompt) continue + except RepeatedInputFlagsException: + self.print_func(self.line_separate) + if self._repeated_input_flags_handler: + self._repeated_input_flags_handler(raw_command) + else: + self.print_func(f'Repeated input flags: "{raw_command}"') + self.print_func(self.line_separate) + if not self.repeat_command_groups: + self.print_func(self.prompt) + continue self._checking_command_for_exit_command(input_command.get_string_entity()) self.print_func(self.line_separate) @@ -125,18 +138,29 @@ class App: else: args = getfullargspec(handler).args if len(args) != 1: - raise IncorrectNumberArgsHandlerException() + raise IncorrectNumberOfHandlerArgsException() else: self._invalid_input_flags_handler = handler + def set_repeated_input_flags_handler(self, handler: Callable[[str], None]) -> None: + if self._repeated_input_flags_handler: + raise RepeatedInputFlagsHandlerHasBeenAlreadyCreatedException() + else: + args = getfullargspec(handler).args + if len(args) != 1: + raise IncorrectNumberOfHandlerArgsException() + else: + self._repeated_input_flags_handler = handler + + def set_unknown_command_handler(self, handler: Callable[[str], None]) -> None: if self._unknown_command_handler: raise UnknownCommandHandlerHasBeenAlreadyCreatedException() else: args = getfullargspec(handler).args if len(args) != 1: - raise IncorrectNumberArgsHandlerException() + raise IncorrectNumberOfHandlerArgsException() else: self._unknown_command_handler = handler diff --git a/argenta/command/input_comand/entity.py b/argenta/command/input_comand/entity.py index 33c4fa3..4492f91 100644 --- a/argenta/command/input_comand/entity.py +++ b/argenta/command/input_comand/entity.py @@ -1,4 +1,4 @@ -from ..input_comand.exceptions import IncorrectInputFlagException, RepeatedInputFlagsException +from ..input_comand.exceptions import UnprocessedInputFlagException, RepeatedInputFlagsException from ..entity import Command from ..params.flag.flags_group.entity import FlagsGroup from ..params.flag.input_flag.entity import InputFlag @@ -29,12 +29,12 @@ class InputCommand(Command, Generic[T]): if _.startswith('-'): flag_prefix_last_symbol_index = _.rfind('-') if current_flag_name or len(_) < 2 or len(_[:flag_prefix_last_symbol_index]) > 3: - raise IncorrectInputFlagException() + raise UnprocessedInputFlagException() else: current_flag_name = _ else: if not current_flag_name: - raise IncorrectInputFlagException() + raise UnprocessedInputFlagException() else: current_flag_value = _ if current_flag_name and current_flag_value: @@ -55,7 +55,7 @@ class InputCommand(Command, Generic[T]): current_flag_name = None current_flag_value = None if any([current_flag_name, current_flag_value]): - raise IncorrectInputFlagException() + raise UnprocessedInputFlagException() if len(flags.get_flags()) == 0: return InputCommand(command=command) else: diff --git a/argenta/command/input_comand/exceptions.py b/argenta/command/input_comand/exceptions.py index 3cbdb2b..6b89860 100644 --- a/argenta/command/input_comand/exceptions.py +++ b/argenta/command/input_comand/exceptions.py @@ -1,16 +1,9 @@ from ..params.flag.input_flag.entity import InputFlag -class InvalidInputFlagException(Exception): - def __init__(self, flag: InputFlag): - self.flag = flag +class UnprocessedInputFlagException(Exception): def __str__(self): - return ("Invalid Input Flags\n" - f"Unknown or invalid input flag: '{self.flag.get_string_entity()} {self.flag.get_value()}'") - -class IncorrectInputFlagException(Exception): - def __str__(self): - return "Incorrect Input Flags" + return "Unprocessed Input Flags" class RepeatedInputFlagsException(Exception): @@ -26,12 +19,17 @@ class InvalidInputFlagsHandlerHasBeenAlreadyCreatedException(Exception): return "Invalid Input Flags Handler has already been created" +class RepeatedInputFlagsHandlerHasBeenAlreadyCreatedException(Exception): + def __str__(self): + return "Repeated Input Flags Handler has already been created" + + class UnknownCommandHandlerHasBeenAlreadyCreatedException(Exception): def __str__(self): return "Unknown Command Handler has already been created" -class IncorrectNumberArgsHandlerException(Exception): +class IncorrectNumberOfHandlerArgsException(Exception): def __str__(self): return "Incorrect Input Flags Handler has incorrect number of arguments" diff --git a/argenta/command/params/flag/flags_group/entity.py b/argenta/command/params/flag/flags_group/entity.py index a27e4f4..6c3f929 100644 --- a/argenta/command/params/flag/flags_group/entity.py +++ b/argenta/command/params/flag/flags_group/entity.py @@ -20,3 +20,6 @@ class FlagsGroup: def __next__(self): return next(iter(self)) + + def __getitem__(self, item): + return self._flags[item] diff --git a/argenta/router/entity.py b/argenta/router/entity.py index 0e6522d..12aa25b 100644 --- a/argenta/router/entity.py +++ b/argenta/router/entity.py @@ -2,12 +2,12 @@ from typing import Callable, Any from inspect import getfullargspec from ..command.entity import Command from ..command.input_comand.entity import InputCommand -from ..command.input_comand.exceptions import InvalidInputFlagException from ..command.params.flag.flags_group.entity import FlagsGroup from ..router.exceptions import (RepeatedCommandException, RepeatedFlagNameException, - CurrentCommandDoesNotProcessFlagsException, TooManyTransferredArgsException, - RequiredArgumentNotPassedException) + RequiredArgumentNotPassedException, + NotValidInputFlagHandlerHasBeenAlreadyCreatedException, + IncorrectNumberOfHandlerArgsException) class Router: @@ -21,8 +21,7 @@ class Router: self._command_entities: list[dict[str, Callable[[], None] | Command]] = [] self._ignore_command_register: bool = False - self._unknown_command_handler: Callable[[str], None] | None = None - self._not_valid_flag_handler: Callable[[str], None] | None = None + self._not_valid_flag_handler: Callable[[Command], None] | None = None def command(self, command: Command) -> Callable[[Any], Any]: @@ -39,23 +38,46 @@ class Router: return command_decorator + def not_valid_input_flag(self, func): + if self._not_valid_flag_handler: + raise NotValidInputFlagHandlerHasBeenAlreadyCreatedException() + else: + processed_args = getfullargspec(func).args + if len(processed_args) != 1: + raise IncorrectNumberOfHandlerArgsException() + else: + self._not_valid_flag_handler = func + def wrapper(*args, **kwargs): + return func(*args, **kwargs) + + return wrapper + def input_command_handler(self, input_command: InputCommand): input_command_name: str = input_command.get_string_entity() + input_command_flags: FlagsGroup = input_command.get_input_flags() for command_entity in self._command_entities: if input_command_name.lower() == command_entity['command'].get_string_entity().lower(): if command_entity['command'].get_flags(): - if input_command.get_input_flags(): - for flag in input_command.get_input_flags(): + if input_command_flags: + for flag in input_command_flags: is_valid = command_entity['command'].validate_input_flag(flag) if not is_valid: - raise InvalidInputFlagException(flag) - return command_entity['handler_func'](input_command.get_input_flags()) + if self._not_valid_flag_handler: + self._not_valid_flag_handler(input_command) + else: + print(f"Undefined or incorrect input flag: '{flag.get_string_entity()} {flag.get_value()}'") + return + return command_entity['handler_func'](input_command_flags) else: return command_entity['handler_func'](FlagsGroup(None)) else: - if input_command.get_input_flags(): - raise CurrentCommandDoesNotProcessFlagsException() + if input_command_flags: + if self._not_valid_flag_handler: + self._not_valid_flag_handler(input_command) + else: + print(f"Undefined or incorrect input flag: '{input_command_flags[0].get_string_entity()} {input_command_flags[0].get_value()}'") + return else: return command_entity['handler_func']() @@ -111,7 +133,6 @@ class Router: 'ignore_command_register': self._ignore_command_register, 'attributes': { 'command_entities': self._command_entities, - 'unknown_command_func': self._unknown_command_handler } } diff --git a/argenta/router/exceptions.py b/argenta/router/exceptions.py index 18493b9..d3e3469 100644 --- a/argenta/router/exceptions.py +++ b/argenta/router/exceptions.py @@ -1,3 +1,6 @@ +from ..command.params.flag.input_flag.entity import InputFlag + + class InvalidDescriptionInstanceException(Exception): def __str__(self): return "Invalid Description Instance" @@ -13,11 +16,6 @@ class RepeatedFlagNameException(Exception): return "Repeated flag name in register command" -class CurrentCommandDoesNotProcessFlagsException(Exception): - def __str__(self): - return "Current command does not process flags" - - class TooManyTransferredArgsException(Exception): def __str__(self): return "Too many transferred arguments" @@ -26,3 +24,13 @@ class TooManyTransferredArgsException(Exception): class RequiredArgumentNotPassedException(Exception): def __str__(self): return "Required argument not passed" + + +class NotValidInputFlagHandlerHasBeenAlreadyCreatedException(Exception): + def __str__(self): + return "Invalid Input Flag Handler has already been created" + + +class IncorrectNumberOfHandlerArgsException(Exception): + def __str__(self): + return "Incorrect Input Flags Handler has incorrect number of arguments" diff --git a/pyproject.toml b/pyproject.toml index 90ac497..fe60837 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "argenta" -version = "0.3.1" +version = "0.3.2" description = "python library for creating custom shells" authors = [ {name = "kolo",email = "kolo.is.main@gmail.com"} @@ -33,6 +33,4 @@ numpy = "^2.2.2" word2number = "^1.1" numexpr = "^2.10.2" requests = "^2.32.3" -tqdm = "^4.67.1" -setuptools = "^75.8.0" diff --git a/tests/mock_app/handlers/routers.py b/tests/mock_app/handlers/routers.py index 77c94e0..b6e545d 100644 --- a/tests/mock_app/handlers/routers.py +++ b/tests/mock_app/handlers/routers.py @@ -42,3 +42,11 @@ def command_start_solving(argrrtrts: FlagsGroup | None): def command_update(): print('uefi') # upgrade_command() + + +@work_router.not_valid_input_flag +def invalid_input_flag(command): + print('Invalid inpuuuuuuuuuuuuuuuuuuuuuuuut flag') + + + diff --git a/tests/mock_app/main.py b/tests/mock_app/main.py index 70c1e68..5f42cb4 100644 --- a/tests/mock_app/main.py +++ b/tests/mock_app/main.py @@ -5,7 +5,7 @@ from rich.console import Console app: App = App(prompt='[italic white bold]What do you want to do(enter number of action)?', - line_separate='[bold green]\n---------------------------------------------\n', + 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=False) @@ -25,6 +25,8 @@ 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_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}')