step by step

This commit is contained in:
2025-10-09 22:01:06 +03:00
parent b3b5e2e8a8
commit 0a1d462090
5 changed files with 65 additions and 66 deletions
+1 -1
View File
@@ -2,4 +2,4 @@ import argparse
parser = argparse.ArgumentParser(prog='myprogram')
_ = parser.add_argument('--foo', help='foo of the %(prog)s program')
parser.print_help()
print(vars(parser.parse_args()))
+6 -2
View File
@@ -3,6 +3,7 @@ import re
from contextlib import redirect_stdout
from typing import Never, TypeAlias
from argenta.orchestrator.argparser.entity import ArgSpace
from art import text2art # pyright: ignore[reportMissingTypeStubs, reportUnknownVariableType]
from rich.console import Console
from rich.markup import escape
@@ -41,7 +42,8 @@ class BaseApp:
repeat_command_groups: bool,
override_system_messages: bool,
autocompleter: AutoCompleter,
print_func: Printer) -> None:
print_func: Printer,
argspace: ArgSpace | None = None) -> None:
self._prompt: str = prompt
self._print_func: Printer = print_func
self._exit_command: Command = exit_command
@@ -51,6 +53,7 @@ class BaseApp:
self._repeat_command_groups_description: bool = repeat_command_groups
self._override_system_messages: bool = override_system_messages
self._autocompleter: AutoCompleter = autocompleter
self._argspace: ArgSpace | None = argspace
self._farewell_message: str = farewell_message
self._initial_message: str = initial_message
@@ -392,11 +395,12 @@ class App(BaseApp):
print_func=print_func,
)
def run_polling(self) -> None:
def run_polling(self, argspace: ArgSpace | None) -> None:
"""
Private. Starts the user input processing cycle
:return: None
"""
self._argspace = argspace
self._pre_cycle_setup()
while True:
if self._repeat_command_groups_description:
@@ -1,24 +1,26 @@
from abc import ABC, abstractmethod
from typing import Literal, override
class BaseArgument(ABC):
class BaseArgument:
"""
Private. Base class for all arguments
"""
@property
@abstractmethod
def string_entity(self) -> str:
def __init__(self, name: str, *,
help: str,
is_required: bool,
is_deprecated: bool):
"""
Public. Returns the string representation of the argument
:return: the string representation as a str
Public. Boolean argument, does not require a value
:param name: name of the argument
:param help: help message for the argument
:param is_required: whether the argument is required
:param is_deprecated: whether the argument is deprecated
"""
raise NotImplementedError
self.name: str = name
self.help: str = help
self.is_required: bool = is_required
self.is_deprecated: bool = is_deprecated
class RequiredArgument(BaseArgument):
def __init__(self, name: str, *,
prefix: Literal["-", "--", "---"] = "--",
help: str = "Help for required argument",
default: str | None = None,
possible_values: list[str] | None = None,
@@ -27,31 +29,20 @@ class RequiredArgument(BaseArgument):
"""
Public. Required argument at startup
:param name: name of the argument, must not start with minus (-)
:param prefix: prefix of the argument
:param help: help message for the argument
:param default: default value for the argument
:param possible_values: list of possible values for the argument
:param is_required: whether the argument is required
:param is_deprecated: whether the argument is deprecated
"""
self.name: str = name
self.prefix: Literal["-", "--", "---"] = prefix
self.help: str = help
self.default: str | None = default
self.possible_values: list[str] | None = possible_values
self.is_required: bool = is_required
self.is_deprecated: bool = is_deprecated
self.action: str = "store"
@property
@override
def string_entity(self) -> str:
return self.prefix + self.name
super().__init__(name, help=help, is_required=is_required, is_deprecated=is_deprecated)
class ValueArgument(BaseArgument):
def __init__(self, name: str, *,
prefix: Literal["-", "--", "---"] = "--",
help: str = "Help message for the value argument",
possible_values: list[str] | None = None,
default: str | None = None,
@@ -60,50 +51,41 @@ class ValueArgument(BaseArgument):
"""
Public. Value argument, must have the value
:param name: name of the argument
:param prefix: prefix of the argument
:param help: help message for the argument
:param possible_values: list of possible values for the argument
:param default: default value for the argument
:param is_required: whether the argument is required
:param is_deprecated: whether the argument is deprecated
"""
self.name: str = name
self.prefix: Literal["-", "--", "---"] = prefix
self.help: str = help
self.possible_values: list[str] | None = possible_values
self.default: str | None = default
self.is_required: bool = is_required
self.is_deprecated: bool = is_deprecated
self.possible_values: list[str] | None = possible_values
self.action: str = "store"
@property
@override
def string_entity(self) -> str:
return self.prefix + self.name
super().__init__(name, help=help, is_required=is_required, is_deprecated=is_deprecated)
class BooleanArgument(BaseArgument):
def __init__(self, name: str, *,
prefix: Literal["-", "--", "---"] = "--",
help: str = "Help message for the boolean argument",
is_required: bool = False,
is_deprecated: bool = False):
"""
Public. Boolean argument, does not require a value
:param name: name of the argument
:param prefix: prefix of the argument
:param help: help message for the argument
:param is_required: whether the argument is required
:param is_deprecated: whether the argument is deprecated
"""
self.name: str = name
self.prefix: Literal["-", "--", "---"] = prefix
self.help: str = help
self.is_required: bool = is_required
self.is_deprecated: bool = is_deprecated
self.action: str = "store_true"
super().__init__(name, help=help, is_required=is_required, is_deprecated=is_deprecated)
@property
@override
def string_entity(self) -> str:
return self.prefix + self.name
class InputArgument:
def __init__(self, name: str,
value: str | None,
founder_class: type[BaseArgument]) -> None:
self.name: str = name
self.value: str | None = value
self.founder_class: type[BaseArgument] = founder_class
def __str__(self) -> str:
return f"{self.name}={self.value}"
+24 -4
View File
@@ -1,12 +1,30 @@
from argparse import ArgumentParser, Namespace
from typing import Self
from argenta.orchestrator.argparser.arguments.models import (
BaseArgument,
BooleanArgument,
InputArgument,
ValueArgument,
RequiredArgument,
)
class ArgSpace:
def __init__(self, all_arguments: list[InputArgument]) -> None:
self.all_arguments = all_arguments
@classmethod
def from_namespace(cls, namespace: Namespace,
processed_args: list[RequiredArgument | ValueArgument | BooleanArgument]) -> Self:
name_type_paired_args: dict[str, type[BaseArgument]] = {
arg.name: type(arg)
for arg in processed_args
}
return cls([InputArgument(name, value, name_type_paired_args[name])
for name, value in vars(namespace).items()])
class ArgParser:
def __init__(
self,
@@ -31,13 +49,13 @@ class ArgParser:
for arg in processed_args:
if isinstance(arg, BooleanArgument):
_ = self._entity.add_argument(arg.string_entity,
_ = self._entity.add_argument(arg.name,
action=arg.action,
help=arg.help,
required=arg.is_required,
deprecated=arg.is_deprecated)
else:
_ = self._entity.add_argument(arg.string_entity,
_ = self._entity.add_argument(arg.name,
action=arg.action,
help=arg.help,
default=arg.default,
@@ -45,5 +63,7 @@ class ArgParser:
required=arg.is_required,
deprecated=arg.is_deprecated)
def parse_args(self) -> Namespace:
return self._entity.parse_args()
def parse_args(self) -> ArgSpace:
return ArgSpace.from_namespace(namespace=self._entity.parse_args(),
processed_args=self._processed_args)
+5 -12
View File
@@ -1,7 +1,6 @@
from argparse import Namespace
from argenta.app import App
from argenta.orchestrator.argparser import ArgParser
from argenta.orchestrator.argparser.entity import ArgSpace
class Orchestrator:
@@ -19,14 +18,8 @@ class Orchestrator:
:param app: a running application
:return: None
"""
app.run_polling()
def get_input_args(self) -> Namespace | None:
"""
Public. Returns the arguments parsed
:return: None
"""
if self._arg_parser:
return self._arg_parser.parse_args()
if self._arg_parser is not None:
parsed_argspace: ArgSpace = self._arg_parser.parse_args()
app.run_polling(argspace=parsed_argspace)
else:
return None
app.run_polling(argspace=None)