argenta 1.0.0a5__tar.gz → 1.0.0b1__tar.gz
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-1.0.0a5 → argenta-1.0.0b1}/PKG-INFO +2 -2
- {argenta-1.0.0a5 → argenta-1.0.0b1}/README.md +1 -1
- argenta-1.0.0b1/imgs/mock_app_preview4.png +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/mock/default_mock_app/main.py +5 -6
- argenta-1.0.0b1/mock/local_test.py +17 -0
- argenta-1.0.0b1/mock/mock_app/handlers/routers.py +31 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/mock/mock_app/main.py +2 -1
- {argenta-1.0.0a5 → argenta-1.0.0b1}/pyproject.toml +1 -1
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/app/models.py +40 -19
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/command/exceptions.py +1 -1
- argenta-1.0.0b1/src/argenta/command/flag/__init__.py +4 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/command/flag/models.py +20 -126
- argenta-1.0.0b1/src/argenta/command/flags/__init__.py +10 -0
- argenta-1.0.0b1/src/argenta/command/flags/models.py +75 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/command/models.py +17 -9
- argenta-1.0.0b1/src/argenta/response/__init__.py +5 -0
- argenta-1.0.0b1/src/argenta/response/entity.py +20 -0
- argenta-1.0.0b1/src/argenta/response/status.py +9 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/router/command_handler/entity.py +7 -11
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/router/entity.py +59 -41
- argenta-1.0.0a5/mock/local_test.py +0 -6
- argenta-1.0.0a5/mock/mock_app/handlers/routers.py +0 -22
- argenta-1.0.0a5/src/argenta/command/flag/__init__.py +0 -4
- {argenta-1.0.0a5 → argenta-1.0.0b1}/.github/workflows/ruff.yml +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/.github/workflows/tests.yml +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/.gitignore +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/LICENSE +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/imgs/mock_app_preview1.png +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/imgs/mock_app_preview2.png +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/imgs/mock_app_preview3.png +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/mock/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/mock/default_mock_app/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/mock/mock_app/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/mock/mock_app/handlers/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/mock/mock_app/handlers/handlers_implementation/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/mock/mock_app/handlers/handlers_implementation/help_command.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/app/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/app/autocompleter/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/app/autocompleter/entity.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/app/defaults.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/app/dividing_line/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/app/dividing_line/models.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/app/registered_routers/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/app/registered_routers/entity.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/command/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/command/flag/defaults.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/orchestrator/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/orchestrator/argparser/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/orchestrator/argparser/arguments/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/orchestrator/argparser/arguments/models.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/orchestrator/argparser/entity.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/orchestrator/entity.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/router/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/router/command_handler/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/router/defaults.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/router/exceptions.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/tests/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/tests/system_tests/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/tests/system_tests/test_system_handling_non_standard_behavior.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/tests/system_tests/test_system_handling_normal_behavior.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/tests/unit_tests/__init__.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/tests/unit_tests/test_app.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/tests/unit_tests/test_command.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/tests/unit_tests/test_dividing_line.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/tests/unit_tests/test_flag.py +0 -0
- {argenta-1.0.0a5 → argenta-1.0.0b1}/tests/unit_tests/test_router.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: argenta
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.0b1
|
4
4
|
Summary: Python library for creating TUI
|
5
5
|
Author-email: kolo <kolo.is.main@gmail.com>
|
6
6
|
License: MIT
|
@@ -87,7 +87,7 @@ Description-Content-Type: text/markdown
|
|
87
87
|
|
88
88
|
---
|
89
89
|
|
90
|
-

|
91
91
|
An example of the TUI appearance
|
92
92
|
|
93
93
|
---
|
Binary file
|
@@ -1,8 +1,7 @@
|
|
1
|
-
|
1
|
+
from mock.mock_app.handlers.routers import work_router
|
2
2
|
|
3
3
|
from argenta.app import App
|
4
4
|
from argenta.app.defaults import PredefinedMessages
|
5
|
-
from argenta.app.dividing_line import DynamicDividingLine
|
6
5
|
from argenta.app.autocompleter import AutoCompleter
|
7
6
|
from argenta.orchestrator import Orchestrator
|
8
7
|
from argenta.orchestrator.argparser import ArgParser
|
@@ -10,16 +9,16 @@ from argenta.orchestrator.argparser.arguments import BooleanArgument
|
|
10
9
|
|
11
10
|
|
12
11
|
arg_parser = ArgParser(processed_args=[BooleanArgument('repeat')])
|
13
|
-
app: App = App()
|
12
|
+
app: App = App(autocompleter=AutoCompleter('.hist'))
|
14
13
|
orchestrator: Orchestrator = Orchestrator()
|
15
14
|
|
16
15
|
|
17
16
|
def main():
|
18
|
-
|
17
|
+
app.include_router(work_router)
|
19
18
|
|
20
|
-
|
19
|
+
app.add_message_on_startup(PredefinedMessages.USAGE)
|
21
20
|
app.add_message_on_startup(PredefinedMessages.AUTOCOMPLETE)
|
22
|
-
app.add_message_on_startup(PredefinedMessages.HELP)
|
21
|
+
app.add_message_on_startup(PredefinedMessages.HELP)
|
23
22
|
|
24
23
|
orchestrator.start_polling(app)
|
25
24
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
from argenta.response import Response, Status
|
2
|
+
from argenta.app import App
|
3
|
+
from argenta.app.dividing_line import StaticDividingLine, DynamicDividingLine
|
4
|
+
from argenta.app.autocompleter import AutoCompleter
|
5
|
+
from argenta.app.defaults import PredefinedMessages
|
6
|
+
from argenta.command import Command
|
7
|
+
from argenta.command.flags import Flags, InputFlags, InvalidValueInputFlags, UndefinedInputFlags, ValidInputFlags
|
8
|
+
from argenta.command.flag import Flag, InputFlag
|
9
|
+
from argenta.command.flag.defaults import PredefinedFlags
|
10
|
+
from argenta.router import Router
|
11
|
+
from argenta.orchestrator import Orchestrator
|
12
|
+
|
13
|
+
from argenta.command.models import InputCommand
|
14
|
+
from argenta.app.utils import most_similar_command
|
15
|
+
|
16
|
+
|
17
|
+
print(most_similar_command('case', ['case', 'tester', 'poster', 'caser']))
|
@@ -0,0 +1,31 @@
|
|
1
|
+
from rich.console import Console
|
2
|
+
|
3
|
+
from argenta.command import Command
|
4
|
+
from argenta.command.flag.defaults import PredefinedFlags
|
5
|
+
from argenta.command.flags import Flags
|
6
|
+
from argenta.response import Response
|
7
|
+
from argenta.router import Router
|
8
|
+
|
9
|
+
|
10
|
+
work_router: Router = Router(title='Work points:')
|
11
|
+
|
12
|
+
console = Console()
|
13
|
+
|
14
|
+
|
15
|
+
@work_router.command(Command('get', 'Get Help', aliases=['help', 'Get_help'], flags=Flags(PredefinedFlags.PORT, PredefinedFlags.HOST)))
|
16
|
+
def command_help(response: Response):
|
17
|
+
print(response.status)
|
18
|
+
print(response.undefined_flags.get_flags())
|
19
|
+
print(response.valid_flags.get_flags())
|
20
|
+
print(response.invalid_value_flags.get_flags())
|
21
|
+
|
22
|
+
|
23
|
+
@work_router.command(Command('run', 'Run All'))
|
24
|
+
def command_start_solving(response: Response):
|
25
|
+
print(response.status)
|
26
|
+
print(response.undefined_flags.get_flags())
|
27
|
+
print(response.valid_flags.get_flags())
|
28
|
+
print(response.invalid_value_flags.get_flags())
|
29
|
+
|
30
|
+
|
31
|
+
|
@@ -11,7 +11,8 @@ from argenta.orchestrator.argparser.arguments import BooleanArgument
|
|
11
11
|
|
12
12
|
arg_parser = ArgParser(processed_args=[BooleanArgument('repeat')])
|
13
13
|
app: App = App(dividing_line=DynamicDividingLine(),
|
14
|
-
autocompleter=AutoCompleter('./mock/.hist')
|
14
|
+
autocompleter=AutoCompleter('./mock/.hist'),
|
15
|
+
repeat_command_groups=False,)
|
15
16
|
orchestrator: Orchestrator = Orchestrator(arg_parser)
|
16
17
|
|
17
18
|
|
@@ -16,6 +16,7 @@ from argenta.command.exceptions import (UnprocessedInputFlagException,
|
|
16
16
|
EmptyInputCommandException,
|
17
17
|
BaseInputCommandException)
|
18
18
|
from argenta.app.registered_routers.entity import RegisteredRouters
|
19
|
+
from argenta.response import Response
|
19
20
|
|
20
21
|
|
21
22
|
|
@@ -58,7 +59,7 @@ class BaseApp:
|
|
58
59
|
self._repeated_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'Repeated input flags: {raw_command}')
|
59
60
|
self._empty_input_command_handler: Callable[[], None] = lambda: print_func('Empty input command')
|
60
61
|
self._unknown_command_handler: Callable[[InputCommand], None] = lambda command: print_func(f"Unknown command: {command.get_trigger()}")
|
61
|
-
self._exit_command_handler: Callable[[], None] = lambda: print_func(self._farewell_message)
|
62
|
+
self._exit_command_handler: Callable[[Response], None] = lambda response: print_func(self._farewell_message)
|
62
63
|
|
63
64
|
|
64
65
|
def set_description_message_pattern(self, _: Callable[[str, str], str]) -> None:
|
@@ -210,30 +211,51 @@ class BaseApp:
|
|
210
211
|
system_router.set_title(self._system_router_title)
|
211
212
|
|
212
213
|
@system_router.command(self._exit_command)
|
213
|
-
def exit_command():
|
214
|
-
self._exit_command_handler()
|
214
|
+
def exit_command(response: Response) -> None:
|
215
|
+
self._exit_command_handler(response)
|
215
216
|
|
216
217
|
if system_router not in self._registered_routers.get_registered_routers():
|
217
218
|
system_router.set_command_register_ignore(self._ignore_command_register)
|
218
219
|
self._registered_routers.add_registered_router(system_router)
|
219
220
|
|
220
221
|
|
222
|
+
def _most_similar_command(self, unknown_command: str) -> str | None:
|
223
|
+
all_commands = self._all_registered_triggers_in_lower if self._ignore_command_register else self._all_registered_triggers_in_default_case
|
224
|
+
matches: list[str] | list = sorted(cmd for cmd in all_commands if cmd.startswith(unknown_command))
|
225
|
+
if not matches:
|
226
|
+
matches: list[str] | list = sorted(cmd for cmd in all_commands if unknown_command.startswith(cmd))
|
227
|
+
if len(matches) == 1:
|
228
|
+
return matches[0]
|
229
|
+
elif len(matches) > 1:
|
230
|
+
return sorted(matches, key=lambda cmd: len(cmd))[0]
|
231
|
+
else:
|
232
|
+
return None
|
233
|
+
|
234
|
+
|
221
235
|
def _setup_default_view(self) -> None:
|
222
236
|
"""
|
223
237
|
Private. Sets up default app view
|
224
238
|
:return: None
|
225
239
|
"""
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
240
|
+
self._prompt = '[italic dim bold]What do you want to do?\n'
|
241
|
+
self._initial_message = f'\n[bold red]{text2art(self._initial_message, font="tarty1")}\n\n'
|
242
|
+
self._farewell_message = (f'[bold red]\n{text2art(f"\n{self._farewell_message}\n", font="chanky")}[/bold red]\n'
|
243
|
+
f'[red i]github.com/koloideal/Argenta[/red i] | [red bold i]made by kolo[/red bold i]\n')
|
244
|
+
self._description_message_gen = lambda command, description: (f'[bold red]{escape("[" + command + "]")}[/bold red] '
|
245
|
+
f'[blue dim]*=*=*[/blue dim] '
|
246
|
+
f'[bold yellow italic]{escape(description)}')
|
247
|
+
self._invalid_input_flags_handler = lambda raw_command: self._print_func(f'[red bold]Incorrect flag syntax: {escape(raw_command)}')
|
248
|
+
self._repeated_input_flags_handler = lambda raw_command: self._print_func(f'[red bold]Repeated input flags: {escape(raw_command)}')
|
249
|
+
self._empty_input_command_handler = lambda: self._print_func('[red bold]Empty input command')
|
250
|
+
|
251
|
+
def unknown_command_handler(command: InputCommand) -> None:
|
252
|
+
cmd_trg: str = command.get_trigger()
|
253
|
+
mst_sim_cmd: str | None = self._most_similar_command(cmd_trg)
|
254
|
+
first_part_of_text = f"[red]Unknown command:[/red] [blue]{escape(cmd_trg)}[/blue]"
|
255
|
+
second_part_of_text = ('[red], most similar:[/red] ' + ('[blue]' + mst_sim_cmd + '[/blue]')) if mst_sim_cmd else ''
|
256
|
+
self._print_func(first_part_of_text + second_part_of_text)
|
257
|
+
|
258
|
+
self._unknown_command_handler = unknown_command_handler
|
237
259
|
|
238
260
|
|
239
261
|
def _pre_cycle_setup(self) -> None:
|
@@ -241,7 +263,6 @@ class BaseApp:
|
|
241
263
|
Private. Configures various aspects of the application before the start of the cycle
|
242
264
|
:return: None
|
243
265
|
"""
|
244
|
-
self._setup_default_view()
|
245
266
|
self._setup_system_router()
|
246
267
|
|
247
268
|
for router_entity in self._registered_routers:
|
@@ -253,6 +274,9 @@ class BaseApp:
|
|
253
274
|
|
254
275
|
self._autocompleter.initial_setup(self._all_registered_triggers_in_lower)
|
255
276
|
|
277
|
+
if not self._override_system_messages:
|
278
|
+
self._setup_default_view()
|
279
|
+
|
256
280
|
self._print_func(self._initial_message)
|
257
281
|
|
258
282
|
for message in self._messages_on_startup:
|
@@ -267,7 +291,7 @@ class BaseApp:
|
|
267
291
|
|
268
292
|
class App(BaseApp):
|
269
293
|
def __init__(self,
|
270
|
-
prompt: str = '
|
294
|
+
prompt: str = 'What do you want to do?\n',
|
271
295
|
initial_message: str = '\nArgenta\n',
|
272
296
|
farewell_message: str = '\nSee you\n',
|
273
297
|
exit_command: Command = Command('Q', 'Exit command'),
|
@@ -346,9 +370,6 @@ class App(BaseApp):
|
|
346
370
|
res: str = f.getvalue()
|
347
371
|
self._print_framed_text(res)
|
348
372
|
|
349
|
-
if not self._repeat_command_groups_description:
|
350
|
-
self._print_func(self._prompt)
|
351
|
-
|
352
373
|
|
353
374
|
def include_router(self, router: Router) -> None:
|
354
375
|
"""
|
@@ -1,8 +1,8 @@
|
|
1
1
|
from typing import Literal, Pattern
|
2
|
-
from abc import ABC, abstractmethod
|
3
2
|
|
4
3
|
|
5
|
-
|
4
|
+
|
5
|
+
class BaseFlag:
|
6
6
|
def __init__(self, name: str,
|
7
7
|
prefix: Literal['-', '--', '---'] = '--') -> None:
|
8
8
|
"""
|
@@ -37,38 +37,6 @@ class BaseFlag(ABC):
|
|
37
37
|
return self._prefix
|
38
38
|
|
39
39
|
|
40
|
-
|
41
|
-
class InputFlag(BaseFlag):
|
42
|
-
def __init__(self, name: str,
|
43
|
-
prefix: Literal['-', '--', '---'] = '--',
|
44
|
-
value: str = None):
|
45
|
-
"""
|
46
|
-
Public. The entity of the flag of the entered command
|
47
|
-
:param name: the name of the input flag
|
48
|
-
:param prefix: the prefix of the input flag
|
49
|
-
:param value: the value of the input flag
|
50
|
-
:return: None
|
51
|
-
"""
|
52
|
-
super().__init__(name, prefix)
|
53
|
-
self._flag_value = value
|
54
|
-
|
55
|
-
def get_value(self) -> str | None:
|
56
|
-
"""
|
57
|
-
Public. Returns the value of the flag
|
58
|
-
:return: the value of the flag as str
|
59
|
-
"""
|
60
|
-
return self._flag_value
|
61
|
-
|
62
|
-
def set_value(self, value):
|
63
|
-
"""
|
64
|
-
Private. Sets the value of the flag
|
65
|
-
:param value: the fag value to set
|
66
|
-
:return: None
|
67
|
-
"""
|
68
|
-
self._flag_value = value
|
69
|
-
|
70
|
-
|
71
|
-
|
72
40
|
class Flag(BaseFlag):
|
73
41
|
def __init__(self, name: str,
|
74
42
|
prefix: Literal['-', '--', '---'] = '--',
|
@@ -113,106 +81,32 @@ class Flag(BaseFlag):
|
|
113
81
|
return True
|
114
82
|
|
115
83
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
"""
|
121
|
-
__slots__ = ('_flags',)
|
122
|
-
|
123
|
-
@abstractmethod
|
124
|
-
def get_flags(self):
|
125
|
-
"""
|
126
|
-
Public. Returns a list of flags
|
127
|
-
:return: list of flags
|
128
|
-
"""
|
129
|
-
pass
|
130
|
-
|
131
|
-
@abstractmethod
|
132
|
-
def add_flag(self, flag: Flag | InputFlag):
|
133
|
-
"""
|
134
|
-
Public. Adds a flag to the list of flags
|
135
|
-
:param flag: flag to add
|
136
|
-
:return: None
|
137
|
-
"""
|
138
|
-
pass
|
139
|
-
|
140
|
-
@abstractmethod
|
141
|
-
def add_flags(self, flags: list[Flag] | list[InputFlag]):
|
84
|
+
class InputFlag(BaseFlag):
|
85
|
+
def __init__(self, name: str,
|
86
|
+
prefix: Literal['-', '--', '---'] = '--',
|
87
|
+
value: str = None):
|
142
88
|
"""
|
143
|
-
Public.
|
144
|
-
:param
|
89
|
+
Public. The entity of the flag of the entered command
|
90
|
+
:param name: the name of the input flag
|
91
|
+
:param prefix: the prefix of the input flag
|
92
|
+
:param value: the value of the input flag
|
145
93
|
:return: None
|
146
94
|
"""
|
147
|
-
|
148
|
-
|
149
|
-
@abstractmethod
|
150
|
-
def get_flag(self, name: str):
|
151
|
-
"""
|
152
|
-
Public. Returns the flag entity by its name or None if not found
|
153
|
-
:param name: the name of the flag to get
|
154
|
-
:return: entity of the flag or None
|
155
|
-
"""
|
156
|
-
pass
|
157
|
-
|
158
|
-
def __iter__(self):
|
159
|
-
return iter(self._flags)
|
160
|
-
|
161
|
-
def __next__(self):
|
162
|
-
return next(iter(self))
|
163
|
-
|
164
|
-
def __getitem__(self, item):
|
165
|
-
return self._flags[item]
|
166
|
-
|
167
|
-
|
95
|
+
super().__init__(name, prefix)
|
96
|
+
self._flag_value = value
|
168
97
|
|
169
|
-
|
170
|
-
def __init__(self, *flags: Flag):
|
98
|
+
def get_value(self) -> str | None:
|
171
99
|
"""
|
172
|
-
Public.
|
173
|
-
:
|
174
|
-
:return: None
|
100
|
+
Public. Returns the value of the flag
|
101
|
+
:return: the value of the flag as str
|
175
102
|
"""
|
176
|
-
self.
|
177
|
-
|
178
|
-
def get_flags(self) -> list[Flag]:
|
179
|
-
return self._flags
|
180
|
-
|
181
|
-
def add_flag(self, flag: Flag):
|
182
|
-
self._flags.append(flag)
|
183
|
-
|
184
|
-
def add_flags(self, flags: list[Flag]):
|
185
|
-
self._flags.extend(flags)
|
186
|
-
|
187
|
-
def get_flag(self, name: str) -> Flag | None:
|
188
|
-
if name in [flag.get_name() for flag in self._flags]:
|
189
|
-
return list(filter(lambda flag: flag.get_name() == name, self._flags))[0]
|
190
|
-
else:
|
191
|
-
return None
|
192
|
-
|
193
|
-
|
103
|
+
return self._flag_value
|
194
104
|
|
195
|
-
|
196
|
-
def __init__(self, *flags: InputFlag):
|
105
|
+
def set_value(self, value):
|
197
106
|
"""
|
198
|
-
|
199
|
-
:param
|
107
|
+
Private. Sets the value of the flag
|
108
|
+
:param value: the fag value to set
|
200
109
|
:return: None
|
201
110
|
"""
|
202
|
-
self.
|
203
|
-
|
204
|
-
def get_flags(self) -> list[InputFlag]:
|
205
|
-
return self._flags
|
206
|
-
|
207
|
-
def add_flag(self, flag: InputFlag):
|
208
|
-
self._flags.append(flag)
|
209
|
-
|
210
|
-
def add_flags(self, flags: list[InputFlag]):
|
211
|
-
self._flags.extend(flags)
|
212
|
-
|
213
|
-
def get_flag(self, name: str) -> InputFlag | None:
|
214
|
-
if name in [flag.get_name() for flag in self._flags]:
|
215
|
-
return list(filter(lambda flag: flag.get_name() == name, self._flags))[0]
|
216
|
-
else:
|
217
|
-
return None
|
111
|
+
self._flag_value = value
|
218
112
|
|
@@ -0,0 +1,75 @@
|
|
1
|
+
from argenta.command.flag.models import InputFlag, Flag
|
2
|
+
from typing import Generic, TypeVar
|
3
|
+
|
4
|
+
|
5
|
+
|
6
|
+
FlagType = TypeVar('FlagType')
|
7
|
+
|
8
|
+
|
9
|
+
class BaseFlags(Generic[FlagType]):
|
10
|
+
def __init__(self, *flags: FlagType):
|
11
|
+
"""
|
12
|
+
Public. A model that combines the registered flags
|
13
|
+
:param flags: the flags that will be registered
|
14
|
+
:return: None
|
15
|
+
"""
|
16
|
+
self._flags = flags if flags else []
|
17
|
+
|
18
|
+
def get_flags(self) -> list[FlagType]:
|
19
|
+
"""
|
20
|
+
Public. Returns a list of flags
|
21
|
+
:return: list of flags as list[FlagType]
|
22
|
+
"""
|
23
|
+
return self._flags
|
24
|
+
|
25
|
+
def add_flag(self, flag: FlagType):
|
26
|
+
"""
|
27
|
+
Public. Adds a flag to the list of flags
|
28
|
+
:param flag: flag to add
|
29
|
+
:return: None
|
30
|
+
"""
|
31
|
+
self._flags.append(flag)
|
32
|
+
|
33
|
+
def add_flags(self, flags: list[FlagType]):
|
34
|
+
"""
|
35
|
+
Public. Adds a list of flags to the list of flags
|
36
|
+
:param flags: list of flags to add
|
37
|
+
:return: None
|
38
|
+
"""
|
39
|
+
self._flags.extend(flags)
|
40
|
+
|
41
|
+
def get_flag(self, name: str) -> FlagType | None:
|
42
|
+
"""
|
43
|
+
Public. Returns the flag entity by its name or None if not found
|
44
|
+
:param name: the name of the flag to get
|
45
|
+
:return: entity of the flag or None
|
46
|
+
"""
|
47
|
+
if name in [flag.get_name() for flag in self._flags]:
|
48
|
+
return list(filter(lambda flag: flag.get_name() == name, self._flags))[0]
|
49
|
+
else:
|
50
|
+
return None
|
51
|
+
|
52
|
+
def __iter__(self):
|
53
|
+
return iter(self._flags)
|
54
|
+
|
55
|
+
def __next__(self):
|
56
|
+
return next(iter(self))
|
57
|
+
|
58
|
+
def __getitem__(self, item):
|
59
|
+
return self._flags[item]
|
60
|
+
|
61
|
+
|
62
|
+
class Flags(BaseFlags[Flag]): pass
|
63
|
+
|
64
|
+
|
65
|
+
class InputFlags(BaseFlags[InputFlag]): pass
|
66
|
+
|
67
|
+
|
68
|
+
class ValidInputFlags(InputFlags): pass
|
69
|
+
|
70
|
+
|
71
|
+
class UndefinedInputFlags(InputFlags): pass
|
72
|
+
|
73
|
+
|
74
|
+
class InvalidValueInputFlags(InputFlags): pass
|
75
|
+
|
@@ -1,4 +1,5 @@
|
|
1
|
-
from argenta.command.flag.models import Flag, InputFlag
|
1
|
+
from argenta.command.flag.models import Flag, InputFlag
|
2
|
+
from argenta.command.flags.models import InputFlags, Flags
|
2
3
|
from argenta.command.exceptions import (UnprocessedInputFlagException,
|
3
4
|
RepeatedInputFlagsException,
|
4
5
|
EmptyInputCommandException)
|
@@ -55,7 +56,7 @@ class Command(BaseCommand):
|
|
55
56
|
"""
|
56
57
|
return self._aliases
|
57
58
|
|
58
|
-
def validate_input_flag(self, flag: InputFlag) ->
|
59
|
+
def validate_input_flag(self, flag: InputFlag) -> Literal['Undefined', 'Valid', 'Invalid']:
|
59
60
|
"""
|
60
61
|
Private. Validates the input flag
|
61
62
|
:param flag: input flag for validation
|
@@ -67,14 +68,21 @@ class Command(BaseCommand):
|
|
67
68
|
if registered_flags.get_string_entity() == flag.get_string_entity():
|
68
69
|
is_valid = registered_flags.validate_input_flag_value(flag.get_value())
|
69
70
|
if is_valid:
|
70
|
-
return
|
71
|
+
return 'Valid'
|
72
|
+
else:
|
73
|
+
return 'Invalid'
|
74
|
+
else:
|
75
|
+
return 'Undefined'
|
71
76
|
else:
|
72
77
|
for registered_flag in registered_flags:
|
73
78
|
if registered_flag.get_string_entity() == flag.get_string_entity():
|
74
79
|
is_valid = registered_flag.validate_input_flag_value(flag.get_value())
|
75
80
|
if is_valid:
|
76
|
-
return
|
77
|
-
|
81
|
+
return 'Valid'
|
82
|
+
else:
|
83
|
+
return 'Invalid'
|
84
|
+
return 'Undefined'
|
85
|
+
return 'Undefined'
|
78
86
|
|
79
87
|
def get_description(self) -> str:
|
80
88
|
"""
|
@@ -131,11 +139,11 @@ class InputCommand(BaseCommand, Generic[InputCommandType]):
|
|
131
139
|
|
132
140
|
for k, _ in enumerate(list_of_tokens):
|
133
141
|
if _.startswith('-'):
|
134
|
-
if
|
142
|
+
if len(_) < 2 or len(_[:_.rfind('-')]) > 3:
|
135
143
|
raise UnprocessedInputFlagException()
|
136
144
|
current_flag_name = _
|
137
145
|
else:
|
138
|
-
if not current_flag_name:
|
146
|
+
if not current_flag_name or current_flag_value:
|
139
147
|
raise UnprocessedInputFlagException()
|
140
148
|
current_flag_value = _
|
141
149
|
|
@@ -144,9 +152,9 @@ class InputCommand(BaseCommand, Generic[InputCommandType]):
|
|
144
152
|
if not list_of_tokens[k+1].startswith('-'):
|
145
153
|
continue
|
146
154
|
|
147
|
-
input_flag = InputFlag(name=current_flag_name[current_flag_name.rfind('-')+1:],
|
155
|
+
input_flag = InputFlag(name=current_flag_name[current_flag_name.rfind('-') + 1:],
|
148
156
|
prefix=cast(Literal['-', '--', '---'],
|
149
|
-
|
157
|
+
current_flag_name[:current_flag_name.rfind('-')+1]),
|
150
158
|
value=current_flag_value)
|
151
159
|
|
152
160
|
all_flags = [flag.get_string_entity() for flag in input_flags.get_flags()]
|
@@ -0,0 +1,20 @@
|
|
1
|
+
from argenta.command.flags.models import ValidInputFlags, UndefinedInputFlags, InvalidValueInputFlags
|
2
|
+
from argenta.response.status import Status
|
3
|
+
|
4
|
+
|
5
|
+
class Response:
|
6
|
+
def __init__(self, status: Status = None,
|
7
|
+
valid_flags: ValidInputFlags = ValidInputFlags(),
|
8
|
+
undefined_flags: UndefinedInputFlags = UndefinedInputFlags(),
|
9
|
+
invalid_value_flags: InvalidValueInputFlags = InvalidValueInputFlags()):
|
10
|
+
"""
|
11
|
+
Public. The entity of the user input sent to the handler
|
12
|
+
:param status: the status of the response
|
13
|
+
:param valid_flags: valid input flags
|
14
|
+
:param undefined_flags: undefined input flags
|
15
|
+
:param invalid_value_flags: input flags with invalid values
|
16
|
+
"""
|
17
|
+
self.status = status
|
18
|
+
self.valid_flags = valid_flags
|
19
|
+
self.undefined_flags = undefined_flags
|
20
|
+
self.invalid_value_flags = invalid_value_flags
|
@@ -1,12 +1,11 @@
|
|
1
1
|
from typing import Callable, Iterator
|
2
2
|
|
3
3
|
from argenta.command import Command
|
4
|
-
from argenta.
|
5
|
-
|
4
|
+
from argenta.response import Response
|
6
5
|
|
7
6
|
|
8
7
|
class CommandHandler:
|
9
|
-
def __init__(self, handler: Callable[[], None]
|
8
|
+
def __init__(self, handler: Callable[[Response], None], handled_command: Command):
|
10
9
|
"""
|
11
10
|
Private. Entity of the model linking the handler and the command being processed
|
12
11
|
:param handler: the handler being called
|
@@ -15,21 +14,18 @@ class CommandHandler:
|
|
15
14
|
self._handler = handler
|
16
15
|
self._handled_command = handled_command
|
17
16
|
|
18
|
-
def handling(self,
|
17
|
+
def handling(self, response: Response) -> None:
|
19
18
|
"""
|
20
19
|
Private. Direct processing of an input command
|
21
|
-
:param
|
20
|
+
:param response: the entity of response: various groups of flags and status of response
|
22
21
|
:return: None
|
23
22
|
"""
|
24
|
-
|
25
|
-
self._handler(input_flags)
|
26
|
-
else:
|
27
|
-
self._handler()
|
23
|
+
self._handler(response)
|
28
24
|
|
29
|
-
def get_handler(self) -> Callable[[], None]
|
25
|
+
def get_handler(self) -> Callable[[Response], None]:
|
30
26
|
"""
|
31
27
|
Private. Returns the handler being called
|
32
|
-
:return: the handler being called as Callable[[], None]
|
28
|
+
:return: the handler being called as Callable[[Response], None]
|
33
29
|
"""
|
34
30
|
return self._handler
|
35
31
|
|
@@ -1,9 +1,12 @@
|
|
1
|
-
from typing import Callable
|
2
|
-
from inspect import getfullargspec
|
1
|
+
from typing import Callable, Literal, Type
|
2
|
+
from inspect import getfullargspec, get_annotations
|
3
|
+
from rich.console import Console
|
4
|
+
|
3
5
|
from argenta.command import Command
|
4
6
|
from argenta.command.models import InputCommand
|
7
|
+
from argenta.response import Response, Status
|
5
8
|
from argenta.router.command_handler.entity import CommandHandlers, CommandHandler
|
6
|
-
from argenta.command.
|
9
|
+
from argenta.command.flags.models import Flags, InputFlags, UndefinedInputFlags, ValidInputFlags, InvalidValueInputFlags
|
7
10
|
from argenta.router.exceptions import (RepeatedFlagNameException,
|
8
11
|
TooManyTransferredArgsException,
|
9
12
|
RequiredArgumentNotPassedException,
|
@@ -11,8 +14,7 @@ from argenta.router.exceptions import (RepeatedFlagNameException,
|
|
11
14
|
|
12
15
|
|
13
16
|
class Router:
|
14
|
-
def __init__(self,
|
15
|
-
title: str = None):
|
17
|
+
def __init__(self, title: str = None):
|
16
18
|
"""
|
17
19
|
Public. Directly configures and manages handlers
|
18
20
|
:param title: the title of the router, displayed when displaying the available commands
|
@@ -22,19 +24,18 @@ class Router:
|
|
22
24
|
|
23
25
|
self._command_handlers: CommandHandlers = CommandHandlers()
|
24
26
|
self._ignore_command_register: bool = False
|
25
|
-
self._not_valid_flag_handler: Callable[[Flag], None] = lambda flag: print(f"Undefined or incorrect input flag: {flag.get_string_entity()}{(' '+flag.get_value()) if flag.get_value() else ''}")
|
26
27
|
|
27
28
|
|
28
29
|
def command(self, command: Command) -> Callable:
|
29
30
|
"""
|
30
31
|
Public. Registers handler
|
31
32
|
:param command: Registered command
|
32
|
-
:return: decorated handler as Callable
|
33
|
+
:return: decorated handler as Callable
|
33
34
|
"""
|
34
35
|
self._validate_command(command)
|
35
36
|
|
36
37
|
def command_decorator(func):
|
37
|
-
Router._validate_func_args(
|
38
|
+
Router._validate_func_args(func)
|
38
39
|
self._command_handlers.add_handler(CommandHandler(func, command))
|
39
40
|
|
40
41
|
def wrapper(*args, **kwargs):
|
@@ -44,15 +45,6 @@ class Router:
|
|
44
45
|
return command_decorator
|
45
46
|
|
46
47
|
|
47
|
-
def set_invalid_input_flag_handler(self, func: Callable[[Flag], None]) -> None:
|
48
|
-
"""
|
49
|
-
Public. Registers handler for invalid input flag
|
50
|
-
:param func: registered handler
|
51
|
-
:return: None
|
52
|
-
"""
|
53
|
-
self._not_valid_flag_handler = func
|
54
|
-
|
55
|
-
|
56
48
|
def finds_appropriate_handler(self, input_command: InputCommand) -> None:
|
57
49
|
"""
|
58
50
|
Private. Finds the appropriate handler for given input command and passes control to it
|
@@ -78,36 +70,61 @@ class Router:
|
|
78
70
|
:return: None
|
79
71
|
"""
|
80
72
|
handle_command = command_handler.get_handled_command()
|
73
|
+
response: Response = Response()
|
81
74
|
if handle_command.get_registered_flags().get_flags():
|
82
75
|
if input_command_flags.get_flags():
|
83
|
-
|
84
|
-
|
85
|
-
|
76
|
+
flags, status = self._validate_input_flags(handle_command, input_command_flags)
|
77
|
+
response.valid_flags, response.undefined_flags, response.invalid_value_flags = flags
|
78
|
+
response.status = status
|
79
|
+
command_handler.handling(response)
|
86
80
|
else:
|
87
|
-
|
88
|
-
|
81
|
+
response.status = Status.ALL_FLAGS_VALID
|
82
|
+
command_handler.handling(response)
|
89
83
|
else:
|
90
84
|
if input_command_flags.get_flags():
|
91
|
-
|
92
|
-
|
85
|
+
response.status = Status.UNDEFINED_FLAGS
|
86
|
+
response.undefined_flags = UndefinedInputFlags()
|
87
|
+
response.undefined_flags.add_flags(input_command_flags.get_flags())
|
88
|
+
command_handler.handling(response)
|
93
89
|
else:
|
94
|
-
|
95
|
-
|
90
|
+
response.status = Status.ALL_FLAGS_VALID
|
91
|
+
command_handler.handling(response)
|
96
92
|
|
97
93
|
|
98
|
-
|
94
|
+
@staticmethod
|
95
|
+
def _validate_input_flags(handled_command: Command, input_flags: InputFlags) -> tuple[tuple[ValidInputFlags,
|
96
|
+
UndefinedInputFlags,
|
97
|
+
InvalidValueInputFlags],
|
98
|
+
Status]:
|
99
99
|
"""
|
100
100
|
Private. Validates flags of input command
|
101
101
|
:param handled_command: entity of the handled command
|
102
102
|
:param input_flags:
|
103
103
|
:return: is flags of input command valid as bool
|
104
104
|
"""
|
105
|
+
valid_input_flags: ValidInputFlags = ValidInputFlags()
|
106
|
+
invalid_value_input_flags: InvalidValueInputFlags = InvalidValueInputFlags()
|
107
|
+
undefined_input_flags: UndefinedInputFlags = UndefinedInputFlags()
|
105
108
|
for flag in input_flags:
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
109
|
+
flag_status: Literal['Undefined', 'Valid', 'Invalid'] = handled_command.validate_input_flag(flag)
|
110
|
+
match flag_status:
|
111
|
+
case 'Valid':
|
112
|
+
valid_input_flags.add_flag(flag)
|
113
|
+
case 'Undefined':
|
114
|
+
undefined_input_flags.add_flag(flag)
|
115
|
+
case 'Invalid':
|
116
|
+
invalid_value_input_flags.add_flag(flag)
|
117
|
+
|
118
|
+
if not invalid_value_input_flags.get_flags() and not undefined_input_flags.get_flags():
|
119
|
+
status = Status.ALL_FLAGS_VALID
|
120
|
+
elif invalid_value_input_flags.get_flags() and not undefined_input_flags.get_flags():
|
121
|
+
status = Status.INVALID_VALUE_FLAGS
|
122
|
+
elif not invalid_value_input_flags.get_flags() and undefined_input_flags.get_flags():
|
123
|
+
status = Status.UNDEFINED_FLAGS
|
124
|
+
else:
|
125
|
+
status = Status.UNDEFINED_AND_INVALID_FLAGS
|
126
|
+
|
127
|
+
return (valid_input_flags, undefined_input_flags, invalid_value_input_flags), status
|
111
128
|
|
112
129
|
|
113
130
|
@staticmethod
|
@@ -129,22 +146,23 @@ class Router:
|
|
129
146
|
|
130
147
|
|
131
148
|
@staticmethod
|
132
|
-
def _validate_func_args(
|
149
|
+
def _validate_func_args(func: Callable) -> None:
|
133
150
|
"""
|
134
151
|
Private. Validates the arguments of the handler
|
135
|
-
:param command: registered command in handler
|
136
152
|
:param func: entity of the handler func
|
137
153
|
:return: None if func is valid else raise exception
|
138
154
|
"""
|
139
|
-
registered_args = command.get_registered_flags()
|
140
155
|
transferred_args = getfullargspec(func).args
|
141
|
-
if
|
142
|
-
if len(transferred_args) != 1:
|
143
|
-
raise TooManyTransferredArgsException()
|
144
|
-
elif registered_args.get_flags() and not transferred_args:
|
145
|
-
raise RequiredArgumentNotPassedException()
|
146
|
-
elif not registered_args.get_flags() and transferred_args:
|
156
|
+
if len(transferred_args) > 1:
|
147
157
|
raise TooManyTransferredArgsException()
|
158
|
+
elif len(transferred_args) == 0:
|
159
|
+
raise RequiredArgumentNotPassedException()
|
160
|
+
|
161
|
+
arg_annotation: Type = get_annotations(func)[transferred_args[0]]
|
162
|
+
if not arg_annotation is Response:
|
163
|
+
Console().print(f'\n\n[b red]WARNING:[/b red] [i]The type of argument passed to the handler is [/i][blue]{Response}[/blue],'
|
164
|
+
f' [i]but[/i] [bold blue]{arg_annotation}[/bold blue] [i]is specified[/i]', highlight=False)
|
165
|
+
|
148
166
|
|
149
167
|
|
150
168
|
def set_command_register_ignore(self, _: bool) -> None:
|
@@ -1,22 +0,0 @@
|
|
1
|
-
from rich.console import Console
|
2
|
-
|
3
|
-
from argenta.command import Command
|
4
|
-
from argenta.router import Router
|
5
|
-
|
6
|
-
|
7
|
-
work_router: Router = Router(title='Work points:')
|
8
|
-
|
9
|
-
console = Console()
|
10
|
-
|
11
|
-
|
12
|
-
@work_router.command(Command('get', 'Get Help', aliases=['help', 'Get_help']))
|
13
|
-
def command_help():
|
14
|
-
pass
|
15
|
-
|
16
|
-
|
17
|
-
@work_router.command(Command('run', 'Run All'))
|
18
|
-
def command_start_solving():
|
19
|
-
pass
|
20
|
-
|
21
|
-
|
22
|
-
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{argenta-1.0.0a5 → argenta-1.0.0b1}/mock/mock_app/handlers/handlers_implementation/__init__.py
RENAMED
File without changes
|
{argenta-1.0.0a5 → argenta-1.0.0b1}/mock/mock_app/handlers/handlers_implementation/help_command.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{argenta-1.0.0a5 → argenta-1.0.0b1}/src/argenta/orchestrator/argparser/arguments/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{argenta-1.0.0a5 → argenta-1.0.0b1}/tests/system_tests/test_system_handling_non_standard_behavior.py
RENAMED
File without changes
|
{argenta-1.0.0a5 → argenta-1.0.0b1}/tests/system_tests/test_system_handling_normal_behavior.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|