argenta 1.0.6__py3-none-any.whl → 1.1.1__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 +10 -0
- argenta/app/__init__.py +10 -1
- argenta/app/autocompleter/entity.py +18 -19
- argenta/app/dividing_line/models.py +5 -5
- argenta/app/models.py +184 -179
- 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 +9 -5
- argenta/command/flag/defaults.py +20 -24
- argenta/command/flag/flags/__init__.py +2 -8
- argenta/command/flag/flags/models.py +65 -49
- argenta/command/flag/models.py +80 -82
- argenta/command/models.py +100 -143
- argenta/metrics/main.py +2 -10
- argenta/orchestrator/__init__.py +5 -1
- argenta/orchestrator/argparser/__init__.py +9 -1
- argenta/orchestrator/argparser/arguments/models.py +18 -12
- argenta/orchestrator/argparser/entity.py +15 -35
- argenta/orchestrator/entity.py +4 -7
- argenta/py.typed +0 -0
- argenta/response/__init__.py +2 -2
- argenta/response/entity.py +12 -18
- argenta/response/status.py +12 -1
- argenta/router/__init__.py +2 -2
- argenta/router/command_handler/entity.py +7 -27
- argenta/router/entity.py +129 -155
- argenta/router/exceptions.py +11 -8
- {argenta-1.0.6.dist-info → argenta-1.1.1.dist-info}/METADATA +10 -4
- argenta-1.1.1.dist-info/RECORD +41 -0
- argenta-1.0.6.dist-info/RECORD +0 -39
- {argenta-1.0.6.dist-info → argenta-1.1.1.dist-info}/WHEEL +0 -0
- {argenta-1.0.6.dist-info → argenta-1.1.1.dist-info}/licenses/LICENSE +0 -0
argenta/app/models.py
CHANGED
@@ -1,29 +1,37 @@
|
|
1
|
-
from typing import Callable
|
2
|
-
from rich.console import Console
|
3
|
-
from rich.markup import escape
|
4
|
-
from art import text2art
|
5
|
-
from contextlib import redirect_stdout
|
6
1
|
import io
|
7
2
|
import re
|
3
|
+
from contextlib import redirect_stdout
|
4
|
+
from typing import Never, TypeAlias
|
5
|
+
|
6
|
+
from art import text2art # pyright: ignore[reportMissingTypeStubs, reportUnknownVariableType]
|
7
|
+
from rich.console import Console
|
8
|
+
from rich.markup import escape
|
8
9
|
|
9
|
-
from argenta.command.models import Command, InputCommand
|
10
|
-
from argenta.router import Router
|
11
|
-
from argenta.router.defaults import system_router
|
12
10
|
from argenta.app.autocompleter import AutoCompleter
|
13
|
-
from argenta.app.dividing_line.models import
|
11
|
+
from argenta.app.dividing_line.models import DynamicDividingLine, StaticDividingLine
|
12
|
+
from argenta.app.protocols import (
|
13
|
+
DescriptionMessageGenerator,
|
14
|
+
EmptyCommandHandler,
|
15
|
+
NonStandardBehaviorHandler,
|
16
|
+
Printer,
|
17
|
+
)
|
18
|
+
from argenta.app.registered_routers.entity import RegisteredRouters
|
14
19
|
from argenta.command.exceptions import (
|
15
|
-
UnprocessedInputFlagException,
|
16
|
-
RepeatedInputFlagsException,
|
17
20
|
EmptyInputCommandException,
|
18
|
-
|
21
|
+
InputCommandException,
|
22
|
+
RepeatedInputFlagsException,
|
23
|
+
UnprocessedInputFlagException,
|
19
24
|
)
|
20
|
-
from argenta.
|
25
|
+
from argenta.command.models import Command, InputCommand
|
21
26
|
from argenta.response import Response
|
27
|
+
from argenta.router import Router
|
28
|
+
from argenta.router.defaults import system_router
|
29
|
+
|
30
|
+
Matches: TypeAlias = list[str] | list[Never]
|
22
31
|
|
23
32
|
|
24
33
|
class BaseApp:
|
25
|
-
def __init__(self,
|
26
|
-
prompt: str,
|
34
|
+
def __init__(self, *, prompt: str,
|
27
35
|
initial_message: str,
|
28
36
|
farewell_message: str,
|
29
37
|
exit_command: Command,
|
@@ -33,42 +41,44 @@ class BaseApp:
|
|
33
41
|
repeat_command_groups: bool,
|
34
42
|
override_system_messages: bool,
|
35
43
|
autocompleter: AutoCompleter,
|
36
|
-
print_func:
|
37
|
-
self._prompt = prompt
|
38
|
-
self._print_func = print_func
|
39
|
-
self._exit_command = exit_command
|
40
|
-
self._system_router_title = system_router_title
|
41
|
-
self._dividing_line = dividing_line
|
42
|
-
self._ignore_command_register = ignore_command_register
|
43
|
-
self._repeat_command_groups_description = repeat_command_groups
|
44
|
-
self._override_system_messages = override_system_messages
|
45
|
-
self._autocompleter = autocompleter
|
46
|
-
|
47
|
-
self._farewell_message = farewell_message
|
48
|
-
self._initial_message = initial_message
|
49
|
-
|
50
|
-
self._description_message_gen:
|
44
|
+
print_func: Printer) -> None:
|
45
|
+
self._prompt: str = prompt
|
46
|
+
self._print_func: Printer = print_func
|
47
|
+
self._exit_command: Command = exit_command
|
48
|
+
self._system_router_title: str | None = system_router_title
|
49
|
+
self._dividing_line: StaticDividingLine | DynamicDividingLine = dividing_line
|
50
|
+
self._ignore_command_register: bool = ignore_command_register
|
51
|
+
self._repeat_command_groups_description: bool = repeat_command_groups
|
52
|
+
self._override_system_messages: bool = override_system_messages
|
53
|
+
self._autocompleter: AutoCompleter = autocompleter
|
54
|
+
|
55
|
+
self._farewell_message: str = farewell_message
|
56
|
+
self._initial_message: str = initial_message
|
57
|
+
|
58
|
+
self._description_message_gen: DescriptionMessageGenerator = lambda command, description: f"{command} *=*=* {description}"
|
51
59
|
self._registered_routers: RegisteredRouters = RegisteredRouters()
|
52
60
|
self._messages_on_startup: list[str] = []
|
53
61
|
|
54
|
-
self.
|
55
|
-
self.
|
62
|
+
self._matching_lower_triggers_with_routers: dict[str, Router] = {}
|
63
|
+
self._matching_default_triggers_with_routers: dict[str, Router] = {}
|
56
64
|
|
57
|
-
self.
|
58
|
-
self._repeated_input_flags_handler: Callable[[str], None] = (lambda raw_command: print_func(f"Repeated input flags: {raw_command}"))
|
59
|
-
self._empty_input_command_handler: Callable[[], None] = lambda: print_func("Empty input command")
|
60
|
-
self._unknown_command_handler: Callable[[InputCommand], None] = (lambda command: print_func(f"Unknown command: {command.get_trigger()}"))
|
61
|
-
self._exit_command_handler: Callable[[Response], None] = (lambda response: print_func(self._farewell_message))
|
65
|
+
self._current_matching_triggers_with_routers: dict[str, Router] = self._matching_lower_triggers_with_routers if self._ignore_command_register else self._matching_default_triggers_with_routers
|
62
66
|
|
63
|
-
|
67
|
+
self._incorrect_input_syntax_handler: NonStandardBehaviorHandler[str] = lambda _: print_func(f"Incorrect flag syntax: {_}")
|
68
|
+
self._repeated_input_flags_handler: NonStandardBehaviorHandler[str] = lambda _: print_func(f"Repeated input flags: {_}")
|
69
|
+
self._empty_input_command_handler: EmptyCommandHandler = lambda: print_func("Empty input command")
|
70
|
+
self._unknown_command_handler: NonStandardBehaviorHandler[InputCommand] = lambda _: print_func(f"Unknown command: {_.trigger}")
|
71
|
+
self._exit_command_handler: NonStandardBehaviorHandler[Response] = lambda _: print_func(self._farewell_message)
|
72
|
+
|
73
|
+
def set_description_message_pattern(self, _: DescriptionMessageGenerator, /) -> None:
|
64
74
|
"""
|
65
75
|
Public. Sets the output pattern of the available commands
|
66
76
|
:param _: output pattern of the available commands
|
67
77
|
:return: None
|
68
78
|
"""
|
69
|
-
self._description_message_gen
|
79
|
+
self._description_message_gen = _
|
70
80
|
|
71
|
-
def set_incorrect_input_syntax_handler(self, _:
|
81
|
+
def set_incorrect_input_syntax_handler(self, _: NonStandardBehaviorHandler[str], /) -> None:
|
72
82
|
"""
|
73
83
|
Public. Sets the handler for incorrect flags when entering a command
|
74
84
|
:param _: handler for incorrect flags when entering a command
|
@@ -76,7 +86,7 @@ class BaseApp:
|
|
76
86
|
"""
|
77
87
|
self._incorrect_input_syntax_handler = _
|
78
88
|
|
79
|
-
def set_repeated_input_flags_handler(self, _:
|
89
|
+
def set_repeated_input_flags_handler(self, _: NonStandardBehaviorHandler[str], /) -> None:
|
80
90
|
"""
|
81
91
|
Public. Sets the handler for repeated flags when entering a command
|
82
92
|
:param _: handler for repeated flags when entering a command
|
@@ -84,7 +94,7 @@ class BaseApp:
|
|
84
94
|
"""
|
85
95
|
self._repeated_input_flags_handler = _
|
86
96
|
|
87
|
-
def set_unknown_command_handler(self, _:
|
97
|
+
def set_unknown_command_handler(self, _: NonStandardBehaviorHandler[InputCommand], /) -> None:
|
88
98
|
"""
|
89
99
|
Public. Sets the handler for unknown commands when entering a command
|
90
100
|
:param _: handler for unknown commands when entering a command
|
@@ -92,7 +102,7 @@ class BaseApp:
|
|
92
102
|
"""
|
93
103
|
self._unknown_command_handler = _
|
94
104
|
|
95
|
-
def set_empty_command_handler(self, _:
|
105
|
+
def set_empty_command_handler(self, _: EmptyCommandHandler, /) -> None:
|
96
106
|
"""
|
97
107
|
Public. Sets the handler for empty commands when entering a command
|
98
108
|
:param _: handler for empty commands when entering a command
|
@@ -100,7 +110,7 @@ class BaseApp:
|
|
100
110
|
"""
|
101
111
|
self._empty_input_command_handler = _
|
102
112
|
|
103
|
-
def set_exit_command_handler(self, _:
|
113
|
+
def set_exit_command_handler(self, _: NonStandardBehaviorHandler[Response], /) -> None:
|
104
114
|
"""
|
105
115
|
Public. Sets the handler for exit command when entering a command
|
106
116
|
:param _: handler for exit command when entering a command
|
@@ -116,11 +126,12 @@ class BaseApp:
|
|
116
126
|
for registered_router in self._registered_routers:
|
117
127
|
if registered_router.title:
|
118
128
|
self._print_func(registered_router.title)
|
119
|
-
for command_handler in registered_router.
|
129
|
+
for command_handler in registered_router.command_handlers:
|
130
|
+
handled_command = command_handler.handled_command
|
120
131
|
self._print_func(
|
121
132
|
self._description_message_gen(
|
122
|
-
|
123
|
-
|
133
|
+
handled_command.trigger,
|
134
|
+
handled_command.description,
|
124
135
|
)
|
125
136
|
)
|
126
137
|
self._print_func("")
|
@@ -131,16 +142,7 @@ class BaseApp:
|
|
131
142
|
:param text: framed text
|
132
143
|
:return: None
|
133
144
|
"""
|
134
|
-
if isinstance(self._dividing_line,
|
135
|
-
self._print_func(
|
136
|
-
self._dividing_line.get_full_static_line(self._override_system_messages)
|
137
|
-
)
|
138
|
-
print(text.strip("\n"))
|
139
|
-
self._print_func(
|
140
|
-
self._dividing_line.get_full_static_line(self._override_system_messages)
|
141
|
-
)
|
142
|
-
|
143
|
-
elif isinstance(self._dividing_line, DynamicDividingLine):
|
145
|
+
if isinstance(self._dividing_line, DynamicDividingLine):
|
144
146
|
clear_text = re.sub(r"\u001b\[[0-9;]*m", "", text)
|
145
147
|
max_length_line = max([len(line) for line in clear_text.split("\n")])
|
146
148
|
max_length_line = (
|
@@ -153,15 +155,27 @@ class BaseApp:
|
|
153
155
|
|
154
156
|
self._print_func(
|
155
157
|
self._dividing_line.get_full_dynamic_line(
|
156
|
-
max_length_line, self._override_system_messages
|
158
|
+
length=max_length_line, is_override=self._override_system_messages
|
157
159
|
)
|
158
160
|
)
|
159
161
|
print(text.strip("\n"))
|
160
162
|
self._print_func(
|
161
163
|
self._dividing_line.get_full_dynamic_line(
|
162
|
-
max_length_line, self._override_system_messages
|
164
|
+
length=max_length_line, is_override=self._override_system_messages
|
163
165
|
)
|
164
166
|
)
|
167
|
+
|
168
|
+
elif isinstance(self._dividing_line, StaticDividingLine): # pyright: ignore[reportUnnecessaryIsInstance]
|
169
|
+
self._print_func(
|
170
|
+
self._dividing_line.get_full_static_line(is_override=self._override_system_messages)
|
171
|
+
)
|
172
|
+
print(text.strip("\n"))
|
173
|
+
self._print_func(
|
174
|
+
self._dividing_line.get_full_static_line(is_override=self._override_system_messages)
|
175
|
+
)
|
176
|
+
|
177
|
+
else:
|
178
|
+
raise NotImplementedError
|
165
179
|
|
166
180
|
def _is_exit_command(self, command: InputCommand) -> bool:
|
167
181
|
"""
|
@@ -169,20 +183,21 @@ class BaseApp:
|
|
169
183
|
:param command: command to check
|
170
184
|
:return: is it an exit command or not as bool
|
171
185
|
"""
|
186
|
+
trigger = command.trigger
|
187
|
+
exit_trigger = self._exit_command.trigger
|
172
188
|
if self._ignore_command_register:
|
173
189
|
if (
|
174
|
-
|
175
|
-
== self._exit_command.get_trigger().lower()
|
190
|
+
trigger.lower() == exit_trigger.lower()
|
176
191
|
):
|
177
192
|
return True
|
178
|
-
elif
|
179
|
-
x.lower() for x in self._exit_command.
|
193
|
+
elif trigger.lower() in [
|
194
|
+
x.lower() for x in self._exit_command.aliases
|
180
195
|
]:
|
181
196
|
return True
|
182
197
|
else:
|
183
|
-
if
|
198
|
+
if trigger == exit_trigger:
|
184
199
|
return True
|
185
|
-
elif
|
200
|
+
elif trigger in self._exit_command.aliases:
|
186
201
|
return True
|
187
202
|
return False
|
188
203
|
|
@@ -192,16 +207,18 @@ class BaseApp:
|
|
192
207
|
:param command: command to check
|
193
208
|
:return: is it an unknown command or not as bool
|
194
209
|
"""
|
195
|
-
input_command_trigger = command.
|
210
|
+
input_command_trigger = command.trigger
|
196
211
|
if self._ignore_command_register:
|
197
|
-
if input_command_trigger.lower() in self.
|
212
|
+
if input_command_trigger.lower() in list(self._current_matching_triggers_with_routers.keys()):
|
198
213
|
return False
|
199
214
|
else:
|
200
|
-
if input_command_trigger in self.
|
215
|
+
if input_command_trigger in list(self._current_matching_triggers_with_routers.keys()):
|
201
216
|
return False
|
202
217
|
return True
|
203
218
|
|
204
|
-
def _error_handler(
|
219
|
+
def _error_handler(
|
220
|
+
self, error: InputCommandException, raw_command: str
|
221
|
+
) -> None:
|
205
222
|
"""
|
206
223
|
Private. Handles parsing errors of the entered command
|
207
224
|
:param error: error being handled
|
@@ -223,26 +240,25 @@ class BaseApp:
|
|
223
240
|
system_router.title = self._system_router_title
|
224
241
|
|
225
242
|
@system_router.command(self._exit_command)
|
226
|
-
def
|
243
|
+
def _(response: Response) -> None:
|
227
244
|
self._exit_command_handler(response)
|
228
245
|
|
229
|
-
if system_router not in self._registered_routers.
|
230
|
-
system_router.
|
246
|
+
if system_router not in self._registered_routers.registered_routers:
|
247
|
+
system_router.command_register_ignore = self._ignore_command_register
|
231
248
|
self._registered_routers.add_registered_router(system_router)
|
232
249
|
|
233
250
|
def _most_similar_command(self, unknown_command: str) -> str | None:
|
234
|
-
all_commands = (
|
235
|
-
|
236
|
-
|
237
|
-
else self._all_registered_triggers_in_default_case
|
238
|
-
)
|
239
|
-
matches: list[str] | list = sorted(
|
251
|
+
all_commands = list(self._current_matching_triggers_with_routers.keys())
|
252
|
+
|
253
|
+
matches_startswith_unknown_command: Matches = sorted(
|
240
254
|
cmd for cmd in all_commands if cmd.startswith(unknown_command)
|
241
255
|
)
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
256
|
+
matches_startswith_cmd: Matches = sorted(
|
257
|
+
cmd for cmd in all_commands if unknown_command.startswith(cmd)
|
258
|
+
)
|
259
|
+
|
260
|
+
matches: Matches = matches_startswith_unknown_command or matches_startswith_cmd
|
261
|
+
|
246
262
|
if len(matches) == 1:
|
247
263
|
return matches[0]
|
248
264
|
elif len(matches) > 1:
|
@@ -255,12 +271,12 @@ class BaseApp:
|
|
255
271
|
Private. Sets up default app view
|
256
272
|
:return: None
|
257
273
|
"""
|
258
|
-
self._prompt = "[italic dim bold]
|
259
|
-
self._initial_message = (
|
260
|
-
"\n"+f"[bold red]{text2art(self._initial_message, font='tarty1')}"+"\n"
|
261
|
-
)
|
274
|
+
self._prompt = f"[italic dim bold]{self._prompt}"
|
275
|
+
self._initial_message = ("\n" + f"[bold red]{text2art(self._initial_message, font='tarty1')}" + "\n")
|
262
276
|
self._farewell_message = (
|
263
|
-
"[bold red]\n\n"
|
277
|
+
"[bold red]\n\n" +
|
278
|
+
str(text2art(self._farewell_message, font="chanky")) + # pyright: ignore[reportUnknownArgumentType]
|
279
|
+
"\n[/bold red]\n" +
|
264
280
|
"[red i]github.com/koloideal/Argenta[/red i] | [red bold i]made by kolo[/red bold i]\n"
|
265
281
|
)
|
266
282
|
self._description_message_gen = lambda command, description: (
|
@@ -268,22 +284,14 @@ class BaseApp:
|
|
268
284
|
f"[blue dim]*=*=*[/blue dim] "
|
269
285
|
f"[bold yellow italic]{escape(description)}"
|
270
286
|
)
|
271
|
-
self._incorrect_input_syntax_handler = lambda raw_command: self._print_func(
|
272
|
-
|
273
|
-
)
|
274
|
-
self._repeated_input_flags_handler = lambda raw_command: self._print_func(
|
275
|
-
f"[red bold]Repeated input flags: {escape(raw_command)}"
|
276
|
-
)
|
277
|
-
self._empty_input_command_handler = lambda: self._print_func(
|
278
|
-
"[red bold]Empty input command"
|
279
|
-
)
|
287
|
+
self._incorrect_input_syntax_handler = lambda raw_command: self._print_func(f"[red bold]Incorrect flag syntax: {escape(raw_command)}")
|
288
|
+
self._repeated_input_flags_handler = lambda raw_command: self._print_func(f"[red bold]Repeated input flags: {escape(raw_command)}")
|
289
|
+
self._empty_input_command_handler = lambda: self._print_func("[red bold]Empty input command")
|
280
290
|
|
281
291
|
def unknown_command_handler(command: InputCommand) -> None:
|
282
|
-
cmd_trg: str = command.
|
292
|
+
cmd_trg: str = command.trigger
|
283
293
|
mst_sim_cmd: str | None = self._most_similar_command(cmd_trg)
|
284
|
-
first_part_of_text = (
|
285
|
-
f"[red]Unknown command:[/red] [blue]{escape(cmd_trg)}[/blue]"
|
286
|
-
)
|
294
|
+
first_part_of_text = f"[red]Unknown command:[/red] [blue]{escape(cmd_trg)}[/blue]"
|
287
295
|
second_part_of_text = (
|
288
296
|
("[red], most similar:[/red] " + ("[blue]" + mst_sim_cmd + "[/blue]"))
|
289
297
|
if mst_sim_cmd
|
@@ -293,7 +301,7 @@ class BaseApp:
|
|
293
301
|
|
294
302
|
self._unknown_command_handler = unknown_command_handler
|
295
303
|
|
296
|
-
def
|
304
|
+
def _pre_cycle_setup(self) -> None:
|
297
305
|
"""
|
298
306
|
Private. Configures various aspects of the application before the start of the cycle
|
299
307
|
:return: None
|
@@ -301,30 +309,22 @@ class BaseApp:
|
|
301
309
|
self._setup_system_router()
|
302
310
|
|
303
311
|
for router_entity in self._registered_routers:
|
304
|
-
router_triggers = router_entity.
|
305
|
-
router_aliases = router_entity.
|
312
|
+
router_triggers = router_entity.triggers
|
313
|
+
router_aliases = router_entity.aliases
|
306
314
|
combined = router_triggers + router_aliases
|
307
315
|
|
308
|
-
|
316
|
+
for trigger in combined:
|
317
|
+
self._matching_default_triggers_with_routers[trigger] = router_entity
|
318
|
+
self._matching_lower_triggers_with_routers[trigger.lower()] = router_entity
|
309
319
|
|
310
|
-
|
320
|
+
self._autocompleter.initial_setup(list(self._current_matching_triggers_with_routers.keys()))
|
311
321
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
Console().print(f"\n[b red]WARNING:[/b red] Overlapping trigger or alias: [b blue]{item}[/b blue]")
|
319
|
-
else:
|
320
|
-
seen[item] = True
|
321
|
-
else:
|
322
|
-
seen = {}
|
323
|
-
for item in self._all_registered_triggers_in_default_case:
|
324
|
-
if item in seen:
|
325
|
-
Console().print(f"\n[b red]WARNING:[/b red] Overlapping trigger or alias: [b blue]{item}[/b blue]")
|
326
|
-
else:
|
327
|
-
seen[item] = True
|
322
|
+
seen = {}
|
323
|
+
for item in list(self._current_matching_triggers_with_routers.keys()):
|
324
|
+
if item in seen:
|
325
|
+
Console().print(f"\n[b red]WARNING:[/b red] Overlapping trigger or alias: [b blue]{item}[/b blue]")
|
326
|
+
else:
|
327
|
+
seen[item] = True
|
328
328
|
|
329
329
|
if not self._override_system_messages:
|
330
330
|
self._setup_default_view()
|
@@ -339,19 +339,29 @@ class BaseApp:
|
|
339
339
|
self._print_command_group_description()
|
340
340
|
|
341
341
|
|
342
|
+
AVAILABLE_DIVIDING_LINES: TypeAlias = StaticDividingLine | DynamicDividingLine
|
343
|
+
DEFAULT_DIVIDING_LINE: StaticDividingLine = StaticDividingLine()
|
344
|
+
|
345
|
+
DEFAULT_PRINT_FUNC: Printer = Console().print
|
346
|
+
DEFAULT_AUTOCOMPLETER: AutoCompleter = AutoCompleter()
|
347
|
+
DEFAULT_EXIT_COMMAND: Command = Command("Q", description="Exit command")
|
348
|
+
|
349
|
+
|
342
350
|
class App(BaseApp):
|
343
|
-
def __init__(
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
351
|
+
def __init__(
|
352
|
+
self, *,
|
353
|
+
prompt: str = "What do you want to do?\n\n",
|
354
|
+
initial_message: str = "Argenta\n",
|
355
|
+
farewell_message: str = "\nSee you\n",
|
356
|
+
exit_command: Command = DEFAULT_EXIT_COMMAND,
|
357
|
+
system_router_title: str | None = "System points:",
|
358
|
+
ignore_command_register: bool = True,
|
359
|
+
dividing_line: AVAILABLE_DIVIDING_LINES = DEFAULT_DIVIDING_LINE,
|
360
|
+
repeat_command_groups: bool = True,
|
361
|
+
override_system_messages: bool = False,
|
362
|
+
autocompleter: AutoCompleter = DEFAULT_AUTOCOMPLETER,
|
363
|
+
print_func: Printer = DEFAULT_PRINT_FUNC,
|
364
|
+
) -> None:
|
355
365
|
"""
|
356
366
|
Public. The essence of the application itself.
|
357
367
|
Configures and manages all aspects of the behavior and presentation of the user interacting with the user
|
@@ -368,24 +378,26 @@ class App(BaseApp):
|
|
368
378
|
:param print_func: system messages text output function
|
369
379
|
:return: None
|
370
380
|
"""
|
371
|
-
super().__init__(
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
381
|
+
super().__init__(
|
382
|
+
prompt=prompt,
|
383
|
+
initial_message=initial_message,
|
384
|
+
farewell_message=farewell_message,
|
385
|
+
exit_command=exit_command,
|
386
|
+
system_router_title=system_router_title,
|
387
|
+
ignore_command_register=ignore_command_register,
|
388
|
+
dividing_line=dividing_line,
|
389
|
+
repeat_command_groups=repeat_command_groups,
|
390
|
+
override_system_messages=override_system_messages,
|
391
|
+
autocompleter=autocompleter,
|
392
|
+
print_func=print_func,
|
393
|
+
)
|
382
394
|
|
383
395
|
def run_polling(self) -> None:
|
384
396
|
"""
|
385
397
|
Private. Starts the user input processing cycle
|
386
398
|
:return: None
|
387
399
|
"""
|
388
|
-
self.
|
400
|
+
self._pre_cycle_setup()
|
389
401
|
while True:
|
390
402
|
if self._repeat_command_groups_description:
|
391
403
|
self._print_command_group_description()
|
@@ -393,51 +405,44 @@ class App(BaseApp):
|
|
393
405
|
raw_command: str = Console().input(self._prompt)
|
394
406
|
|
395
407
|
try:
|
396
|
-
input_command: InputCommand = InputCommand.parse(
|
397
|
-
|
398
|
-
)
|
399
|
-
except BaseInputCommandException as error:
|
400
|
-
with redirect_stdout(io.StringIO()) as f:
|
408
|
+
input_command: InputCommand = InputCommand.parse(raw_command=raw_command)
|
409
|
+
except InputCommandException as error:
|
410
|
+
with redirect_stdout(io.StringIO()) as stderr:
|
401
411
|
self._error_handler(error, raw_command)
|
402
|
-
|
403
|
-
self._print_framed_text(
|
412
|
+
stderr_result: str = stderr.getvalue()
|
413
|
+
self._print_framed_text(stderr_result)
|
404
414
|
continue
|
405
415
|
|
406
416
|
if self._is_exit_command(input_command):
|
407
417
|
system_router.finds_appropriate_handler(input_command)
|
408
|
-
|
409
|
-
self._autocompleter.exit_setup(
|
410
|
-
self._all_registered_triggers_in_lower_case
|
411
|
-
)
|
412
|
-
else:
|
413
|
-
self._autocompleter.exit_setup(
|
414
|
-
self._all_registered_triggers_in_default_case
|
415
|
-
)
|
418
|
+
self._autocompleter.exit_setup(list(self._current_matching_triggers_with_routers.keys()))
|
416
419
|
return
|
417
420
|
|
418
421
|
if self._is_unknown_command(input_command):
|
419
|
-
with redirect_stdout(io.StringIO()) as
|
422
|
+
with redirect_stdout(io.StringIO()) as stdout:
|
420
423
|
self._unknown_command_handler(input_command)
|
421
|
-
|
422
|
-
self._print_framed_text(
|
424
|
+
stdout_res: str = stdout.getvalue()
|
425
|
+
self._print_framed_text(stdout_res)
|
423
426
|
continue
|
424
427
|
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
self._print_func(StaticDividingLine(self._dividing_line.get_unit_part()).get_full_static_line(self._override_system_messages))
|
433
|
-
registered_router.finds_appropriate_handler(input_command)
|
434
|
-
self._print_func(StaticDividingLine(self._dividing_line.get_unit_part()).get_full_static_line(self._override_system_messages))
|
428
|
+
processing_router = self._current_matching_triggers_with_routers[input_command.trigger.lower()]
|
429
|
+
|
430
|
+
if processing_router.disable_redirect_stdout:
|
431
|
+
if isinstance(self._dividing_line, StaticDividingLine):
|
432
|
+
self._print_func(self._dividing_line.get_full_static_line(is_override=self._override_system_messages))
|
433
|
+
processing_router.finds_appropriate_handler(input_command)
|
434
|
+
self._print_func(self._dividing_line.get_full_static_line(is_override=self._override_system_messages))
|
435
435
|
else:
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
436
|
+
dividing_line_unit_part: str = self._dividing_line.get_unit_part()
|
437
|
+
self._print_func(StaticDividingLine(dividing_line_unit_part).get_full_static_line(is_override=self._override_system_messages))
|
438
|
+
processing_router.finds_appropriate_handler(input_command)
|
439
|
+
self._print_func(StaticDividingLine(dividing_line_unit_part).get_full_static_line(is_override=self._override_system_messages))
|
440
|
+
else:
|
441
|
+
with redirect_stdout(io.StringIO()) as stdout:
|
442
|
+
processing_router.finds_appropriate_handler(input_command)
|
443
|
+
stdout_result: str = stdout.getvalue()
|
444
|
+
if stdout_result:
|
445
|
+
self._print_framed_text(stdout_result)
|
441
446
|
|
442
447
|
def include_router(self, router: Router) -> None:
|
443
448
|
"""
|
@@ -445,7 +450,7 @@ class App(BaseApp):
|
|
445
450
|
:param router: registered router
|
446
451
|
:return: None
|
447
452
|
"""
|
448
|
-
router.
|
453
|
+
router.command_register_ignore = self._ignore_command_register
|
449
454
|
self._registered_routers.add_registered_router(router)
|
450
455
|
|
451
456
|
def include_routers(self, *routers: Router) -> None:
|
argenta/app/protocols.py
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
from typing import Protocol, TypeVar
|
2
|
+
|
3
|
+
T = TypeVar('T', contravariant=True) # noqa: WPS111
|
4
|
+
|
5
|
+
|
6
|
+
class NonStandardBehaviorHandler(Protocol[T]):
|
7
|
+
def __call__(self, __param: T) -> None:
|
8
|
+
raise NotImplementedError
|
9
|
+
|
10
|
+
class EmptyCommandHandler(Protocol):
|
11
|
+
def __call__(self) -> None:
|
12
|
+
raise NotImplementedError
|
13
|
+
|
14
|
+
|
15
|
+
class Printer(Protocol):
|
16
|
+
def __call__(self, __text: str) -> None:
|
17
|
+
raise NotImplementedError
|
18
|
+
|
19
|
+
|
20
|
+
class DescriptionMessageGenerator(Protocol):
|
21
|
+
def __call__(self, __first_param: str, __second_param: str) -> str:
|
22
|
+
raise NotImplementedError
|
@@ -1,34 +1,27 @@
|
|
1
|
-
from typing import Iterator
|
1
|
+
from typing import Iterator, Optional
|
2
2
|
|
3
3
|
from argenta.router import Router
|
4
4
|
|
5
5
|
|
6
6
|
class RegisteredRouters:
|
7
|
-
def __init__(self, registered_routers: list[Router]
|
7
|
+
def __init__(self, registered_routers: Optional[list[Router]] = None) -> None:
|
8
8
|
"""
|
9
9
|
Private. Combines registered routers
|
10
10
|
:param registered_routers: list of the registered routers
|
11
11
|
:return: None
|
12
12
|
"""
|
13
|
-
self.
|
13
|
+
self.registered_routers: list[Router] = registered_routers if registered_routers else []
|
14
14
|
|
15
|
-
def
|
16
|
-
"""
|
17
|
-
Private. Returns the registered routers
|
18
|
-
:return: registered routers as list[Router]
|
19
|
-
"""
|
20
|
-
return self._registered_routers
|
21
|
-
|
22
|
-
def add_registered_router(self, router: Router) -> None:
|
15
|
+
def add_registered_router(self, router: Router, /) -> None:
|
23
16
|
"""
|
24
17
|
Private. Adds a new registered router
|
25
18
|
:param router: registered router
|
26
19
|
:return: None
|
27
20
|
"""
|
28
|
-
self.
|
21
|
+
self.registered_routers.append(router)
|
29
22
|
|
30
23
|
def __iter__(self) -> Iterator[Router]:
|
31
|
-
return iter(self.
|
24
|
+
return iter(self.registered_routers)
|
32
25
|
|
33
26
|
def __next__(self) -> Router:
|
34
|
-
return next(iter(self.
|
27
|
+
return next(iter(self.registered_routers))
|
argenta/command/__init__.py
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
-
__all__ = [
|
1
|
+
__all__ = [
|
2
|
+
"Command",
|
3
|
+
"PossibleValues",
|
4
|
+
"PredefinedFlags",
|
5
|
+
"InputCommand",
|
6
|
+
"Flags",
|
7
|
+
"Flag"
|
8
|
+
]
|
2
9
|
|
3
|
-
from argenta.command.models import Command
|
10
|
+
from argenta.command.models import Command, InputCommand
|
11
|
+
from argenta.command.flag import defaults as PredefinedFlags
|
12
|
+
from argenta.command.flag import (Flag, Flags, PossibleValues)
|