argenta 1.0.0a4__py3-none-any.whl → 1.0.0b1__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/app/models.py CHANGED
@@ -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:
@@ -138,7 +139,7 @@ class BaseApp:
138
139
  """
139
140
  if isinstance(self._dividing_line, StaticDividingLine):
140
141
  self._print_func(self._dividing_line.get_full_static_line(self._override_system_messages))
141
- self._print_func(text)
142
+ print(text.strip('\n'))
142
143
  self._print_func(self._dividing_line.get_full_static_line(self._override_system_messages))
143
144
 
144
145
  elif isinstance(self._dividing_line, DynamicDividingLine):
@@ -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
- if not self._override_system_messages:
227
- self._initial_message = f'\n[bold red]{text2art(self._initial_message, font="tarty1")}\n\n'
228
- self._farewell_message = (f'[bold red]\n{text2art(f"\n{self._farewell_message}\n", font="chanky")}[/bold red]\n'
229
- f'[red i]github.com/koloideal/Argenta[/red i] | [red bold i]made by kolo[/red bold i]\n')
230
- self._description_message_gen = lambda command, description: (f'[bold red]{escape("[" + command + "]")}[/bold red] '
231
- f'[blue dim]*=*=*[/blue dim] '
232
- f'[bold yellow italic]{escape(description)}')
233
- self._invalid_input_flags_handler = lambda raw_command: self._print_func(f'[red bold]Incorrect flag syntax: {escape(raw_command)}')
234
- self._repeated_input_flags_handler = lambda raw_command: self._print_func(f'[red bold]Repeated input flags: {escape(raw_command)}')
235
- self._empty_input_command_handler = lambda: self._print_func('[red bold]Empty input command')
236
- self._unknown_command_handler = lambda command: self._print_func(f"[red bold]Unknown command: {escape(command.get_trigger())}")
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 = '[italic dim bold]What do you want to do?\n',
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,4 +1,4 @@
1
- from argenta.command.flag.models import InputFlag, Flag
1
+ from argenta.command.flag.models import Flag, InputFlag
2
2
 
3
3
 
4
4
  class BaseInputCommandException(Exception):
@@ -1,4 +1,4 @@
1
- __all__ = ('InputFlags', 'InputFlag', 'Flag', 'Flags')
1
+ __all__ = ["Flag", "InputFlag"]
2
2
 
3
3
 
4
- from argenta.command.flag.models import InputFlags, InputFlag, Flags, Flag
4
+ from argenta.command.flag.models import Flag, InputFlag
@@ -1,8 +1,8 @@
1
1
  from typing import Literal, Pattern
2
- from abc import ABC, abstractmethod
3
2
 
4
3
 
5
- class BaseFlag(ABC):
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
- class BaseFlags(ABC):
118
- """
119
- Private. Base class for groups of flags
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. Adds a list of flags to the list of flags
144
- :param flags: list of flags to add
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
- pass
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
- class Flags(BaseFlags, ABC):
170
- def __init__(self, *flags: Flag):
98
+ def get_value(self) -> str | None:
171
99
  """
172
- Public. A model that combines the registered flags
173
- :param flags: the flags that will be registered
174
- :return: None
100
+ Public. Returns the value of the flag
101
+ :return: the value of the flag as str
175
102
  """
176
- self._flags = flags if flags else []
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
- class InputFlags(BaseFlags, ABC):
196
- def __init__(self, *flags: InputFlag):
105
+ def set_value(self, value):
197
106
  """
198
- Public. A model that combines the input flags of the input command
199
- :param flags: all input flags
107
+ Private. Sets the value of the flag
108
+ :param value: the fag value to set
200
109
  :return: None
201
110
  """
202
- self._flags = flags if flags else []
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,10 @@
1
+ __all__ = ["Flags", "InputFlags",
2
+ "UndefinedInputFlags",
3
+ "InvalidValueInputFlags",
4
+ "ValidInputFlags"]
5
+
6
+
7
+ from argenta.command.flags.models import (Flags, InputFlags,
8
+ UndefinedInputFlags,
9
+ InvalidValueInputFlags,
10
+ ValidInputFlags)
@@ -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
+
argenta/command/models.py CHANGED
@@ -1,4 +1,5 @@
1
- from argenta.command.flag.models import Flag, InputFlag, Flags, InputFlags
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) -> bool:
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 True
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 True
77
- return False
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 current_flag_name or len(_) < 2 or len(_[:_.rfind('-')]) > 3:
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
- current_flag_name[:current_flag_name.rfind('-')+1]),
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,5 @@
1
+ __all__ = ["Response", "Status"]
2
+
3
+
4
+ from argenta.response.entity import Response
5
+ from argenta.response.status import Status
@@ -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
@@ -0,0 +1,9 @@
1
+ from enum import Enum
2
+
3
+
4
+ class Status(Enum):
5
+ ALL_FLAGS_VALID = 'ALL_FLAGS_VALID'
6
+ UNDEFINED_FLAGS = 'UNDEFINED_FLAGS'
7
+ INVALID_VALUE_FLAGS = 'INVALID_VALUE_FLAGS'
8
+ UNDEFINED_AND_INVALID_FLAGS = 'UNDEFINED_AND_INVALID_FLAGS'
9
+
@@ -1,12 +1,11 @@
1
1
  from typing import Callable, Iterator
2
2
 
3
3
  from argenta.command import Command
4
- from argenta.command.flag import InputFlags
5
-
4
+ from argenta.response import Response
6
5
 
7
6
 
8
7
  class CommandHandler:
9
- def __init__(self, handler: Callable[[], None] | Callable[[InputFlags], None], handled_command: Command):
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, input_flags: InputFlags = None) -> None:
17
+ def handling(self, response: Response) -> None:
19
18
  """
20
19
  Private. Direct processing of an input command
21
- :param input_flags: the flags of the input command
20
+ :param response: the entity of response: various groups of flags and status of response
22
21
  :return: None
23
22
  """
24
- if input_flags is not None:
25
- self._handler(input_flags)
26
- else:
27
- self._handler()
23
+ self._handler(response)
28
24
 
29
- def get_handler(self) -> Callable[[], None] | Callable[[InputFlags], 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] or Callable[[InputFlags], None]
28
+ :return: the handler being called as Callable[[Response], None]
33
29
  """
34
30
  return self._handler
35
31
 
argenta/router/entity.py CHANGED
@@ -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.flag.models import Flag, Flags, InputFlags
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[[Any], Any]
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(command, func)
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
- if self._validate_input_flags(handle_command, input_command_flags):
84
- command_handler.handling(input_command_flags)
85
- return
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
- command_handler.handling(input_command_flags)
88
- return
81
+ response.status = Status.ALL_FLAGS_VALID
82
+ command_handler.handling(response)
89
83
  else:
90
84
  if input_command_flags.get_flags():
91
- self._not_valid_flag_handler(input_command_flags[0])
92
- return
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
- command_handler.handling()
95
- return
90
+ response.status = Status.ALL_FLAGS_VALID
91
+ command_handler.handling(response)
96
92
 
97
93
 
98
- def _validate_input_flags(self, handled_command: Command, input_flags: InputFlags) -> bool:
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
- is_valid: bool = handled_command.validate_input_flag(flag)
107
- if not is_valid:
108
- self._not_valid_flag_handler(flag)
109
- return False
110
- return True
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(command: Command, func: Callable) -> None:
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 registered_args.get_flags() and transferred_args:
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: argenta
3
- Version: 1.0.0a4
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
- ![preview](https://github.com/koloideal/Argenta/blob/kolo/imgs/mock_app_preview3.png?raw=True)
90
+ ![preview](https://github.com/koloideal/Argenta/blob/kolo/imgs/mock_app_preview4.png?raw=True)
91
91
  An example of the TUI appearance
92
92
 
93
93
  ---
@@ -1,7 +1,7 @@
1
1
  argenta/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  argenta/app/__init__.py,sha256=I8FTXU17ajDI-hbC6Rw0LxLmvDYipdQaos3v1pmu14E,57
3
3
  argenta/app/defaults.py,sha256=GE4UzsJ7PD7654weNzTFGcBroc_0Zy5H9VL5P8ZbFek,393
4
- argenta/app/models.py,sha256=4hGZhJ7t2bq8QgkDmH_ePghEhybJn0DYLo4t4gyc6rg,17160
4
+ argenta/app/models.py,sha256=h4MKbxu-CaZWV8ydjz14LoWO_TNIgjreY4CZlfBGcwQ,18250
5
5
  argenta/app/autocompleter/__init__.py,sha256=VT_p3QA78UnczV7pYR2NnwQ0Atd8mnDUnLazvUQNqJk,93
6
6
  argenta/app/autocompleter/entity.py,sha256=6IurcSTLfiEYrh-yYsCYjrKsJ8_9xds3fxs5sr0FoqE,2901
7
7
  argenta/app/dividing_line/__init__.py,sha256=jJZDDZix8XYCAUWW4FzGJH0JmJlchYcx0FPWifjgv1I,147
@@ -9,24 +9,29 @@ argenta/app/dividing_line/models.py,sha256=pDHZsUhgMJOGusMigS93a-4KXM-zqdQkahCdg
9
9
  argenta/app/registered_routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  argenta/app/registered_routers/entity.py,sha256=hNaY3YfCp62Dk3U1XGvqTjt8mYDzgXcMsgNJMAqIU4w,1076
11
11
  argenta/command/__init__.py,sha256=Plo2Da0fhq8H1eo2mg7nA1-OBLuGjK2BYpDGRvGGMIU,67
12
- argenta/command/exceptions.py,sha256=FLX4z7-mvCTRKO7_2_FfJVUbfNLf_Z-vwyZYDy6cnnY,1030
13
- argenta/command/models.py,sha256=-CTHYhiBYOUz-XmkNPIxC8-Ma0rb7e1uYwLodQlW4D4,6604
14
- argenta/command/flag/__init__.py,sha256=PaZAaqU3DgyO1o5do-xKhWV6TyEuOSaQTmE4VbPY6JA,136
12
+ argenta/command/exceptions.py,sha256=QvJl3fY3MxDZscQQKSQ__lRuP9Jd2XVdQOo27TvmVnw,1030
13
+ argenta/command/models.py,sha256=xXQ-xcyEKCMKSTYZTA7nUtg7Fy6vAIzJCeVvWGYQW48,6936
14
+ argenta/command/flag/__init__.py,sha256=4MOxfv8f2SkBzIfVo5LAZUTu4iH1jcs5WzPq60PhFMs,94
15
15
  argenta/command/flag/defaults.py,sha256=0wCvh2l3eNU3vTuxuARVaUwhEzG3v9FID0rBbXHyK-k,982
16
- argenta/command/flag/models.py,sha256=OYC4yfym1XPvGdtWtRFKJF48SuwZpVU3dalOIplm-zQ,6403
16
+ argenta/command/flag/models.py,sha256=tEc3p_EqOOjUDZ3Qv_wo0eDwbmr7p15u6sOy19zhZcs,3608
17
+ argenta/command/flags/__init__.py,sha256=Hpw8RO2_RxdRhS8EqWPGuLwAlmRLA-XkbO7q1iNxrvQ,396
18
+ argenta/command/flags/models.py,sha256=hHgp-SkTZWMjGLVdAwvLDkuulIGBMK2QY6BBP0wTP8o,1938
17
19
  argenta/orchestrator/__init__.py,sha256=vFtJEJTjFfoYP3DZx0gNlhoa0Tk8u-yzkGIUN3SiABA,86
18
20
  argenta/orchestrator/entity.py,sha256=HUKhoEQtiWvxeA3QhSkvTcIgwgXDLjmcB2cBFHlCGhw,1101
19
21
  argenta/orchestrator/argparser/__init__.py,sha256=twfb-FQqW4QUo2XkmMASi654KGiimIbrkEzb1ZkMGzU,88
20
22
  argenta/orchestrator/argparser/entity.py,sha256=nmwp7dFHTIqLvR9v0n_4j9wvtTowvLK7_SeoyaYL_RM,2145
21
23
  argenta/orchestrator/argparser/arguments/__init__.py,sha256=4T55Tl_4WKOYp9HtVDmzQZylYVKA_cb3XiGoBvAyjNo,318
22
24
  argenta/orchestrator/argparser/arguments/models.py,sha256=hSUXBjTsyzNKvyPgWhiNCa4SSQdmixIQnne2A9iuPMc,1546
25
+ argenta/response/__init__.py,sha256=u4NuwUQkWa55aX67hTQs_B_gIaZ9Dn4Fe7xhSFQ_Rpw,128
26
+ argenta/response/entity.py,sha256=_KXv-9oWsh4AfJDN1EZbcoACvtR3S3zruvCmpbK8LqU,942
27
+ argenta/response/status.py,sha256=owDBpCrJ0Xb6U5RtvYt9HTdM8ouVgJLFdzVD8h-Ho4w,246
23
28
  argenta/router/__init__.py,sha256=ldrIWTXNLXUAMAGQ8ex4e8nMso_fhi01nZi2DVzHnnk,66
24
29
  argenta/router/defaults.py,sha256=RX3DMbZk7XUbj6uR4uADhZOPqEDoeCz9X-n26YTCCPM,87
25
- argenta/router/entity.py,sha256=kW_mdL15V9jpRW72Z21sDMvsV3gVO6Bub0hKthYo8ao,7957
30
+ argenta/router/entity.py,sha256=QpTMtz7l5erAmIir4tSsCWy-iOR2e1pkCM6b39fkGYw,9437
26
31
  argenta/router/exceptions.py,sha256=q6y-4gmbgkX-0U4-qXHDP5HTtUQ_c4svaqVILn-ZzRw,852
27
32
  argenta/router/command_handler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
- argenta/router/command_handler/entity.py,sha256=VjSh5tpU-nGKkf8FUn5H_35DN7ZnwVaoVXOVqkoracE,2526
29
- argenta-1.0.0a4.dist-info/METADATA,sha256=cEC4BA9DRBaQleUKOoB0sqQshXbFvd2vpuhMeRD5cGg,25723
30
- argenta-1.0.0a4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
31
- argenta-1.0.0a4.dist-info/licenses/LICENSE,sha256=zmqoGh2n5rReBv4s8wPxF_gZEZDgauJYSPMuPczgOiU,1082
32
- argenta-1.0.0a4.dist-info/RECORD,,
33
+ argenta/router/command_handler/entity.py,sha256=z7X70yD66hAVug0Q-YKPxTLvYOZrLI6qZnPdFLCNmIQ,2385
34
+ argenta-1.0.0b1.dist-info/METADATA,sha256=Dbccwj_p-SK7sgV38hqwT9raCbC_q_yZHkL16Q6czj0,25723
35
+ argenta-1.0.0b1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
36
+ argenta-1.0.0b1.dist-info/licenses/LICENSE,sha256=zmqoGh2n5rReBv4s8wPxF_gZEZDgauJYSPMuPczgOiU,1082
37
+ argenta-1.0.0b1.dist-info/RECORD,,