argenta 1.1.1rc0__py3-none-any.whl → 1.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. argenta/__init__.py +6 -0
  2. argenta/app/__init__.py +10 -1
  3. argenta/app/autocompleter/entity.py +18 -19
  4. argenta/app/defaults.py +0 -1
  5. argenta/app/dividing_line/models.py +5 -5
  6. argenta/app/models.py +226 -140
  7. argenta/app/protocols.py +22 -0
  8. argenta/app/registered_routers/entity.py +7 -14
  9. argenta/command/__init__.py +11 -2
  10. argenta/command/exceptions.py +20 -13
  11. argenta/command/flag/__init__.py +5 -11
  12. argenta/command/flag/defaults.py +19 -24
  13. argenta/command/flag/flags/__init__.py +2 -8
  14. argenta/command/flag/flags/models.py +65 -49
  15. argenta/command/flag/models.py +78 -93
  16. argenta/command/models.py +100 -144
  17. argenta/di/__init__.py +2 -0
  18. argenta/di/integration.py +45 -0
  19. argenta/di/providers.py +14 -0
  20. argenta/metrics/main.py +2 -2
  21. argenta/orchestrator/__init__.py +2 -2
  22. argenta/orchestrator/argparser/__init__.py +6 -1
  23. argenta/orchestrator/argparser/arguments/__init__.py +3 -3
  24. argenta/orchestrator/argparser/arguments/models.py +61 -35
  25. argenta/orchestrator/argparser/entity.py +56 -37
  26. argenta/orchestrator/entity.py +20 -18
  27. argenta/py.typed +0 -0
  28. argenta/response/__init__.py +2 -2
  29. argenta/response/entity.py +17 -18
  30. argenta/response/status.py +12 -1
  31. argenta/router/__init__.py +2 -2
  32. argenta/router/command_handler/entity.py +9 -27
  33. argenta/router/entity.py +133 -160
  34. argenta/router/exceptions.py +9 -12
  35. {argenta-1.1.1rc0.dist-info → argenta-1.1.2.dist-info}/METADATA +12 -5
  36. argenta-1.1.2.dist-info/RECORD +44 -0
  37. argenta-1.1.1rc0.dist-info/RECORD +0 -39
  38. {argenta-1.1.1rc0.dist-info → argenta-1.1.2.dist-info}/WHEEL +0 -0
  39. {argenta-1.1.1rc0.dist-info → argenta-1.1.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,35 +1,37 @@
1
- from argparse import Namespace
2
-
3
1
  from argenta.app import App
2
+ from argenta.response import Response
3
+
4
4
  from argenta.orchestrator.argparser import ArgParser
5
+ from argenta.di.integration import setup_dishka
6
+ from argenta.di.providers import SystemProvider
7
+
8
+ from dishka import Provider, make_container
9
+
10
+
11
+ DEFAULT_ARGPARSER: ArgParser = ArgParser(processed_args=[])
5
12
 
6
13
 
7
14
  class Orchestrator:
8
- def __init__(self, arg_parser: ArgParser | None = None):
15
+ def __init__(self, arg_parser: ArgParser = DEFAULT_ARGPARSER,
16
+ custom_providers: list[Provider] = [],
17
+ auto_inject_handlers: bool = True):
9
18
  """
10
19
  Public. An orchestrator and configurator that defines the behavior of an integrated system, one level higher than the App
11
20
  :param arg_parser: Cmd argument parser and configurator at startup
12
21
  :return: None
13
22
  """
14
- self.arg_parser: ArgParser | None = arg_parser
15
- if arg_parser:
16
- self.arg_parser.register_args()
23
+ self._arg_parser: ArgParser = arg_parser
24
+ self._custom_providers: list[Provider] = custom_providers
25
+ self._auto_inject_handlers: bool = auto_inject_handlers
17
26
 
18
- @staticmethod
19
- def start_polling(app: App) -> None:
27
+ def start_polling(self, app: App) -> None:
20
28
  """
21
29
  Public. Starting the user input processing cycle
22
30
  :param app: a running application
23
31
  :return: None
24
32
  """
25
- app.run_polling()
33
+ container = make_container(SystemProvider(self._arg_parser), *self._custom_providers)
34
+ Response.patch_by_container(container)
35
+ setup_dishka(app, auto_inject=self._auto_inject_handlers)
26
36
 
27
- def get_input_args(self) -> Namespace | None:
28
- """
29
- Public. Returns the arguments parsed
30
- :return: None
31
- """
32
- if self.arg_parser:
33
- return self.arg_parser.entity.parse_args()
34
- else:
35
- return None
37
+ app.run_polling()
argenta/py.typed ADDED
File without changes
@@ -1,5 +1,5 @@
1
- __all__ = ["Response", "Status"]
1
+ __all__ = ["Response", "ResponseStatus"]
2
2
 
3
3
 
4
4
  from argenta.response.entity import Response
5
- from argenta.response.status import Status
5
+ from argenta.response.status import ResponseStatus
@@ -1,29 +1,28 @@
1
- from argenta.response.status import Status
2
- from argenta.command.flag.flags import (
3
- ValidInputFlags,
4
- UndefinedInputFlags,
5
- InvalidValueInputFlags,
6
- )
1
+ from dishka import Container
2
+
3
+ from argenta.command.flag.flags.models import InputFlags
4
+ from argenta.response.status import ResponseStatus
5
+
6
+
7
+ EMPTY_INPUT_FLAGS: InputFlags = InputFlags()
7
8
 
8
9
 
9
10
  class Response:
10
- __slots__ = ("status", "valid_flags", "undefined_flags", "invalid_value_flags")
11
+ _dishka_container: Container
11
12
 
12
13
  def __init__(
13
14
  self,
14
- status: Status | None = None,
15
- valid_flags: ValidInputFlags = ValidInputFlags(),
16
- undefined_flags: UndefinedInputFlags = UndefinedInputFlags(),
17
- invalid_value_flags: InvalidValueInputFlags = InvalidValueInputFlags(),
15
+ status: ResponseStatus,
16
+ input_flags: InputFlags = EMPTY_INPUT_FLAGS,
18
17
  ):
19
18
  """
20
19
  Public. The entity of the user input sent to the handler
21
20
  :param status: the status of the response
22
- :param valid_flags: valid input flags
23
- :param undefined_flags: undefined input flags
24
- :param invalid_value_flags: input flags with invalid values
21
+ :param input_flags: all input flags
25
22
  """
26
- self.status = status
27
- self.valid_flags = valid_flags
28
- self.undefined_flags = undefined_flags
29
- self.invalid_value_flags = invalid_value_flags
23
+ self.status: ResponseStatus = status
24
+ self.input_flags: InputFlags = input_flags
25
+
26
+ @classmethod
27
+ def patch_by_container(cls, container: Container) -> None:
28
+ cls._dishka_container = container
@@ -1,8 +1,19 @@
1
1
  from enum import Enum
2
2
 
3
3
 
4
- class Status(Enum):
4
+ class ResponseStatus(Enum):
5
5
  ALL_FLAGS_VALID = "ALL_FLAGS_VALID"
6
6
  UNDEFINED_FLAGS = "UNDEFINED_FLAGS"
7
7
  INVALID_VALUE_FLAGS = "INVALID_VALUE_FLAGS"
8
8
  UNDEFINED_AND_INVALID_FLAGS = "UNDEFINED_AND_INVALID_FLAGS"
9
+
10
+ @classmethod
11
+ def from_flags(cls, *, has_invalid_value_flags: bool, has_undefined_flags: bool) -> 'ResponseStatus':
12
+ key = (has_invalid_value_flags, has_undefined_flags)
13
+ status_map: dict[tuple[bool, bool], ResponseStatus] = {
14
+ (True, True): cls.UNDEFINED_AND_INVALID_FLAGS,
15
+ (True, False): cls.INVALID_VALUE_FLAGS,
16
+ (False, True): cls.UNDEFINED_FLAGS,
17
+ (False, False): cls.ALL_FLAGS_VALID,
18
+ }
19
+ return status_map[key]
@@ -1,4 +1,4 @@
1
- __all__ = ["Router"]
1
+ from argenta.router.entity import Router
2
2
 
3
3
 
4
- from argenta.router.entity import Router
4
+ __all__ = ["Router"]
@@ -1,18 +1,19 @@
1
- from typing import Callable, Iterator
1
+ from collections.abc import Iterator
2
+ from typing import Callable
2
3
 
3
4
  from argenta.command import Command
4
5
  from argenta.response import Response
5
6
 
6
7
 
7
8
  class CommandHandler:
8
- def __init__(self, handler: Callable[[Response], None], handled_command: Command):
9
+ def __init__(self, handler_as_func: Callable[..., None], handled_command: Command):
9
10
  """
10
11
  Private. Entity of the model linking the handler and the command being processed
11
12
  :param handler: the handler being called
12
13
  :param handled_command: the command being processed
13
14
  """
14
- self._handler = handler
15
- self._handled_command = handled_command
15
+ self.handler_as_func: Callable[..., None] = handler_as_func
16
+ self.handled_command: Command = handled_command
16
17
 
17
18
  def handling(self, response: Response) -> None:
18
19
  """
@@ -20,21 +21,7 @@ class CommandHandler:
20
21
  :param response: the entity of response: various groups of flags and status of response
21
22
  :return: None
22
23
  """
23
- self._handler(response)
24
-
25
- def get_handler(self) -> Callable[[Response], None]:
26
- """
27
- Private. Returns the handler being called
28
- :return: the handler being called as Callable[[Response], None]
29
- """
30
- return self._handler
31
-
32
- def get_handled_command(self) -> Command:
33
- """
34
- Private. Returns the command being processed
35
- :return: the command being processed as Command
36
- """
37
- return self._handled_command
24
+ self.handler_as_func(response)
38
25
 
39
26
 
40
27
  class CommandHandlers:
@@ -43,14 +30,9 @@ class CommandHandlers:
43
30
  Private. The model that unites all CommandHandler of the routers
44
31
  :param command_handlers: list of CommandHandlers for register
45
32
  """
46
- self.command_handlers = command_handlers if command_handlers else []
47
-
48
- def get_handlers(self) -> list[CommandHandler]:
49
- """
50
- Private. Returns the list of CommandHandlers
51
- :return: the list of CommandHandlers as list[CommandHandler]
52
- """
53
- return self.command_handlers
33
+ self.command_handlers: list[CommandHandler] = (
34
+ command_handlers if command_handlers else []
35
+ )
54
36
 
55
37
  def add_handler(self, command_handler: CommandHandler) -> None:
56
38
  """
argenta/router/entity.py CHANGED
@@ -1,29 +1,28 @@
1
- from typing import Callable, Literal, Type
1
+ from typing import Callable, TypeAlias
2
2
  from inspect import getfullargspec, get_annotations, getsourcefile, getsourcelines
3
3
  from rich.console import Console
4
4
 
5
- from argenta.command import Command
6
- from argenta.command.models import InputCommand
7
- from argenta.response import Response, Status
5
+ from argenta.command import Command, InputCommand
6
+ from argenta.command.flag import ValidationStatus
7
+ from argenta.response import Response, ResponseStatus
8
8
  from argenta.router.command_handler.entity import CommandHandlers, CommandHandler
9
- from argenta.command.flag.flags import (
10
- Flags,
11
- InputFlags,
12
- UndefinedInputFlags,
13
- ValidInputFlags,
14
- InvalidValueInputFlags,
15
- )
9
+ from argenta.command.flag.flags import Flags, InputFlags
16
10
  from argenta.router.exceptions import (
17
11
  RepeatedFlagNameException,
18
- TooManyTransferredArgsException,
19
12
  RequiredArgumentNotPassedException,
20
13
  TriggerContainSpacesException,
21
14
  )
22
15
 
23
16
 
17
+ HandlerFunc: TypeAlias = Callable[..., None]
18
+
19
+
24
20
  class Router:
25
21
  def __init__(
26
- self, title: str | None = "Awesome title", disable_redirect_stdout: bool = False
22
+ self,
23
+ *,
24
+ title: str | None = "Default title",
25
+ disable_redirect_stdout: bool = False,
27
26
  ):
28
27
  """
29
28
  Public. Directly configures and manages handlers
@@ -35,13 +34,13 @@ class Router:
35
34
  which is ambiguous behavior and can lead to unexpected work
36
35
  :return: None
37
36
  """
38
- self.title = title
39
- self.disable_redirect_stdout = disable_redirect_stdout
37
+ self.title: str | None = title
38
+ self.disable_redirect_stdout: bool = disable_redirect_stdout
40
39
 
41
- self._command_handlers: CommandHandlers = CommandHandlers()
42
- self._ignore_command_register: bool = False
40
+ self.command_handlers: CommandHandlers = CommandHandlers()
41
+ self.command_register_ignore: bool = False
43
42
 
44
- def command(self, command: Command | str) -> Callable:
43
+ def command(self, command: Command | str) -> Callable[[HandlerFunc], HandlerFunc]:
45
44
  """
46
45
  Public. Registers handler
47
46
  :param command: Registered command
@@ -51,18 +50,15 @@ class Router:
51
50
  redefined_command = Command(command)
52
51
  else:
53
52
  redefined_command = command
54
- self._validate_command(redefined_command)
55
-
56
- def command_decorator(func):
57
- Router._validate_func_args(func)
58
- self._command_handlers.add_handler(CommandHandler(func, redefined_command))
59
53
 
60
- def wrapper(*args, **kwargs):
61
- return func(*args, **kwargs)
54
+ _validate_command(redefined_command)
62
55
 
63
- return wrapper
56
+ def decorator(func: HandlerFunc) -> HandlerFunc:
57
+ _validate_func_args(func)
58
+ self.command_handlers.add_handler(CommandHandler(func, redefined_command))
59
+ return func
64
60
 
65
- return command_decorator
61
+ return decorator
66
62
 
67
63
  def finds_appropriate_handler(self, input_command: InputCommand) -> None:
68
64
  """
@@ -70,14 +66,14 @@ class Router:
70
66
  :param input_command: input command as InputCommand
71
67
  :return: None
72
68
  """
73
- input_command_name: str = input_command.get_trigger()
74
- input_command_flags: InputFlags = input_command.get_input_flags()
69
+ input_command_name: str = input_command.trigger
70
+ input_command_flags: InputFlags = input_command.input_flags
75
71
 
76
- for command_handler in self._command_handlers:
77
- handle_command = command_handler.get_handled_command()
78
- if input_command_name.lower() == handle_command.get_trigger().lower():
72
+ for command_handler in self.command_handlers:
73
+ handle_command = command_handler.handled_command
74
+ if input_command_name.lower() == handle_command.trigger.lower():
79
75
  self.process_input_command(input_command_flags, command_handler)
80
- if input_command_name.lower() in handle_command.get_aliases():
76
+ if input_command_name.lower() in handle_command.aliases:
81
77
  self.process_input_command(input_command_flags, command_handler)
82
78
 
83
79
  def process_input_command(
@@ -89,152 +85,129 @@ class Router:
89
85
  :param command_handler: command handler for input command as CommandHandler
90
86
  :return: None
91
87
  """
92
- handle_command = command_handler.get_handled_command()
93
- response: Response = Response()
94
- if handle_command.get_registered_flags().get_flags():
95
- if input_command_flags.get_flags():
96
- response: Response = self._structuring_input_flags( handle_command, input_command_flags )
88
+ handle_command = command_handler.handled_command
89
+ if handle_command.registered_flags.flags:
90
+ if input_command_flags.flags:
91
+ response: Response = _structuring_input_flags(
92
+ handle_command, input_command_flags
93
+ )
97
94
  command_handler.handling(response)
98
95
  else:
99
- response.status = Status.ALL_FLAGS_VALID
96
+ response = Response(ResponseStatus.ALL_FLAGS_VALID)
100
97
  command_handler.handling(response)
101
98
  else:
102
- if input_command_flags.get_flags():
103
- response.status = Status.UNDEFINED_FLAGS
104
- response.undefined_flags = UndefinedInputFlags()
105
- response.undefined_flags.add_flags(input_command_flags.get_flags())
99
+ if input_command_flags.flags:
100
+ undefined_flags = InputFlags()
101
+ for input_flag in input_command_flags:
102
+ input_flag.status = ValidationStatus.UNDEFINED
103
+ undefined_flags.add_flag(input_flag)
104
+ response = Response(
105
+ ResponseStatus.UNDEFINED_FLAGS, input_flags=undefined_flags
106
+ )
106
107
  command_handler.handling(response)
107
108
  else:
108
- response.status = Status.ALL_FLAGS_VALID
109
+ response = Response(ResponseStatus.ALL_FLAGS_VALID)
109
110
  command_handler.handling(response)
110
111
 
111
- @staticmethod
112
- def _structuring_input_flags(
113
- handled_command: Command, input_flags: InputFlags
114
- ) -> Response:
115
- """
116
- Private. Validates flags of input command
117
- :param handled_command: entity of the handled command
118
- :param input_flags:
119
- :return: entity of response as Response
120
- """
121
- valid_input_flags: ValidInputFlags = ValidInputFlags()
122
- invalid_value_input_flags: InvalidValueInputFlags = InvalidValueInputFlags()
123
- undefined_input_flags: UndefinedInputFlags = UndefinedInputFlags()
124
- for flag in input_flags:
125
- flag_status: Literal["Undefined", "Valid", "Invalid"] = (
126
- handled_command.validate_input_flag(flag)
127
- )
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)
134
-
135
- if (
136
- not invalid_value_input_flags.get_flags()
137
- and not undefined_input_flags.get_flags()
138
- ):
139
- status = Status.ALL_FLAGS_VALID
140
- elif (
141
- invalid_value_input_flags.get_flags()
142
- and not undefined_input_flags.get_flags()
143
- ):
144
- status = Status.INVALID_VALUE_FLAGS
145
- elif (
146
- not invalid_value_input_flags.get_flags()
147
- and undefined_input_flags.get_flags()
148
- ):
149
- status = Status.UNDEFINED_FLAGS
150
- else:
151
- status = Status.UNDEFINED_AND_INVALID_FLAGS
152
-
153
- return Response(
154
- invalid_value_flags=invalid_value_input_flags,
155
- valid_flags=valid_input_flags,
156
- status=status,
157
- undefined_flags=undefined_input_flags,
158
- )
159
-
160
- @staticmethod
161
- def _validate_command(command: Command) -> None:
162
- """
163
- Private. Validates the command registered in handler
164
- :param command: validated command
165
- :return: None if command is valid else raise exception
166
- """
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()
175
-
176
- @staticmethod
177
- def _validate_func_args(func: Callable) -> None:
178
- """
179
- Private. Validates the arguments of the handler
180
- :param func: entity of the handler func
181
- :return: None if func is valid else raise exception
182
- """
183
- transferred_args = getfullargspec(func).args
184
- if len(transferred_args) > 1:
185
- raise TooManyTransferredArgsException()
186
- elif len(transferred_args) == 0:
187
- raise RequiredArgumentNotPassedException()
188
-
189
- transferred_arg: str = transferred_args[0]
190
- func_annotations: dict[str, Type] = get_annotations(func)
191
-
192
- if arg_annotation := func_annotations.get(transferred_arg):
193
- if arg_annotation is Response:
194
- pass
195
- else:
196
- file_path: str | None = getsourcefile(func)
197
- source_line: int = getsourcelines(func)[1]
198
- fprint = Console().print
199
- fprint(
200
- f'\nFile "{file_path}", line {source_line}\n[b red]WARNING:[/b red] [i]The typehint '
201
- f"of argument([green]{transferred_arg}[/green]) passed to the handler is [/i][bold blue]{Response}[/bold blue],"
202
- f" [i]but[/i] [bold blue]{arg_annotation}[/bold blue] [i]is specified[/i]",
203
- highlight=False,
204
- )
205
-
206
- def set_command_register_ignore(self, _: bool) -> None:
207
- """
208
- Private. Sets the router behavior on the input commands register
209
- :param _: is command register ignore
210
- :return: None
211
- """
212
- self._ignore_command_register = _
213
-
214
- def get_triggers(self) -> list[str]:
112
+ @property
113
+ def triggers(self) -> list[str]:
215
114
  """
216
115
  Public. Gets registered triggers
217
116
  :return: registered in router triggers as list[str]
218
117
  """
219
118
  all_triggers: list[str] = []
220
- for command_handler in self._command_handlers:
221
- all_triggers.append(command_handler.get_handled_command().get_trigger())
119
+ for command_handler in self.command_handlers:
120
+ all_triggers.append(command_handler.handled_command.trigger)
222
121
  return all_triggers
223
122
 
224
- def get_aliases(self) -> list[str]:
123
+ @property
124
+ def aliases(self) -> list[str]:
225
125
  """
226
126
  Public. Gets registered aliases
227
127
  :return: registered in router aliases as list[str]
228
128
  """
229
129
  all_aliases: list[str] = []
230
- for command_handler in self._command_handlers:
231
- if command_handler.get_handled_command().get_aliases():
232
- all_aliases.extend(command_handler.get_handled_command().get_aliases())
130
+ for command_handler in self.command_handlers:
131
+ if command_handler.handled_command.aliases:
132
+ all_aliases.extend(command_handler.handled_command.aliases)
233
133
  return all_aliases
234
134
 
235
- def get_command_handlers(self) -> CommandHandlers:
236
- """
237
- Private. Gets registered command handlers
238
- :return: registered command handlers as CommandHandlers
239
- """
240
- return self._command_handlers
135
+
136
+ class CommandDecorator:
137
+ def __init__(self, router_instance: Router, command: Command):
138
+ self.router: Router = router_instance
139
+ self.command: Command = command
140
+
141
+ def __call__(self, handler_func: Callable[..., None]) -> Callable[..., None]:
142
+ _validate_func_args(handler_func)
143
+ self.router.command_handlers.add_handler(
144
+ CommandHandler(handler_func, self.command)
145
+ )
146
+ return handler_func
147
+
148
+
149
+ def _structuring_input_flags(
150
+ handled_command: Command, input_flags: InputFlags
151
+ ) -> Response:
152
+ """
153
+ Private. Validates flags of input command
154
+ :param handled_command: entity of the handled command
155
+ :param input_flags:
156
+ :return: entity of response as Response
157
+ """
158
+ invalid_value_flags, undefined_flags = False, False
159
+
160
+ for flag in input_flags:
161
+ flag_status: ValidationStatus = handled_command.validate_input_flag(flag)
162
+ flag.status = flag_status
163
+ if flag_status == ValidationStatus.INVALID:
164
+ invalid_value_flags = True
165
+ elif flag_status == ValidationStatus.UNDEFINED:
166
+ undefined_flags = True
167
+
168
+ status = ResponseStatus.from_flags(
169
+ has_invalid_value_flags=invalid_value_flags, has_undefined_flags=undefined_flags
170
+ )
171
+
172
+ return Response(status=status, input_flags=input_flags)
173
+
174
+
175
+ def _validate_func_args(func: Callable[..., None]) -> None:
176
+ """
177
+ Private. Validates the arguments of the handler
178
+ :param func: entity of the handler func
179
+ :return: None if func is valid else raise exception
180
+ """
181
+ transferred_args = getfullargspec(func).args
182
+ if len(transferred_args) == 0:
183
+ raise RequiredArgumentNotPassedException()
184
+
185
+ response_arg: str = transferred_args[0]
186
+ func_annotations: dict[str, None] = get_annotations(func)
187
+
188
+ response_arg_annotation = func_annotations.get(response_arg)
189
+
190
+ if response_arg_annotation is not None:
191
+ if response_arg_annotation is not Response:
192
+ source_line: int = getsourcelines(func)[1]
193
+ Console().print(
194
+ f'\nFile "{getsourcefile(func)}", line {source_line}\n[b red]WARNING:[/b red] [i]The typehint '
195
+ + f"of argument([green]{response_arg}[/green]) passed to the handler must be [/i][bold blue]{Response}[/bold blue],"
196
+ + f" [i]but[/i] [bold blue]{response_arg_annotation}[/bold blue] [i]is specified[/i]",
197
+ highlight=False,
198
+ )
199
+
200
+
201
+ def _validate_command(command: Command) -> None:
202
+ """
203
+ Private. Validates the command registered in handler
204
+ :param command: validated command
205
+ :return: None if command is valid else raise exception
206
+ """
207
+ command_name: str = command.trigger
208
+ if command_name.find(" ") != -1:
209
+ raise TriggerContainSpacesException()
210
+ flags: Flags = command.registered_flags
211
+ flags_name: list[str] = [flag.string_entity.lower() for flag in flags]
212
+ if len(set(flags_name)) < len(flags_name):
213
+ raise RepeatedFlagNameException()
@@ -1,27 +1,23 @@
1
+ from typing import override
2
+
3
+
1
4
  class RepeatedFlagNameException(Exception):
2
5
  """
3
6
  Private. Raised when a repeated flag name is registered
4
7
  """
5
8
 
6
- def __str__(self):
9
+ @override
10
+ def __str__(self) -> str:
7
11
  return "Repeated registered flag names in register command"
8
12
 
9
13
 
10
- class TooManyTransferredArgsException(Exception):
11
- """
12
- Private. Raised when too many arguments are passed
13
- """
14
-
15
- def __str__(self):
16
- return "Too many transferred arguments"
17
-
18
-
19
14
  class RequiredArgumentNotPassedException(Exception):
20
15
  """
21
16
  Private. Raised when a required argument is not passed
22
17
  """
23
18
 
24
- def __str__(self):
19
+ @override
20
+ def __str__(self) -> str:
25
21
  return "Required argument not passed"
26
22
 
27
23
 
@@ -30,5 +26,6 @@ class TriggerContainSpacesException(Exception):
30
26
  Private. Raised when there is a space in the trigger being registered
31
27
  """
32
28
 
33
- def __str__(self):
29
+ @override
30
+ def __str__(self) -> str:
34
31
  return "Command trigger cannot contain spaces"
@@ -1,13 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: argenta
3
- Version: 1.1.1rc0
3
+ Version: 1.1.2
4
4
  Summary: Python library for building modular CLI applications
5
5
  Author-email: kolo <kolo.is.main@gmail.com>
6
6
  License: MIT
7
7
  License-File: LICENSE
8
- Requires-Python: >=3.8
8
+ Requires-Python: >=3.11
9
9
  Requires-Dist: art<7.0,>=6.4
10
- Requires-Dist: pyreadline3>=3.5.4
10
+ Requires-Dist: dishka>=1.7.2
11
+ Requires-Dist: pyreadline3>=3.5.4; sys_platform == 'win32'
11
12
  Requires-Dist: rich<15.0.0,>=14.0.0
12
13
  Description-Content-Type: text/markdown
13
14
 
@@ -15,9 +16,15 @@ Description-Content-Type: text/markdown
15
16
 
16
17
  ### Library for creating modular CLI applications
17
18
 
18
- #### RU - [README.ru.md](https://github.com/koloideal/Argenta/blob/kolo/README.ru.md) • DE - [README.de.md](https://github.com/koloideal/Argenta/blob/kolo/README.de.md)
19
+ #### RU - [README.ru.md](https://github.com/koloideal/Argenta/blob/main/README.ru.md) • DE - [README.de.md](https://github.com/koloideal/Argenta/blob/main/README.de.md)
19
20
 
20
- ![preview](https://github.com/koloideal/Argenta/blob/kolo/imgs/mock_app_preview4.png?raw=True)
21
+ ---
22
+
23
+ Argenta allows you to encapsulate CLI functionality in isolated, abstracted environments. Eg: you are creating a utility similar to the Metasploit Framework, where the user first logs into a specific scope (for example, selects a module to scan), and then gets access to a set of commands specific only to that context. Argenta provides a simple and concise way to build such an architecture.
24
+
25
+ ---
26
+
27
+ ![preview](https://github.com/koloideal/Argenta/blob/main/imgs/mock_app_preview4.png?raw=True)
21
28
 
22
29
  ---
23
30