argenta 1.1.1rc0__py3-none-any.whl → 1.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- argenta/__init__.py +6 -0
- argenta/app/__init__.py +10 -1
- argenta/app/autocompleter/entity.py +18 -19
- argenta/app/defaults.py +0 -1
- argenta/app/dividing_line/models.py +5 -5
- argenta/app/models.py +226 -140
- argenta/app/protocols.py +22 -0
- argenta/app/registered_routers/entity.py +7 -14
- argenta/command/__init__.py +11 -2
- argenta/command/exceptions.py +20 -13
- argenta/command/flag/__init__.py +5 -11
- argenta/command/flag/defaults.py +19 -24
- argenta/command/flag/flags/__init__.py +2 -8
- argenta/command/flag/flags/models.py +65 -49
- argenta/command/flag/models.py +78 -93
- argenta/command/models.py +100 -144
- argenta/di/__init__.py +2 -0
- argenta/di/integration.py +45 -0
- argenta/di/providers.py +14 -0
- argenta/metrics/main.py +2 -2
- argenta/orchestrator/__init__.py +2 -2
- argenta/orchestrator/argparser/__init__.py +6 -1
- argenta/orchestrator/argparser/arguments/__init__.py +3 -3
- argenta/orchestrator/argparser/arguments/models.py +61 -35
- argenta/orchestrator/argparser/entity.py +56 -37
- argenta/orchestrator/entity.py +20 -18
- argenta/py.typed +0 -0
- argenta/response/__init__.py +2 -2
- argenta/response/entity.py +17 -18
- argenta/response/status.py +12 -1
- argenta/router/__init__.py +2 -2
- argenta/router/command_handler/entity.py +9 -27
- argenta/router/entity.py +133 -160
- argenta/router/exceptions.py +9 -12
- {argenta-1.1.1rc0.dist-info → argenta-1.1.2.dist-info}/METADATA +12 -5
- argenta-1.1.2.dist-info/RECORD +44 -0
- argenta-1.1.1rc0.dist-info/RECORD +0 -39
- {argenta-1.1.1rc0.dist-info → argenta-1.1.2.dist-info}/WHEEL +0 -0
- {argenta-1.1.1rc0.dist-info → argenta-1.1.2.dist-info}/licenses/LICENSE +0 -0
argenta/command/models.py
CHANGED
@@ -1,35 +1,28 @@
|
|
1
|
-
from argenta.command.flag.models import Flag, InputFlag
|
1
|
+
from argenta.command.flag.models import Flag, InputFlag, ValidationStatus
|
2
2
|
from argenta.command.flag.flags.models import InputFlags, Flags
|
3
3
|
from argenta.command.exceptions import (
|
4
4
|
UnprocessedInputFlagException,
|
5
5
|
RepeatedInputFlagsException,
|
6
6
|
EmptyInputCommandException,
|
7
7
|
)
|
8
|
-
from typing import cast, Literal
|
8
|
+
from typing import Never, Self, cast, Literal
|
9
9
|
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
"""
|
14
|
-
Private. Base class for all commands
|
15
|
-
:param trigger: A string trigger, which, when entered by the user, indicates that the input corresponds to the command
|
16
|
-
"""
|
17
|
-
self._trigger = trigger
|
11
|
+
ParseFlagsResult = tuple[InputFlags, str | None, str | None]
|
12
|
+
ParseResult = tuple[str, InputFlags]
|
18
13
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
"""
|
24
|
-
return self._trigger
|
14
|
+
MIN_FLAG_PREFIX: str = "-"
|
15
|
+
DEFAULT_WITHOUT_FLAGS: Flags = Flags()
|
16
|
+
|
17
|
+
DEFAULT_WITHOUT_INPUT_FLAGS: InputFlags = InputFlags()
|
25
18
|
|
26
19
|
|
27
|
-
class Command
|
20
|
+
class Command:
|
28
21
|
def __init__(
|
29
22
|
self,
|
30
|
-
trigger: str,
|
23
|
+
trigger: str, *,
|
31
24
|
description: str | None = None,
|
32
|
-
flags: Flag | Flags
|
25
|
+
flags: Flag | Flags = DEFAULT_WITHOUT_FLAGS,
|
33
26
|
aliases: list[str] | None = None,
|
34
27
|
):
|
35
28
|
"""
|
@@ -39,157 +32,120 @@ class Command(BaseCommand):
|
|
39
32
|
:param flags: processed commands
|
40
33
|
:param aliases: string synonyms for the main trigger
|
41
34
|
"""
|
42
|
-
|
43
|
-
self.
|
44
|
-
|
45
|
-
|
46
|
-
else Flags(flags)
|
47
|
-
if isinstance(flags, Flag)
|
48
|
-
else Flags()
|
49
|
-
)
|
50
|
-
self._description = "Very useful command" if not description else description
|
51
|
-
self._aliases = aliases if isinstance(aliases, list) else []
|
52
|
-
|
53
|
-
def get_registered_flags(self) -> Flags:
|
54
|
-
"""
|
55
|
-
Private. Returns the registered flags
|
56
|
-
:return: the registered flags as Flags
|
57
|
-
"""
|
58
|
-
return self._registered_flags
|
59
|
-
|
60
|
-
def get_aliases(self) -> list[str] | list:
|
61
|
-
"""
|
62
|
-
Public. Returns the aliases of the command
|
63
|
-
:return: the aliases of the command as list[str] | list
|
64
|
-
"""
|
65
|
-
return self._aliases
|
35
|
+
self.registered_flags: Flags = flags if isinstance(flags, Flags) else Flags([flags])
|
36
|
+
self.trigger: str = trigger
|
37
|
+
self.description: str = description if description else "Command without description"
|
38
|
+
self.aliases: list[str] = aliases if aliases else []
|
66
39
|
|
67
40
|
def validate_input_flag(
|
68
41
|
self, flag: InputFlag
|
69
|
-
) ->
|
42
|
+
) -> ValidationStatus:
|
70
43
|
"""
|
71
44
|
Private. Validates the input flag
|
72
45
|
:param flag: input flag for validation
|
73
46
|
:return: is input flag valid as bool
|
74
47
|
"""
|
75
|
-
registered_flags: Flags
|
76
|
-
|
77
|
-
if
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
)
|
82
|
-
if is_valid:
|
83
|
-
return "Valid"
|
84
|
-
else:
|
85
|
-
return "Invalid"
|
48
|
+
registered_flags: Flags = self.registered_flags
|
49
|
+
for registered_flag in registered_flags:
|
50
|
+
if registered_flag.string_entity == flag.string_entity:
|
51
|
+
is_valid = registered_flag.validate_input_flag_value(flag.input_value)
|
52
|
+
if is_valid:
|
53
|
+
return ValidationStatus.VALID
|
86
54
|
else:
|
87
|
-
return
|
88
|
-
|
89
|
-
for registered_flag in registered_flags:
|
90
|
-
if registered_flag.get_string_entity() == flag.get_string_entity():
|
91
|
-
is_valid = registered_flag.validate_input_flag_value(
|
92
|
-
flag.get_value()
|
93
|
-
)
|
94
|
-
|
95
|
-
if is_valid:
|
96
|
-
return "Valid"
|
97
|
-
else:
|
98
|
-
return "Invalid"
|
99
|
-
return "Undefined"
|
100
|
-
return "Undefined"
|
101
|
-
|
102
|
-
def get_description(self) -> str:
|
103
|
-
"""
|
104
|
-
Private. Returns the description of the command
|
105
|
-
:return: the description of the command as str
|
106
|
-
"""
|
107
|
-
return self._description
|
55
|
+
return ValidationStatus.INVALID
|
56
|
+
return ValidationStatus.UNDEFINED
|
108
57
|
|
109
58
|
|
110
|
-
class InputCommand
|
111
|
-
def __init__(self, trigger: str,
|
59
|
+
class InputCommand:
|
60
|
+
def __init__(self, trigger: str, *,
|
61
|
+
input_flags: InputFlag | InputFlags = DEFAULT_WITHOUT_INPUT_FLAGS):
|
112
62
|
"""
|
113
63
|
Private. The model of the input command, after parsing
|
114
64
|
:param trigger:the trigger of the command
|
115
65
|
:param input_flags: the input flags
|
116
66
|
:return: None
|
117
67
|
"""
|
118
|
-
|
119
|
-
self.
|
120
|
-
input_flags
|
121
|
-
if isinstance(input_flags, InputFlags)
|
122
|
-
else InputFlags(input_flags)
|
123
|
-
if isinstance(input_flags, InputFlag)
|
124
|
-
else InputFlags()
|
125
|
-
)
|
126
|
-
|
127
|
-
def _set_input_flags(self, input_flags: InputFlags) -> None:
|
128
|
-
"""
|
129
|
-
Private. Sets the input flags
|
130
|
-
:param input_flags: the input flags to set
|
131
|
-
:return: None
|
132
|
-
"""
|
133
|
-
self._input_flags = input_flags
|
134
|
-
|
135
|
-
def get_input_flags(self) -> InputFlags:
|
136
|
-
"""
|
137
|
-
Private. Returns the input flags
|
138
|
-
:return: the input flags as InputFlags
|
139
|
-
"""
|
140
|
-
return self._input_flags
|
68
|
+
self.trigger: str = trigger
|
69
|
+
self.input_flags: InputFlags = input_flags if isinstance(input_flags, InputFlags) else InputFlags([input_flags])
|
141
70
|
|
142
|
-
@
|
143
|
-
def parse(raw_command: str) ->
|
71
|
+
@classmethod
|
72
|
+
def parse(cls, raw_command: str) -> Self:
|
144
73
|
"""
|
145
74
|
Private. Parse the raw input command
|
146
75
|
:param raw_command: raw input command
|
147
76
|
:return: model of the input command, after parsing as InputCommand
|
148
77
|
"""
|
149
|
-
|
150
|
-
raise EmptyInputCommandException()
|
78
|
+
trigger, input_flags = CommandParser(raw_command).parse_raw_command()
|
151
79
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
else:
|
164
|
-
if not current_flag_name or current_flag_value:
|
165
|
-
raise UnprocessedInputFlagException()
|
166
|
-
current_flag_value = _
|
167
|
-
|
168
|
-
if current_flag_name:
|
169
|
-
if not len(list_of_tokens) == k + 1:
|
170
|
-
if not list_of_tokens[k + 1].startswith("-"):
|
171
|
-
continue
|
172
|
-
|
173
|
-
input_flag = InputFlag(
|
174
|
-
name=current_flag_name[current_flag_name.rfind("-") + 1 :],
|
175
|
-
prefix=cast(
|
176
|
-
Literal["-", "--", "---"],
|
177
|
-
current_flag_name[: current_flag_name.rfind("-") + 1],
|
178
|
-
),
|
179
|
-
value=current_flag_value,
|
180
|
-
)
|
181
|
-
|
182
|
-
all_flags = [
|
183
|
-
flag.get_string_entity() for flag in input_flags.get_flags()
|
184
|
-
]
|
185
|
-
if input_flag.get_string_entity() not in all_flags:
|
186
|
-
input_flags.add_flag(input_flag)
|
187
|
-
else:
|
188
|
-
raise RepeatedInputFlagsException(input_flag)
|
80
|
+
return cls(trigger=trigger, input_flags=input_flags)
|
81
|
+
|
82
|
+
|
83
|
+
class CommandParser:
|
84
|
+
def __init__(self, raw_command: str) -> None:
|
85
|
+
self.raw_command: str = raw_command
|
86
|
+
self._parsed_input_flags: InputFlags = InputFlags()
|
87
|
+
|
88
|
+
def parse_raw_command(self) -> ParseResult:
|
89
|
+
if not self.raw_command:
|
90
|
+
raise EmptyInputCommandException()
|
189
91
|
|
190
|
-
|
92
|
+
input_flags, crnt_flag_name, crnt_flag_val = self._parse_flags(self.raw_command.split()[1:])
|
191
93
|
|
192
|
-
if any([
|
94
|
+
if any([crnt_flag_name, crnt_flag_val]):
|
193
95
|
raise UnprocessedInputFlagException()
|
194
96
|
else:
|
195
|
-
return
|
97
|
+
return (self.raw_command.split()[0], input_flags)
|
98
|
+
|
99
|
+
def _parse_flags(self, _tokens: list[str] | list[Never]) -> ParseFlagsResult:
|
100
|
+
crnt_flg_name, crnt_flg_val = None, None
|
101
|
+
for index, token in enumerate(_tokens):
|
102
|
+
crnt_flg_name, crnt_flg_val = _parse_single_token(token, crnt_flg_name, crnt_flg_val)
|
103
|
+
|
104
|
+
if not crnt_flg_name or self._is_next_token_value(index, _tokens):
|
105
|
+
continue
|
106
|
+
|
107
|
+
input_flag = InputFlag(
|
108
|
+
name=crnt_flg_name[crnt_flg_name.rfind(MIN_FLAG_PREFIX) + 1:],
|
109
|
+
prefix=cast(
|
110
|
+
Literal["-", "--", "---"],
|
111
|
+
crnt_flg_name[:crnt_flg_name.rfind(MIN_FLAG_PREFIX) + 1],
|
112
|
+
),
|
113
|
+
input_value=crnt_flg_val,
|
114
|
+
status=None
|
115
|
+
)
|
116
|
+
|
117
|
+
if input_flag in self._parsed_input_flags:
|
118
|
+
raise RepeatedInputFlagsException(input_flag)
|
119
|
+
|
120
|
+
self._parsed_input_flags.add_flag(input_flag)
|
121
|
+
crnt_flg_name, crnt_flg_val = None, None
|
122
|
+
|
123
|
+
return (self._parsed_input_flags, crnt_flg_name, crnt_flg_val)
|
124
|
+
|
125
|
+
def _is_next_token_value(self, current_index: int,
|
126
|
+
_tokens: list[str] | list[Never]) -> bool:
|
127
|
+
next_index = current_index + 1
|
128
|
+
if next_index >= len(_tokens):
|
129
|
+
return False
|
130
|
+
|
131
|
+
next_token = _tokens[next_index]
|
132
|
+
return not next_token.startswith(MIN_FLAG_PREFIX)
|
133
|
+
|
134
|
+
def _parse_single_token(
|
135
|
+
token: str,
|
136
|
+
crnt_flag_name: str | None,
|
137
|
+
crnt_flag_val: str | None
|
138
|
+
) -> tuple[str | None, str | None]:
|
139
|
+
if not token.startswith(MIN_FLAG_PREFIX):
|
140
|
+
if not crnt_flag_name or crnt_flag_val:
|
141
|
+
raise UnprocessedInputFlagException
|
142
|
+
return crnt_flag_name, token
|
143
|
+
|
144
|
+
prefix = token[:token.rfind(MIN_FLAG_PREFIX)]
|
145
|
+
if len(token) < 2 or len(prefix) > 2:
|
146
|
+
raise UnprocessedInputFlagException
|
147
|
+
|
148
|
+
new_flag_name = token
|
149
|
+
new_flag_value = None
|
150
|
+
|
151
|
+
return new_flag_name, new_flag_value
|
argenta/di/__init__.py
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
__all__ = ["inject", "setup_dishka", "FromDishka"]
|
2
|
+
|
3
|
+
from typing import Any, Callable, TypeVar
|
4
|
+
|
5
|
+
from dishka import Container, FromDishka
|
6
|
+
from dishka.integrations.base import wrap_injection, is_dishka_injected
|
7
|
+
|
8
|
+
from argenta.response import Response
|
9
|
+
from argenta.app import App
|
10
|
+
|
11
|
+
|
12
|
+
T = TypeVar("T")
|
13
|
+
|
14
|
+
|
15
|
+
def inject(func: Callable[..., T]) -> Callable[..., T]:
|
16
|
+
return wrap_injection(
|
17
|
+
func=func,
|
18
|
+
is_async=False,
|
19
|
+
container_getter=_get_container_from_response,
|
20
|
+
)
|
21
|
+
|
22
|
+
|
23
|
+
def setup_dishka(app: App, *, auto_inject: bool = False) -> None:
|
24
|
+
if auto_inject:
|
25
|
+
_auto_inject_handlers(app)
|
26
|
+
|
27
|
+
|
28
|
+
def _get_container_from_response(
|
29
|
+
args: tuple[Any, ...], kwargs: dict[str, Any]
|
30
|
+
) -> Container:
|
31
|
+
for arg in args:
|
32
|
+
if isinstance(arg, Response):
|
33
|
+
if hasattr(arg, "_dishka_container"):
|
34
|
+
return arg._dishka_container # pyright: ignore[reportPrivateUsage]
|
35
|
+
break
|
36
|
+
|
37
|
+
raise RuntimeError("dishka container not found in Response")
|
38
|
+
|
39
|
+
|
40
|
+
def _auto_inject_handlers(app: App) -> None:
|
41
|
+
for router in app.registered_routers:
|
42
|
+
for command_handler in router.command_handlers:
|
43
|
+
if not is_dishka_injected(command_handler.handler_as_func):
|
44
|
+
injected_handler = inject(command_handler.handler_as_func)
|
45
|
+
command_handler.handler_as_func = injected_handler
|
argenta/di/providers.py
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
from argenta.orchestrator.argparser import ArgParser
|
2
|
+
from dishka import Provider, provide, Scope
|
3
|
+
|
4
|
+
from argenta.orchestrator.argparser.entity import ArgSpace
|
5
|
+
|
6
|
+
|
7
|
+
class SystemProvider(Provider):
|
8
|
+
def __init__(self, arg_parser: ArgParser):
|
9
|
+
super().__init__()
|
10
|
+
self._arg_parser: ArgParser = arg_parser
|
11
|
+
|
12
|
+
@provide(scope=Scope.APP)
|
13
|
+
def get_argspace(self) -> ArgSpace:
|
14
|
+
return self._arg_parser.parse_args()
|
argenta/metrics/main.py
CHANGED
@@ -2,7 +2,7 @@ import io
|
|
2
2
|
from contextlib import redirect_stdout
|
3
3
|
from time import time
|
4
4
|
|
5
|
-
from argenta
|
5
|
+
from argenta import App
|
6
6
|
|
7
7
|
|
8
8
|
def get_time_of_pre_cycle_setup(app: App) -> float:
|
@@ -13,6 +13,6 @@ def get_time_of_pre_cycle_setup(app: App) -> float:
|
|
13
13
|
"""
|
14
14
|
start = time()
|
15
15
|
with redirect_stdout(io.StringIO()):
|
16
|
-
app.
|
16
|
+
app._pre_cycle_setup() # pyright: ignore[reportPrivateUsage]
|
17
17
|
end = time()
|
18
18
|
return end - start
|
argenta/orchestrator/__init__.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
__all__ = ["BooleanArgument", "
|
1
|
+
__all__ = ["BooleanArgument", "ValueArgument", "InputArgument"]
|
2
2
|
|
3
3
|
|
4
4
|
from argenta.orchestrator.argparser.arguments.models import (
|
5
5
|
BooleanArgument,
|
6
|
-
|
7
|
-
|
6
|
+
ValueArgument,
|
7
|
+
InputArgument
|
8
8
|
)
|
@@ -1,56 +1,82 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
1
|
from typing import Literal
|
3
2
|
|
4
3
|
|
5
|
-
class BaseArgument
|
4
|
+
class BaseArgument:
|
6
5
|
"""
|
7
6
|
Private. Base class for all arguments
|
8
7
|
"""
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
Public. Returns the string representation of the argument
|
14
|
-
:return: the string representation as a str
|
8
|
+
def __init__(self, name: str, *,
|
9
|
+
help: str,
|
10
|
+
is_deprecated: bool,
|
11
|
+
prefix: Literal["-", "--", "---"]):
|
15
12
|
"""
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
"""
|
22
|
-
Public. Required argument at startup
|
23
|
-
:param name: name of the argument, must not start with minus (-)
|
13
|
+
Public. Boolean argument, does not require a value
|
14
|
+
:param name: name of the argument
|
15
|
+
:param help: help message for the argument
|
16
|
+
:param is_required: whether the argument is required
|
17
|
+
:param is_deprecated: whether the argument is deprecated
|
24
18
|
"""
|
25
|
-
self.name = name
|
26
|
-
|
27
|
-
|
28
|
-
|
19
|
+
self.name: str = name
|
20
|
+
self.help: str = help
|
21
|
+
self.is_deprecated: bool = is_deprecated
|
22
|
+
self.prefix: Literal["-", "--", "---"] = prefix
|
23
|
+
|
24
|
+
@property
|
25
|
+
def string_entity(self) -> str:
|
26
|
+
return self.prefix + self.name
|
29
27
|
|
30
28
|
|
31
|
-
class
|
32
|
-
def __init__(self, name: str,
|
29
|
+
class ValueArgument(BaseArgument):
|
30
|
+
def __init__(self, name: str, *,
|
31
|
+
prefix: Literal["-", "--", "---"] = "--",
|
32
|
+
help: str = "Help message for the value argument",
|
33
|
+
possible_values: list[str] | None = None,
|
34
|
+
default: str | None = None,
|
35
|
+
is_required: bool = False,
|
36
|
+
is_deprecated: bool = False):
|
33
37
|
"""
|
34
|
-
Public.
|
38
|
+
Public. Value argument, must have the value
|
35
39
|
:param name: name of the argument
|
36
|
-
:param prefix: prefix
|
40
|
+
:param prefix: prefix for the argument
|
41
|
+
:param help: help message for the argument
|
42
|
+
:param possible_values: list of possible values for the argument
|
43
|
+
:param default: default value for the argument
|
44
|
+
:param is_required: whether the argument is required
|
45
|
+
:param is_deprecated: whether the argument is deprecated
|
37
46
|
"""
|
38
|
-
self.
|
39
|
-
self.
|
40
|
-
|
41
|
-
|
42
|
-
|
47
|
+
self.default: str | None = default
|
48
|
+
self.possible_values: list[str] | None = possible_values
|
49
|
+
self.is_required: bool = is_required
|
50
|
+
self.action: str = "store"
|
51
|
+
super().__init__(name, prefix=prefix, help=help, is_deprecated=is_deprecated)
|
43
52
|
|
44
53
|
|
45
54
|
class BooleanArgument(BaseArgument):
|
46
|
-
def __init__(self, name: str,
|
55
|
+
def __init__(self, name: str, *,
|
56
|
+
prefix: Literal["-", "--", "---"] = "--",
|
57
|
+
help: str = "Help message for the boolean argument",
|
58
|
+
is_deprecated: bool = False):
|
47
59
|
"""
|
48
60
|
Public. Boolean argument, does not require a value
|
49
61
|
:param name: name of the argument
|
50
|
-
:param
|
62
|
+
:param help: help message for the argument
|
63
|
+
:param is_required: whether the argument is required
|
64
|
+
:param is_deprecated: whether the argument is deprecated
|
51
65
|
"""
|
52
|
-
self.
|
53
|
-
|
66
|
+
self.action: str = "store_true"
|
67
|
+
super().__init__(name, prefix=prefix, help=help, is_deprecated=is_deprecated)
|
54
68
|
|
55
|
-
|
56
|
-
|
69
|
+
|
70
|
+
class InputArgument:
|
71
|
+
def __init__(self, name: str,
|
72
|
+
value: str | None,
|
73
|
+
founder_class: type[BaseArgument]) -> None:
|
74
|
+
self.name: str = name
|
75
|
+
self.value: str | None = value
|
76
|
+
self.founder_class: type[BaseArgument] = founder_class
|
77
|
+
|
78
|
+
def __str__(self) -> str:
|
79
|
+
return f"InputArgument({self.name}={self.value})"
|
80
|
+
|
81
|
+
def __repr__(self) -> str:
|
82
|
+
return f"InputArgument<name={self.name}, value={self.value}, founder_class={self.founder_class.__name__}>"
|
@@ -1,16 +1,44 @@
|
|
1
|
-
from argparse import ArgumentParser
|
1
|
+
from argparse import ArgumentParser, Namespace
|
2
|
+
from typing import Never, Self
|
2
3
|
|
3
4
|
from argenta.orchestrator.argparser.arguments.models import (
|
5
|
+
BaseArgument,
|
4
6
|
BooleanArgument,
|
5
|
-
|
6
|
-
|
7
|
+
InputArgument,
|
8
|
+
ValueArgument
|
7
9
|
)
|
8
10
|
|
11
|
+
|
12
|
+
class ArgSpace:
|
13
|
+
def __init__(self, all_arguments: list[InputArgument]) -> None:
|
14
|
+
self.all_arguments = all_arguments
|
15
|
+
|
16
|
+
@classmethod
|
17
|
+
def from_namespace(cls, namespace: Namespace,
|
18
|
+
processed_args: list[ValueArgument | BooleanArgument]) -> Self:
|
19
|
+
name_type_paired_args: dict[str, type[BaseArgument]] = {
|
20
|
+
arg.name: type(arg)
|
21
|
+
for arg in processed_args
|
22
|
+
}
|
23
|
+
return cls([InputArgument(name=name,
|
24
|
+
value=value,
|
25
|
+
founder_class=name_type_paired_args[name])
|
26
|
+
for name, value in vars(namespace).items()])
|
27
|
+
|
28
|
+
def get_by_name(self, name: str) -> InputArgument | None:
|
29
|
+
for arg in self.all_arguments:
|
30
|
+
if arg.name == name:
|
31
|
+
return arg
|
32
|
+
return None
|
33
|
+
|
34
|
+
def get_by_type(self, arg_type: type[BaseArgument]) -> list[InputArgument] | list[Never]:
|
35
|
+
return [arg for arg in self.all_arguments if arg.founder_class is arg_type]
|
36
|
+
|
9
37
|
|
10
38
|
class ArgParser:
|
11
39
|
def __init__(
|
12
40
|
self,
|
13
|
-
processed_args: list[
|
41
|
+
processed_args: list[ValueArgument | BooleanArgument], *,
|
14
42
|
name: str = "Argenta",
|
15
43
|
description: str = "Argenta available arguments",
|
16
44
|
epilog: str = "github.com/koloideal/Argenta | made by kolo",
|
@@ -22,38 +50,29 @@ class ArgParser:
|
|
22
50
|
:param epilog: the epilog of the ArgParse instance
|
23
51
|
:param processed_args: registered and processed arguments
|
24
52
|
"""
|
25
|
-
self.name = name
|
26
|
-
self.description = description
|
27
|
-
self.epilog = epilog
|
53
|
+
self.name: str = name
|
54
|
+
self.description: str = description
|
55
|
+
self.epilog: str = epilog
|
56
|
+
self.processed_args: list[ValueArgument | BooleanArgument] = processed_args
|
28
57
|
|
29
|
-
self.
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
58
|
+
self._core: ArgumentParser = ArgumentParser(prog=name, description=description, epilog=epilog)
|
59
|
+
|
60
|
+
for arg in processed_args:
|
61
|
+
if isinstance(arg, BooleanArgument):
|
62
|
+
_ = self._core.add_argument(arg.string_entity,
|
63
|
+
action=arg.action,
|
64
|
+
help=arg.help,
|
65
|
+
deprecated=arg.is_deprecated)
|
66
|
+
else:
|
67
|
+
_ = self._core.add_argument(arg.string_entity,
|
68
|
+
action=arg.action,
|
69
|
+
help=arg.help,
|
70
|
+
default=arg.default,
|
71
|
+
choices=arg.possible_values,
|
72
|
+
required=arg.is_required,
|
73
|
+
deprecated=arg.is_deprecated)
|
35
74
|
|
36
|
-
def
|
37
|
-
self,
|
38
|
-
|
39
|
-
|
40
|
-
Public. Sets the arguments to be processed
|
41
|
-
:param args: processed arguments
|
42
|
-
:return: None
|
43
|
-
"""
|
44
|
-
self.args.extend(args)
|
45
|
-
|
46
|
-
def register_args(self) -> None:
|
47
|
-
"""
|
48
|
-
Private. Registers initialized command line arguments
|
49
|
-
:return: None
|
50
|
-
"""
|
51
|
-
if not self.args:
|
52
|
-
return
|
53
|
-
for arg in self.args:
|
54
|
-
if type(arg) is PositionalArgument:
|
55
|
-
self.entity.add_argument(arg.get_string_entity())
|
56
|
-
elif type(arg) is OptionalArgument:
|
57
|
-
self.entity.add_argument(arg.get_string_entity())
|
58
|
-
elif type(arg) is BooleanArgument:
|
59
|
-
self.entity.add_argument(arg.get_string_entity(), action="store_true")
|
75
|
+
def parse_args(self) -> ArgSpace:
|
76
|
+
return ArgSpace.from_namespace(namespace=self._core.parse_args(),
|
77
|
+
processed_args=self.processed_args)
|
78
|
+
|