argenta 1.0.5__py3-none-any.whl → 1.0.7__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.
@@ -5,7 +5,7 @@ from typing import Never
5
5
 
6
6
  class AutoCompleter:
7
7
  def __init__(
8
- self, history_filename: str = False, autocomplete_button: str = "tab"
8
+ self, history_filename: str | None = None, autocomplete_button: str = "tab"
9
9
  ) -> None:
10
10
  """
11
11
  Public. Configures and implements auto-completion of input command
argenta/app/defaults.py CHANGED
@@ -5,6 +5,7 @@ class PredefinedMessages(StrEnum):
5
5
  """
6
6
  Public. A dataclass with predetermined messages for quick use
7
7
  """
8
+
8
9
  USAGE = "[b dim]Usage[/b dim]: [i]<command> <[green]flags[/green]>[/i]"
9
10
  HELP = "[b dim]Help[/b dim]: [i]<command>[/i] [b red]--help[/b red]"
10
11
  AUTOCOMPLETE = "[b dim]Autocomplete[/b dim]: [i]<part>[/i] [bold]<tab>"
argenta/app/models.py CHANGED
@@ -21,9 +21,9 @@ from argenta.app.registered_routers.entity import RegisteredRouters
21
21
  from argenta.response import Response
22
22
 
23
23
 
24
+
24
25
  class BaseApp:
25
- def __init__(self,
26
- prompt: str,
26
+ def __init__(self, prompt: str,
27
27
  initial_message: str,
28
28
  farewell_message: str,
29
29
  exit_command: Command,
@@ -47,18 +47,33 @@ class BaseApp:
47
47
  self._farewell_message = farewell_message
48
48
  self._initial_message = initial_message
49
49
 
50
- self._description_message_gen: Callable[[str, str], str] = (lambda command, description: f"[{command}] *=*=* {description}")
50
+ self._description_message_gen: Callable[[str, str], str] = lambda command, description: f"{command} *=*=* {description}"
51
51
  self._registered_routers: RegisteredRouters = RegisteredRouters()
52
52
  self._messages_on_startup: list[str] = []
53
53
 
54
- self._all_registered_triggers_in_lower_case: list[str] = []
55
- self._all_registered_triggers_in_default_case: list[str] = []
54
+ self._matching_lower_triggers_with_routers: dict[str, Router] = {}
55
+ self._matching_default_triggers_with_routers: dict[str, Router] = {}
56
+
57
+ if self._ignore_command_register:
58
+ self._current_matching_triggers_with_routers: dict[str, Router] = self._matching_lower_triggers_with_routers
59
+ else:
60
+ self._current_matching_triggers_with_routers: dict[str, Router] = self._matching_default_triggers_with_routers
56
61
 
57
- self._incorrect_input_syntax_handler: Callable[[str], None] = (lambda raw_command: print_func(f"Incorrect flag syntax: {raw_command}"))
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))
62
+ self._incorrect_input_syntax_handler: Callable[[str], None] = (
63
+ lambda raw_command: print_func(f"Incorrect flag syntax: {raw_command}")
64
+ )
65
+ self._repeated_input_flags_handler: Callable[[str], None] = (
66
+ lambda raw_command: print_func(f"Repeated input flags: {raw_command}")
67
+ )
68
+ self._empty_input_command_handler: Callable[[], None] = lambda: print_func(
69
+ "Empty input command"
70
+ )
71
+ self._unknown_command_handler: Callable[[InputCommand], None] = (
72
+ lambda command: print_func(f"Unknown command: {command.get_trigger()}")
73
+ )
74
+ self._exit_command_handler: Callable[[Response], None] = (
75
+ lambda response: print_func(self._farewell_message)
76
+ )
62
77
 
63
78
  def set_description_message_pattern(self, _: Callable[[str, str], str]) -> None:
64
79
  """
@@ -194,27 +209,28 @@ class BaseApp:
194
209
  """
195
210
  input_command_trigger = command.get_trigger()
196
211
  if self._ignore_command_register:
197
- if input_command_trigger.lower() in self._all_registered_triggers_in_lower_case:
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._all_registered_triggers_in_default_case:
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(self, error: BaseInputCommandException, raw_command: str) -> None:
219
+ def _error_handler(
220
+ self, error: BaseInputCommandException, raw_command: str
221
+ ) -> None:
205
222
  """
206
223
  Private. Handles parsing errors of the entered command
207
224
  :param error: error being handled
208
225
  :param raw_command: the raw input command
209
226
  :return: None
210
227
  """
211
- match error:
212
- case UnprocessedInputFlagException():
213
- self._incorrect_input_syntax_handler(raw_command)
214
- case RepeatedInputFlagsException():
215
- self._repeated_input_flags_handler(raw_command)
216
- case EmptyInputCommandException():
217
- self._empty_input_command_handler()
228
+ if isinstance(error, UnprocessedInputFlagException):
229
+ self._incorrect_input_syntax_handler(raw_command)
230
+ elif isinstance(error, RepeatedInputFlagsException):
231
+ self._repeated_input_flags_handler(raw_command)
232
+ elif isinstance(error, EmptyInputCommandException):
233
+ self._empty_input_command_handler()
218
234
 
219
235
  def _setup_system_router(self) -> None:
220
236
  """
@@ -232,11 +248,8 @@ class BaseApp:
232
248
  self._registered_routers.add_registered_router(system_router)
233
249
 
234
250
  def _most_similar_command(self, unknown_command: str) -> str | None:
235
- all_commands = (
236
- self._all_registered_triggers_in_lower_case
237
- if self._ignore_command_register
238
- else self._all_registered_triggers_in_default_case
239
- )
251
+ all_commands = list(self._current_matching_triggers_with_routers.keys())
252
+
240
253
  matches: list[str] | list = sorted(
241
254
  cmd for cmd in all_commands if cmd.startswith(unknown_command)
242
255
  )
@@ -256,35 +269,27 @@ class BaseApp:
256
269
  Private. Sets up default app view
257
270
  :return: None
258
271
  """
259
- self._prompt = "[italic dim bold]What do you want to do?\n"
260
- self._initial_message = (
261
- f"\n[bold red]{text2art(self._initial_message, font='tarty1')}\n"
262
- )
272
+ self._prompt = f"[italic dim bold]{self._prompt}"
273
+ self._initial_message = ("\n" + f"[bold red]{text2art(self._initial_message, font='tarty1')}" + "\n")
263
274
  self._farewell_message = (
264
- f"[bold red]\n{text2art(f'\n{self._farewell_message}\n', font='chanky')}[/bold red]\n"
265
- f"[red i]github.com/koloideal/Argenta[/red i] | [red bold i]made by kolo[/red bold i]\n"
275
+ "[bold red]\n\n"
276
+ + text2art(self._farewell_message, font="chanky")
277
+ + "\n[/bold red]\n"
278
+ "[red i]github.com/koloideal/Argenta[/red i] | [red bold i]made by kolo[/red bold i]\n"
266
279
  )
267
280
  self._description_message_gen = lambda command, description: (
268
281
  f"[bold red]{escape('[' + command + ']')}[/bold red] "
269
282
  f"[blue dim]*=*=*[/blue dim] "
270
283
  f"[bold yellow italic]{escape(description)}"
271
284
  )
272
- self._incorrect_input_syntax_handler = lambda raw_command: self._print_func(
273
- f"[red bold]Incorrect flag syntax: {escape(raw_command)}"
274
- )
275
- self._repeated_input_flags_handler = lambda raw_command: self._print_func(
276
- f"[red bold]Repeated input flags: {escape(raw_command)}"
277
- )
278
- self._empty_input_command_handler = lambda: self._print_func(
279
- "[red bold]Empty input command"
280
- )
285
+ self._incorrect_input_syntax_handler = lambda raw_command: self._print_func(f"[red bold]Incorrect flag syntax: {escape(raw_command)}")
286
+ self._repeated_input_flags_handler = lambda raw_command: self._print_func(f"[red bold]Repeated input flags: {escape(raw_command)}")
287
+ self._empty_input_command_handler = lambda: self._print_func("[red bold]Empty input command")
281
288
 
282
289
  def unknown_command_handler(command: InputCommand) -> None:
283
290
  cmd_trg: str = command.get_trigger()
284
291
  mst_sim_cmd: str | None = self._most_similar_command(cmd_trg)
285
- first_part_of_text = (
286
- f"[red]Unknown command:[/red] [blue]{escape(cmd_trg)}[/blue]"
287
- )
292
+ first_part_of_text = f"[red]Unknown command:[/red] [blue]{escape(cmd_trg)}[/blue]"
288
293
  second_part_of_text = (
289
294
  ("[red], most similar:[/red] " + ("[blue]" + mst_sim_cmd + "[/blue]"))
290
295
  if mst_sim_cmd
@@ -302,22 +307,22 @@ class BaseApp:
302
307
  self._setup_system_router()
303
308
 
304
309
  for router_entity in self._registered_routers:
305
- self._all_registered_triggers_in_default_case.extend(router_entity.get_triggers())
306
- self._all_registered_triggers_in_default_case.extend(router_entity.get_aliases())
310
+ router_triggers = router_entity.get_triggers()
311
+ router_aliases = router_entity.get_aliases()
312
+ combined = router_triggers + router_aliases
307
313
 
308
- self._all_registered_triggers_in_lower_case.extend([x.lower() for x in router_entity.get_triggers()])
309
- self._all_registered_triggers_in_lower_case.extend([x.lower() for x in router_entity.get_aliases()])
314
+ for trigger in combined:
315
+ self._matching_default_triggers_with_routers[trigger] = router_entity
316
+ self._matching_lower_triggers_with_routers[trigger.lower()] = router_entity
310
317
 
311
- self._autocompleter.initial_setup(self._all_registered_triggers_in_lower_case)
318
+ self._autocompleter.initial_setup(list(self._current_matching_triggers_with_routers.keys()))
312
319
 
313
- if self._ignore_command_register:
314
- for cmd in set(self._all_registered_triggers_in_lower_case):
315
- if self._all_registered_triggers_in_lower_case.count(cmd) != 1:
316
- Console().print(f"\n[b red]WARNING:[/b red] Overlapping trigger or alias: [b blue]{cmd}[/b blue]")
317
- else:
318
- for cmd in set(self._all_registered_triggers_in_default_case):
319
- if self._all_registered_triggers_in_default_case.count(cmd) != 1:
320
- Console().print(f"\n[b red]WARNING:[/b red] Overlapping trigger or alias: [b blue]{cmd}[/b blue]")
320
+ seen = {}
321
+ for item in list(self._current_matching_triggers_with_routers.keys()):
322
+ if item in seen:
323
+ Console().print(f"\n[b red]WARNING:[/b red] Overlapping trigger or alias: [b blue]{item}[/b blue]")
324
+ else:
325
+ seen[item] = True
321
326
 
322
327
  if not self._override_system_messages:
323
328
  self._setup_default_view()
@@ -333,18 +338,20 @@ class BaseApp:
333
338
 
334
339
 
335
340
  class App(BaseApp):
336
- def __init__(self,
337
- prompt: str = "What do you want to do?\n",
338
- initial_message: str = "Argenta\n",
339
- farewell_message: str = "\nSee you\n",
340
- exit_command: Command = Command("Q", "Exit command"),
341
- system_router_title: str | None = "System points:",
342
- ignore_command_register: bool = True,
343
- dividing_line: StaticDividingLine | DynamicDividingLine = StaticDividingLine(),
344
- repeat_command_groups: bool = True,
345
- override_system_messages: bool = False,
346
- autocompleter: AutoCompleter = AutoCompleter(),
347
- print_func: Callable[[str], None] = Console().print) -> None:
341
+ def __init__(
342
+ self,
343
+ prompt: str = "What do you want to do?\n",
344
+ initial_message: str = "Argenta\n",
345
+ farewell_message: str = "\nSee you\n",
346
+ exit_command: Command = Command("Q", "Exit command"),
347
+ system_router_title: str | None = "System points:",
348
+ ignore_command_register: bool = True,
349
+ dividing_line: StaticDividingLine | DynamicDividingLine = StaticDividingLine(),
350
+ repeat_command_groups: bool = True,
351
+ override_system_messages: bool = False,
352
+ autocompleter: AutoCompleter = AutoCompleter(),
353
+ print_func: Callable[[str], None] = Console().print,
354
+ ) -> None:
348
355
  """
349
356
  Public. The essence of the application itself.
350
357
  Configures and manages all aspects of the behavior and presentation of the user interacting with the user
@@ -361,17 +368,19 @@ class App(BaseApp):
361
368
  :param print_func: system messages text output function
362
369
  :return: None
363
370
  """
364
- super().__init__(prompt=prompt,
365
- initial_message=initial_message,
366
- farewell_message=farewell_message,
367
- exit_command=exit_command,
368
- system_router_title=system_router_title,
369
- ignore_command_register=ignore_command_register,
370
- dividing_line=dividing_line,
371
- repeat_command_groups=repeat_command_groups,
372
- override_system_messages=override_system_messages,
373
- autocompleter=autocompleter,
374
- print_func=print_func)
371
+ super().__init__(
372
+ prompt=prompt,
373
+ initial_message=initial_message,
374
+ farewell_message=farewell_message,
375
+ exit_command=exit_command,
376
+ system_router_title=system_router_title,
377
+ ignore_command_register=ignore_command_register,
378
+ dividing_line=dividing_line,
379
+ repeat_command_groups=repeat_command_groups,
380
+ override_system_messages=override_system_messages,
381
+ autocompleter=autocompleter,
382
+ print_func=print_func,
383
+ )
375
384
 
376
385
  def run_polling(self) -> None:
377
386
  """
@@ -386,9 +395,7 @@ class App(BaseApp):
386
395
  raw_command: str = Console().input(self._prompt)
387
396
 
388
397
  try:
389
- input_command: InputCommand = InputCommand.parse(
390
- raw_command=raw_command
391
- )
398
+ input_command: InputCommand = InputCommand.parse(raw_command=raw_command)
392
399
  except BaseInputCommandException as error:
393
400
  with redirect_stdout(io.StringIO()) as f:
394
401
  self._error_handler(error, raw_command)
@@ -398,14 +405,7 @@ class App(BaseApp):
398
405
 
399
406
  if self._is_exit_command(input_command):
400
407
  system_router.finds_appropriate_handler(input_command)
401
- if self._ignore_command_register:
402
- self._autocompleter.exit_setup(
403
- self._all_registered_triggers_in_lower_case
404
- )
405
- else:
406
- self._autocompleter.exit_setup(
407
- self._all_registered_triggers_in_default_case
408
- )
408
+ self._autocompleter.exit_setup(list(self._current_matching_triggers_with_routers.keys()))
409
409
  return
410
410
 
411
411
  if self._is_unknown_command(input_command):
@@ -415,11 +415,23 @@ class App(BaseApp):
415
415
  self._print_framed_text(res)
416
416
  continue
417
417
 
418
- with redirect_stdout(io.StringIO()) as f:
419
- for registered_router in self._registered_routers:
420
- registered_router.finds_appropriate_handler(input_command)
421
- res: str = f.getvalue()
422
- self._print_framed_text(res)
418
+ processing_router = self._current_matching_triggers_with_routers[input_command.get_trigger().lower()]
419
+
420
+ if processing_router.disable_redirect_stdout:
421
+ if isinstance(self._dividing_line, StaticDividingLine):
422
+ self._print_func(self._dividing_line.get_full_static_line(self._override_system_messages))
423
+ processing_router.finds_appropriate_handler(input_command)
424
+ self._print_func(self._dividing_line.get_full_static_line(self._override_system_messages))
425
+ else:
426
+ self._print_func(StaticDividingLine(self._dividing_line.get_unit_part()).get_full_static_line(self._override_system_messages))
427
+ processing_router.finds_appropriate_handler(input_command)
428
+ self._print_func(StaticDividingLine(self._dividing_line.get_unit_part()).get_full_static_line(self._override_system_messages))
429
+ else:
430
+ with redirect_stdout(io.StringIO()) as f:
431
+ processing_router.finds_appropriate_handler(input_command)
432
+ res: str = f.getvalue()
433
+ if res:
434
+ self._print_framed_text(res)
423
435
 
424
436
  def include_router(self, router: Router) -> None:
425
437
  """
@@ -4,7 +4,7 @@ from argenta.router import Router
4
4
 
5
5
 
6
6
  class RegisteredRouters:
7
- def __init__(self, registered_routers: list[Router] = None) -> None:
7
+ def __init__(self, registered_routers: list[Router] | None = None) -> None:
8
8
  """
9
9
  Private. Combines registered routers
10
10
  :param registered_routers: list of the registered routers
@@ -1,7 +1,17 @@
1
- __all__ = ["Flag", "InputFlag", "UndefinedInputFlags", "ValidInputFlags", "InvalidValueInputFlags", "Flags"]
1
+ __all__ = [
2
+ "Flag",
3
+ "InputFlag",
4
+ "UndefinedInputFlags",
5
+ "ValidInputFlags",
6
+ "InvalidValueInputFlags",
7
+ "Flags", "PossibleValues"
8
+ ]
2
9
 
3
10
 
4
- from argenta.command.flag.models import Flag, InputFlag
5
- from argenta.command.flag.flags.models import (UndefinedInputFlags,
6
- ValidInputFlags, Flags,
7
- InvalidValueInputFlags)
11
+ from argenta.command.flag.models import Flag, InputFlag, PossibleValues
12
+ from argenta.command.flag.flags.models import (
13
+ UndefinedInputFlags,
14
+ ValidInputFlags,
15
+ Flags,
16
+ InvalidValueInputFlags,
17
+ )
@@ -1,22 +1,23 @@
1
1
  from dataclasses import dataclass
2
- from argenta.command.flag.models import Flag
2
+ from argenta.command.flag.models import Flag, PossibleValues
3
3
  import re
4
4
 
5
5
 
6
+
6
7
  @dataclass
7
8
  class PredefinedFlags:
8
9
  """
9
10
  Public. A dataclass with predefined flags and most frequently used flags for quick use
10
11
  """
11
12
 
12
- HELP = Flag(name="help", possible_values=False)
13
- SHORT_HELP = Flag(name="H", prefix="-", possible_values=False)
13
+ HELP = Flag(name="help", possible_values=PossibleValues.DISABLE)
14
+ SHORT_HELP = Flag(name="H", prefix="-", possible_values=PossibleValues.DISABLE)
14
15
 
15
- INFO = Flag(name="info", possible_values=False)
16
- SHORT_INFO = Flag(name="I", prefix="-", possible_values=False)
16
+ INFO = Flag(name="info", possible_values=PossibleValues.DISABLE)
17
+ SHORT_INFO = Flag(name="I", prefix="-", possible_values=PossibleValues.DISABLE)
17
18
 
18
- ALL = Flag(name="all", possible_values=False)
19
- SHORT_ALL = Flag(name="A", prefix="-", possible_values=False)
19
+ ALL = Flag(name="all", possible_values=PossibleValues.DISABLE)
20
+ SHORT_ALL = Flag(name="A", prefix="-", possible_values=PossibleValues.DISABLE)
20
21
 
21
22
  HOST = Flag(
22
23
  name="host", possible_values=re.compile(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$")
@@ -1,6 +1,16 @@
1
+ from enum import Enum
1
2
  from typing import Literal, Pattern
2
3
 
3
4
 
5
+
6
+ class PossibleValues(Enum):
7
+ DISABLE: Literal[False] = False
8
+ ALL: Literal[True] = True
9
+
10
+ def __eq__(self, other: bool) -> bool:
11
+ return self.value == other
12
+
13
+
4
14
  class BaseFlag:
5
15
  def __init__(self, name: str, prefix: Literal["-", "--", "---"] = "--") -> None:
6
16
  """
@@ -43,7 +53,7 @@ class Flag(BaseFlag):
43
53
  self,
44
54
  name: str,
45
55
  prefix: Literal["-", "--", "---"] = "--",
46
- possible_values: list[str] | Pattern[str] | False = True,
56
+ possible_values: list[str] | Pattern[str] | PossibleValues = PossibleValues.ALL,
47
57
  ) -> None:
48
58
  """
49
59
  Public. The entity of the flag being registered for subsequent processing
@@ -61,7 +71,7 @@ class Flag(BaseFlag):
61
71
  :param input_flag_value: The input flag value to validate
62
72
  :return: whether the entered flag is valid as bool
63
73
  """
64
- if self.possible_values is False:
74
+ if self.possible_values == PossibleValues.DISABLE:
65
75
  if input_flag_value is None:
66
76
  return True
67
77
  else:
@@ -87,7 +97,10 @@ class Flag(BaseFlag):
87
97
 
88
98
  class InputFlag(BaseFlag):
89
99
  def __init__(
90
- self, name: str, prefix: Literal["-", "--", "---"] = "--", value: str = None
100
+ self,
101
+ name: str,
102
+ prefix: Literal["-", "--", "---"] = "--",
103
+ value: str | None = None,
91
104
  ):
92
105
  """
93
106
  Public. The entity of the flag of the entered command
argenta/command/models.py CHANGED
@@ -5,10 +5,7 @@ from argenta.command.exceptions import (
5
5
  RepeatedInputFlagsException,
6
6
  EmptyInputCommandException,
7
7
  )
8
- from typing import Generic, TypeVar, cast, Literal
9
-
10
-
11
- InputCommandType = TypeVar("InputCommandType")
8
+ from typing import cast, Literal
12
9
 
13
10
 
14
11
  class BaseCommand:
@@ -31,9 +28,9 @@ class Command(BaseCommand):
31
28
  def __init__(
32
29
  self,
33
30
  trigger: str,
34
- description: str = None,
35
- flags: Flag | Flags = None,
36
- aliases: list[str] = None,
31
+ description: str | None = None,
32
+ flags: Flag | Flags | None = None,
33
+ aliases: list[str] | None = None,
37
34
  ):
38
35
  """
39
36
  Public. The command that can and should be registered in the Router
@@ -94,6 +91,7 @@ class Command(BaseCommand):
94
91
  is_valid = registered_flag.validate_input_flag_value(
95
92
  flag.get_value()
96
93
  )
94
+
97
95
  if is_valid:
98
96
  return "Valid"
99
97
  else:
@@ -109,8 +107,8 @@ class Command(BaseCommand):
109
107
  return self._description
110
108
 
111
109
 
112
- class InputCommand(BaseCommand, Generic[InputCommandType]):
113
- def __init__(self, trigger: str, input_flags: InputFlag | InputFlags = None):
110
+ class InputCommand(BaseCommand):
111
+ def __init__(self, trigger: str, input_flags: InputFlag | InputFlags | None = None):
114
112
  """
115
113
  Private. The model of the input command, after parsing
116
114
  :param trigger:the trigger of the command
@@ -142,7 +140,7 @@ class InputCommand(BaseCommand, Generic[InputCommandType]):
142
140
  return self._input_flags
143
141
 
144
142
  @staticmethod
145
- def parse(raw_command: str) -> InputCommandType:
143
+ def parse(raw_command: str) -> "InputCommand":
146
144
  """
147
145
  Private. Parse the raw input command
148
146
  :param raw_command: raw input command
argenta/metrics/main.py CHANGED
@@ -2,25 +2,17 @@ import io
2
2
  from contextlib import redirect_stdout
3
3
  from time import time
4
4
 
5
- from argenta.router import Router
6
- from argenta.command import Command
7
- from argenta.response import Response
8
- from argenta.response.status import Status
9
- from argenta.command.flag import Flag, Flags
10
5
  from argenta.app import App
11
6
 
12
7
 
13
8
  def get_time_of_pre_cycle_setup(app: App) -> float:
9
+ """
10
+ Public. Return time of pre cycle setup
11
+ :param app: app instance for testing time of pre cycle setup
12
+ :return: time of pre cycle setup as float
13
+ """
14
14
  start = time()
15
15
  with redirect_stdout(io.StringIO()):
16
16
  app.pre_cycle_setup()
17
17
  end = time()
18
18
  return end - start
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
@@ -5,13 +5,13 @@ from argenta.orchestrator.argparser import ArgParser
5
5
 
6
6
 
7
7
  class Orchestrator:
8
- def __init__(self, arg_parser: ArgParser = False):
8
+ def __init__(self, arg_parser: ArgParser | None = None):
9
9
  """
10
10
  Public. An orchestrator and configurator that defines the behavior of an integrated system, one level higher than the App
11
11
  :param arg_parser: Cmd argument parser and configurator at startup
12
12
  :return: None
13
13
  """
14
- self.arg_parser: ArgParser | False = arg_parser
14
+ self.arg_parser: ArgParser | None = arg_parser
15
15
  if arg_parser:
16
16
  self.arg_parser.register_args()
17
17
 
@@ -11,7 +11,7 @@ class Response:
11
11
 
12
12
  def __init__(
13
13
  self,
14
- status: Status = None,
14
+ status: Status | None = None,
15
15
  valid_flags: ValidInputFlags = ValidInputFlags(),
16
16
  undefined_flags: UndefinedInputFlags = UndefinedInputFlags(),
17
17
  invalid_value_flags: InvalidValueInputFlags = InvalidValueInputFlags(),
@@ -38,7 +38,7 @@ class CommandHandler:
38
38
 
39
39
 
40
40
  class CommandHandlers:
41
- def __init__(self, command_handlers: list[CommandHandler] = None):
41
+ def __init__(self, command_handlers: list[CommandHandler] | None = None):
42
42
  """
43
43
  Private. The model that unites all CommandHandler of the routers
44
44
  :param command_handlers: list of CommandHandlers for register
argenta/router/entity.py CHANGED
@@ -22,13 +22,21 @@ from argenta.router.exceptions import (
22
22
 
23
23
 
24
24
  class Router:
25
- def __init__(self, title: str | None = "Awesome title"):
25
+ def __init__(
26
+ self, title: str | None = "Awesome title", disable_redirect_stdout: bool = False
27
+ ):
26
28
  """
27
29
  Public. Directly configures and manages handlers
28
30
  :param title: the title of the router, displayed when displaying the available commands
31
+ :param disable_redirect_stdout: Disables stdout forwarding, if the argument value is True,
32
+ the StaticDividingLine will be forced to be used as a line separator for this router,
33
+ disabled forwarding is needed when there is text output in conjunction with a text input request (for example, input()),
34
+ if the argument value is True, the output of the input() prompt is intercepted and not displayed,
35
+ which is ambiguous behavior and can lead to unexpected work
29
36
  :return: None
30
37
  """
31
38
  self.title = title
39
+ self.disable_redirect_stdout = disable_redirect_stdout
32
40
 
33
41
  self._command_handlers: CommandHandlers = CommandHandlers()
34
42
  self._ignore_command_register: bool = False
@@ -39,13 +47,15 @@ class Router:
39
47
  :param command: Registered command
40
48
  :return: decorated handler as Callable
41
49
  """
42
- self._validate_command(command)
43
50
  if isinstance(command, str):
44
- command = Command(command)
51
+ redefined_command = Command(command)
52
+ else:
53
+ redefined_command = command
54
+ self._validate_command(redefined_command)
45
55
 
46
56
  def command_decorator(func):
47
57
  Router._validate_func_args(func)
48
- self._command_handlers.add_handler(CommandHandler(func, command))
58
+ self._command_handlers.add_handler(CommandHandler(func, redefined_command))
49
59
 
50
60
  def wrapper(*args, **kwargs):
51
61
  return func(*args, **kwargs)
@@ -83,9 +93,7 @@ class Router:
83
93
  response: Response = Response()
84
94
  if handle_command.get_registered_flags().get_flags():
85
95
  if input_command_flags.get_flags():
86
- response: Response = self._structuring_input_flags(
87
- handle_command, input_command_flags
88
- )
96
+ response: Response = self._structuring_input_flags( handle_command, input_command_flags )
89
97
  command_handler.handling(response)
90
98
  else:
91
99
  response.status = Status.ALL_FLAGS_VALID
@@ -117,13 +125,12 @@ class Router:
117
125
  flag_status: Literal["Undefined", "Valid", "Invalid"] = (
118
126
  handled_command.validate_input_flag(flag)
119
127
  )
120
- match flag_status:
121
- case "Valid":
122
- valid_input_flags.add_flag(flag)
123
- case "Undefined":
124
- undefined_input_flags.add_flag(flag)
125
- case "Invalid":
126
- invalid_value_input_flags.add_flag(flag)
128
+ if flag_status == "Valid":
129
+ valid_input_flags.add_flag(flag)
130
+ elif flag_status == "Undefined":
131
+ undefined_input_flags.add_flag(flag)
132
+ elif flag_status == "Invalid":
133
+ invalid_value_input_flags.add_flag(flag)
127
134
 
128
135
  if (
129
136
  not invalid_value_input_flags.get_flags()
@@ -151,25 +158,20 @@ class Router:
151
158
  )
152
159
 
153
160
  @staticmethod
154
- def _validate_command(command: Command | str) -> None:
161
+ def _validate_command(command: Command) -> None:
155
162
  """
156
163
  Private. Validates the command registered in handler
157
164
  :param command: validated command
158
165
  :return: None if command is valid else raise exception
159
166
  """
160
- match type(command).__name__:
161
- case "Command":
162
- command_name: str = command.get_trigger()
163
- if command_name.find(" ") != -1:
164
- raise TriggerContainSpacesException()
165
- flags: Flags = command.get_registered_flags()
166
- if flags:
167
- flags_name: list = [x.get_string_entity().lower() for x in flags]
168
- if len(set(flags_name)) < len(flags_name):
169
- raise RepeatedFlagNameException()
170
- case "str":
171
- if command.find(" ") != -1:
172
- raise TriggerContainSpacesException()
167
+ command_name: str = command.get_trigger()
168
+ if command_name.find(" ") != -1:
169
+ raise TriggerContainSpacesException()
170
+ flags: Flags = command.get_registered_flags()
171
+ if flags:
172
+ flags_name: list = [x.get_string_entity().lower() for x in flags]
173
+ if len(set(flags_name)) < len(flags_name):
174
+ raise RepeatedFlagNameException()
173
175
 
174
176
  @staticmethod
175
177
  def _validate_func_args(func: Callable) -> None:
@@ -191,13 +193,15 @@ class Router:
191
193
  if arg_annotation is Response:
192
194
  pass
193
195
  else:
194
- file_path: str = getsourcefile(func)
196
+ file_path: str | None = getsourcefile(func)
195
197
  source_line: int = getsourcelines(func)[1]
196
198
  fprint = Console().print
197
- fprint(f'\nFile "{file_path}", line {source_line}\n[b red]WARNING:[/b red] [i]The typehint '
199
+ fprint(
200
+ f'\nFile "{file_path}", line {source_line}\n[b red]WARNING:[/b red] [i]The typehint '
198
201
  f"of argument([green]{transferred_arg}[/green]) passed to the handler is [/i][bold blue]{Response}[/bold blue],"
199
202
  f" [i]but[/i] [bold blue]{arg_annotation}[/bold blue] [i]is specified[/i]",
200
- highlight=False)
203
+ highlight=False,
204
+ )
201
205
 
202
206
  def set_command_register_ignore(self, _: bool) -> None:
203
207
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: argenta
3
- Version: 1.0.5
3
+ Version: 1.0.7
4
4
  Summary: Python library for building modular CLI applications
5
5
  Author-email: kolo <kolo.is.main@gmail.com>
6
6
  License: MIT
@@ -73,7 +73,6 @@ if __name__ == '__main__':
73
73
  # Features in development
74
74
 
75
75
  - Full support for autocompleter on Linux
76
- - Ability to configure stdout capture when handling input by the handler
77
76
 
78
77
  ## Full [docs](https://argenta-docs.vercel.app) | MIT 2025 kolo | made by [kolo](https://t.me/kolo_id)
79
78
 
@@ -1,39 +1,39 @@
1
1
  argenta/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  argenta/app/__init__.py,sha256=I8FTXU17ajDI-hbC6Rw0LxLmvDYipdQaos3v1pmu14E,57
3
- argenta/app/defaults.py,sha256=TmpHGfEmJeefgJlgW90rfw9xTgssNANRds6JZqKdDrc,379
4
- argenta/app/models.py,sha256=8Kr2605VMa2X7S9_XvLLR1WvOh7Y9mf8VqkWgBqNgfg,19777
3
+ argenta/app/defaults.py,sha256=imtg6sOZ82xwttr7YCwBoMRFG_lhCkyk0tP63o1NSuI,381
4
+ argenta/app/models.py,sha256=y7XZ3MVw_q8wHyrLlZMhtl9LzgzzXIY_m6Ud8hsli2w,20150
5
5
  argenta/app/autocompleter/__init__.py,sha256=VT_p3QA78UnczV7pYR2NnwQ0Atd8mnDUnLazvUQNqJk,93
6
- argenta/app/autocompleter/entity.py,sha256=QgEZ2Tzfp9liWBCd-BdRpUE-ELUOxAhPpW7KBLVcPRE,3556
6
+ argenta/app/autocompleter/entity.py,sha256=55yUwlCEPPF8Z4t7y8Fl4DgLyH27qeybynXphDJ6XvM,3562
7
7
  argenta/app/dividing_line/__init__.py,sha256=jJZDDZix8XYCAUWW4FzGJH0JmJlchYcx0FPWifjgv1I,147
8
8
  argenta/app/dividing_line/models.py,sha256=syBTrzcIIt6E6RiaKC9QH3kdAuWLBDNIX0cH7Bnn0mk,2265
9
9
  argenta/app/registered_routers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- argenta/app/registered_routers/entity.py,sha256=OH7plYfjQrlyVliXE6OLVD2ftOAd5U1VO6SlyvLNikk,1078
10
+ argenta/app/registered_routers/entity.py,sha256=xTRW3R2dWnSOz8QIsiUVmG8VuMJmyOMUqHzEDDpNX-0,1085
11
11
  argenta/command/__init__.py,sha256=RvacrM84ZwBdVDy4MUwjLTyzQdDQrjjoikZxwh5ov-0,69
12
12
  argenta/command/exceptions.py,sha256=86Gs_9-NutmbSkduEMljtxQHWHhDRFcqyyOKDhQ440o,1060
13
- argenta/command/models.py,sha256=hhW1FJgRrxLg3MP1FkTqp5t1iDuhKyB4l2QCZ7dC76M,7185
14
- argenta/command/flag/__init__.py,sha256=Xjh_nR4vsHPPHFxQmc5o0673DvbnRkdr_vUaA31GeEk,384
15
- argenta/command/flag/defaults.py,sha256=1F9bEngv6tB_yn5lLQg5pxWZSuinryfGGdXnWD7EvuY,1035
16
- argenta/command/flag/models.py,sha256=KAzyoNWVOVLiIT4f8auI15D0TCHosGXHGw_xXRuEtgY,3875
13
+ argenta/command/models.py,sha256=TYmKVJUsX8vxBfCVnQw0rp7CvzStr5BrDcV0IlRyCyc,7116
14
+ argenta/command/flag/__init__.py,sha256=cXzUCEK_zGYd7d3YbymYVzfDAusrY9DMhjC48--PUdg,379
15
+ argenta/command/flag/defaults.py,sha256=dkzE750mC-w6DPIGZsdhfnmc87-y7P-FIKMT_PAcq_0,1155
16
+ argenta/command/flag/models.py,sha256=hGmgVX__ZgfNSB8KCqIT6SF-BOiZ_A0b2C031a_pSac,4158
17
17
  argenta/command/flag/flags/__init__.py,sha256=-HfdBZ3WXrjMrM8vEDWg0LLOLuQafqncrjw9KVFyqoE,294
18
18
  argenta/command/flag/flags/models.py,sha256=U4nOwCqsCOURGigTKiQx07zBUKj0EoY0fCwgTNq4GIg,2332
19
19
  argenta/metrics/__init__.py,sha256=PPLFPxhe4j7r6hP1P1pk0A_gnXgylbTaHqopky872AU,109
20
- argenta/metrics/main.py,sha256=tMMrbpUIiW4BjYLhB7yWYK4mSBdjppeZtslf4VoXPsI,514
20
+ argenta/metrics/main.py,sha256=vkvvI4xFbIcs0bNumtyiA_o3v66FF5LI38QoNnLCD6c,472
21
21
  argenta/orchestrator/__init__.py,sha256=vFtJEJTjFfoYP3DZx0gNlhoa0Tk8u-yzkGIUN3SiABA,86
22
- argenta/orchestrator/entity.py,sha256=kgTHGrbWdsTDR7aAKv2Bvm8pO7LKFv7v8Dv1LDsdrTo,1093
22
+ argenta/orchestrator/entity.py,sha256=I0HWZnpoD0Pen5azeTBh8s-CFU8vs0bTILpgRls-1hI,1098
23
23
  argenta/orchestrator/argparser/__init__.py,sha256=akbTPC5CfNrgJTVVu1A2E9KeI8KPN4JnMM8M8U21jc8,90
24
24
  argenta/orchestrator/argparser/entity.py,sha256=i3lCsCr_8JT09OosvxRuRD7KKP1MgeNFYz5kTTTqu9Q,2087
25
25
  argenta/orchestrator/argparser/arguments/__init__.py,sha256=lRsKyJeiibPYhFZoeB3BRfIYM4mlUFp6nZpy9RdbgYg,213
26
26
  argenta/orchestrator/argparser/arguments/models.py,sha256=wF4rIaEAx9Rt-c6rAeq6kZLfNPTn4v9WBNt9JHzJ0RA,1548
27
27
  argenta/response/__init__.py,sha256=u4NuwUQkWa55aX67hTQs_B_gIaZ9Dn4Fe7xhSFQ_Rpw,128
28
- argenta/response/entity.py,sha256=urzUQmZxk7BNGJj9tR9AcrTNM5dDLUiGLJDg3VdhDVk,1047
28
+ argenta/response/entity.py,sha256=vUVeiOp8BbuUW2VRtyQlFMQ_-KkQPjOgz9p7DxwyoeE,1054
29
29
  argenta/response/status.py,sha256=bWFMHvyIHpOA4LxUQFoSpld-F8gu183M9nY-zN-MiZM,244
30
30
  argenta/router/__init__.py,sha256=rvqAx80IXHFdVw7cWBRGaTtb94a4OQQEsMJ5f7YA1gU,68
31
31
  argenta/router/defaults.py,sha256=vvkwFYCQdwjtMntfyrJuisxFX8XxeyhDMA-RwteHZGg,87
32
- argenta/router/entity.py,sha256=7vRhw8_U-gKb2KoKXBCYr8q0inuDQsGrxV49abt6bwU,9607
32
+ argenta/router/entity.py,sha256=5eIn6OwUM4oNdFOtmC_jxDyxD54U3wl8c7W2AU2hyqE,10071
33
33
  argenta/router/exceptions.py,sha256=5k0mTHYYItWHzGC0NU5oHHYrHxU0M5fEbO5wne_wFg8,860
34
34
  argenta/router/command_handler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
- argenta/router/command_handler/entity.py,sha256=xmHgbXBvD_-JMLpUPc5w3VVe-upTJ-y4lR13rUiiygo,2387
36
- argenta-1.0.5.dist-info/METADATA,sha256=4achR5RDIS460uWEATjty-kIc7Q6OVqLvspnCwVMaTU,1649
37
- argenta-1.0.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
38
- argenta-1.0.5.dist-info/licenses/LICENSE,sha256=zmqoGh2n5rReBv4s8wPxF_gZEZDgauJYSPMuPczgOiU,1082
39
- argenta-1.0.5.dist-info/RECORD,,
35
+ argenta/router/command_handler/entity.py,sha256=ascEf3AzYcWh-G5cml08WOoRr2q9QkfLP2IaKC1iKWM,2394
36
+ argenta-1.0.7.dist-info/METADATA,sha256=4uN_xlRCoJWKU0TY48l78TD6-jllclnWonMqknFX6-8,1576
37
+ argenta-1.0.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
38
+ argenta-1.0.7.dist-info/licenses/LICENSE,sha256=zmqoGh2n5rReBv4s8wPxF_gZEZDgauJYSPMuPczgOiU,1082
39
+ argenta-1.0.7.dist-info/RECORD,,