fix type hints with ty help, add ability to configure stdout capture when handling input by the router

This commit is contained in:
2025-05-20 22:44:47 +03:00
parent 45f410e3e8
commit fd287c5da0
15 changed files with 59 additions and 70 deletions
-1
View File
@@ -58,7 +58,6 @@ if __name__ == '__main__':
# Funktionen in der Entwicklung
- Vollständige Unterstützung für Autocompleter unter Linux
- Möglichkeit zur Konfiguration der Standardausgabeerfassung bei der Verarbeitung von Eingaben durch den Handler
## Vollständige [Dokumentation](https://argenta-docs.vercel.app) | MIT 2025 kolo | made by [kolo](https://t.me/kolo_id)
-1
View File
@@ -60,7 +60,6 @@ if __name__ == '__main__':
# Features in development
- Full support for autocompleter on Linux
- Ability to configure stdout capture when handling input by the handler
## Full [docs](https://argenta-docs.vercel.app) | MIT 2025 kolo | made by [kolo](https://t.me/kolo_id)
-1
View File
@@ -58,7 +58,6 @@ if __name__ == '__main__':
# Фичи в разработке
- Полноценная поддержка автокомплитера на Linux
- Возможность настройки захвата stdout при обработке хэндлером ввода
## Полная [документация](https://argenta-docs.vercel.app) | MIT 2025 kolo | made by [kolo](https://t.me/kolo_id)
+4 -7
View File
@@ -10,19 +10,16 @@ from argenta.orchestrator import Orchestrator
router = Router()
for i in range(10000):
trigger = f"cmd{i}"
@router.command(Command(trigger, aliases=[f'dfs{i}']))
def handler(response: Response):
print(response.status)
@router.command(Command('case are'))
def handler(response: Response):
print(response.status)
app = App(repeat_command_groups=False)
app.include_router(router)
print(get_time_of_pre_cycle_setup(app))
app.run_polling()
+1 -1
View File
@@ -21,7 +21,7 @@ console = Console()
)
)
def command_help(response: Response):
case = input('test')
case = input('test > ')
print(case)
print(response.status)
print(response.undefined_flags.get_flags())
+1 -6
View File
@@ -1,6 +1,6 @@
[project]
name = "argenta"
version = "1.0.5"
version = "1.0.6"
description = "Python library for building modular CLI applications"
authors = [{ name = "kolo", email = "kolo.is.main@gmail.com" }]
requires-python = ">=3.8"
@@ -26,8 +26,3 @@ exclude = [
requires = ["hatchling"]
build-backend = "hatchling.build"
[dependency-groups]
dev = [
"pandas>=2.0.3",
]
+1 -1
View File
@@ -5,7 +5,7 @@ from typing import Never
class AutoCompleter:
def __init__(
self, history_filename: str = False, autocomplete_button: str = "tab"
self, history_filename: str | None = None, autocomplete_button: str = "tab"
) -> None:
"""
Public. Configures and implements auto-completion of input command
+19 -12
View File
@@ -208,13 +208,12 @@ class BaseApp:
:param raw_command: the raw input command
:return: None
"""
match error:
case UnprocessedInputFlagException():
self._incorrect_input_syntax_handler(raw_command)
case RepeatedInputFlagsException():
self._repeated_input_flags_handler(raw_command)
case EmptyInputCommandException():
self._empty_input_command_handler()
if isinstance(error, UnprocessedInputFlagException):
self._incorrect_input_syntax_handler(raw_command)
elif isinstance(error, RepeatedInputFlagsException):
self._repeated_input_flags_handler(raw_command)
elif isinstance(error, EmptyInputCommandException):
self._empty_input_command_handler()
def _setup_system_router(self) -> None:
"""
@@ -258,11 +257,11 @@ class BaseApp:
"""
self._prompt = "[italic dim bold]What do you want to do?\n"
self._initial_message = (
f"\n[bold red]{text2art(self._initial_message, font='tarty1')}\n"
"\n"+f"[bold red]{text2art(self._initial_message, font='tarty1')}"+"\n"
)
self._farewell_message = (
f"[bold red]\n{text2art(f'\n{self._farewell_message}\n', font='chanky')}[/bold red]\n"
f"[red i]github.com/koloideal/Argenta[/red i] | [red bold i]made by kolo[/red bold i]\n"
"[bold red]\n\n"+text2art(self._farewell_message, font='chanky')+"\n[/bold red]\n"
"[red i]github.com/koloideal/Argenta[/red i] | [red bold i]made by kolo[/red bold i]\n"
)
self._description_message_gen = lambda command, description: (
f"[bold red]{escape('[' + command + ']')}[/bold red] "
@@ -425,12 +424,20 @@ class App(BaseApp):
for registered_router in self._registered_routers:
if registered_router.disable_redirect_stdout:
registered_router.finds_appropriate_handler(input_command)
if isinstance(self._dividing_line, StaticDividingLine):
self._print_func(self._dividing_line.get_full_static_line(self._override_system_messages))
registered_router.finds_appropriate_handler(input_command)
self._print_func(self._dividing_line.get_full_static_line(self._override_system_messages))
else:
self._print_func(StaticDividingLine(self._dividing_line.get_unit_part()).get_full_static_line(self._override_system_messages))
registered_router.finds_appropriate_handler(input_command)
self._print_func(StaticDividingLine(self._dividing_line.get_unit_part()).get_full_static_line(self._override_system_messages))
else:
with redirect_stdout(io.StringIO()) as f:
registered_router.finds_appropriate_handler(input_command)
res: str = f.getvalue()
self._print_framed_text(res)
if res:
self._print_framed_text(res)
def include_router(self, router: Router) -> None:
"""
+1 -1
View File
@@ -4,7 +4,7 @@ from argenta.router import Router
class RegisteredRouters:
def __init__(self, registered_routers: list[Router] = None) -> None:
def __init__(self, registered_routers: list[Router] | None = None) -> None:
"""
Private. Combines registered routers
:param registered_routers: list of the registered routers
+1 -1
View File
@@ -87,7 +87,7 @@ class Flag(BaseFlag):
class InputFlag(BaseFlag):
def __init__(
self, name: str, prefix: Literal["-", "--", "---"] = "--", value: str = None
self, name: str, prefix: Literal["-", "--", "---"] = "--", value: str | None = None
):
"""
Public. The entity of the flag of the entered command
+7 -10
View File
@@ -5,10 +5,7 @@ from argenta.command.exceptions import (
RepeatedInputFlagsException,
EmptyInputCommandException,
)
from typing import Generic, TypeVar, cast, Literal
InputCommandType = TypeVar("InputCommandType")
from typing import cast, Literal
class BaseCommand:
@@ -31,9 +28,9 @@ class Command(BaseCommand):
def __init__(
self,
trigger: str,
description: str = None,
flags: Flag | Flags = None,
aliases: list[str] = None,
description: str | None = None,
flags: Flag | Flags | None = None,
aliases: list[str] | None = None,
):
"""
Public. The command that can and should be registered in the Router
@@ -109,8 +106,8 @@ class Command(BaseCommand):
return self._description
class InputCommand(BaseCommand, Generic[InputCommandType]):
def __init__(self, trigger: str, input_flags: InputFlag | InputFlags = None):
class InputCommand(BaseCommand):
def __init__(self, trigger: str, input_flags: InputFlag | InputFlags | None = None):
"""
Private. The model of the input command, after parsing
:param trigger:the trigger of the command
@@ -142,7 +139,7 @@ class InputCommand(BaseCommand, Generic[InputCommandType]):
return self._input_flags
@staticmethod
def parse(raw_command: str) -> InputCommandType:
def parse(raw_command: str) -> 'InputCommand':
"""
Private. Parse the raw input command
:param raw_command: raw input command
+2 -2
View File
@@ -5,13 +5,13 @@ from argenta.orchestrator.argparser import ArgParser
class Orchestrator:
def __init__(self, arg_parser: ArgParser = False):
def __init__(self, arg_parser: ArgParser | None = None):
"""
Public. An orchestrator and configurator that defines the behavior of an integrated system, one level higher than the App
:param arg_parser: Cmd argument parser and configurator at startup
:return: None
"""
self.arg_parser: ArgParser | False = arg_parser
self.arg_parser: ArgParser | None = arg_parser
if arg_parser:
self.arg_parser.register_args()
+1 -1
View File
@@ -11,7 +11,7 @@ class Response:
def __init__(
self,
status: Status = None,
status: Status | None = None,
valid_flags: ValidInputFlags = ValidInputFlags(),
undefined_flags: UndefinedInputFlags = UndefinedInputFlags(),
invalid_value_flags: InvalidValueInputFlags = InvalidValueInputFlags(),
+1 -1
View File
@@ -38,7 +38,7 @@ class CommandHandler:
class CommandHandlers:
def __init__(self, command_handlers: list[CommandHandler] = None):
def __init__(self, command_handlers: list[CommandHandler] | None = None):
"""
Private. The model that unites all CommandHandler of the routers
:param command_handlers: list of CommandHandlers for register
+20 -24
View File
@@ -45,13 +45,15 @@ class Router:
:param command: Registered command
:return: decorated handler as Callable
"""
self._validate_command(command)
if isinstance(command, str):
command = Command(command)
redefined_command = Command(command)
else:
redefined_command = command
self._validate_command(redefined_command)
def command_decorator(func):
Router._validate_func_args(func)
self._command_handlers.add_handler(CommandHandler(func, command))
self._command_handlers.add_handler(CommandHandler(func, redefined_command))
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
@@ -123,13 +125,12 @@ class Router:
flag_status: Literal["Undefined", "Valid", "Invalid"] = (
handled_command.validate_input_flag(flag)
)
match flag_status:
case "Valid":
valid_input_flags.add_flag(flag)
case "Undefined":
undefined_input_flags.add_flag(flag)
case "Invalid":
invalid_value_input_flags.add_flag(flag)
if flag_status == "Valid":
valid_input_flags.add_flag(flag)
elif flag_status == "Undefined":
undefined_input_flags.add_flag(flag)
elif flag_status == "Invalid":
invalid_value_input_flags.add_flag(flag)
if (
not invalid_value_input_flags.get_flags()
@@ -163,19 +164,14 @@ class Router:
:param command: validated command
:return: None if command is valid else raise exception
"""
match type(command).__name__:
case "Command":
command_name: str = command.get_trigger()
if command_name.find(" ") != -1:
raise TriggerContainSpacesException()
flags: Flags = command.get_registered_flags()
if flags:
flags_name: list = [x.get_string_entity().lower() for x in flags]
if len(set(flags_name)) < len(flags_name):
raise RepeatedFlagNameException()
case "str":
if command.find(" ") != -1:
raise TriggerContainSpacesException()
command_name: str = command.get_trigger()
if command_name.find(" ") != -1:
raise TriggerContainSpacesException()
flags: Flags = command.get_registered_flags()
if flags:
flags_name: list = [x.get_string_entity().lower() for x in flags]
if len(set(flags_name)) < len(flags_name):
raise RepeatedFlagNameException()
@staticmethod
def _validate_func_args(func: Callable) -> None:
@@ -197,7 +193,7 @@ class Router:
if arg_annotation is Response:
pass
else:
file_path: str = getsourcefile(func)
file_path: str | None = getsourcefile(func)
source_line: int = getsourcelines(func)[1]
fprint = Console().print
fprint(f'\nFile "{file_path}", line {source_line}\n[b red]WARNING:[/b red] [i]The typehint '