argenta 0.1.2__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: argenta
3
- Version: 0.1.2
3
+ Version: 0.2.0
4
4
  Summary: python library for creating cli apps
5
5
  License: MIT
6
6
  Author: kolo
@@ -0,0 +1,200 @@
1
+ from typing import Callable
2
+ from ..router.entity import Router
3
+ from .exceptions import (InvalidRouterInstanceException,
4
+ InvalidDescriptionMessagePatternException,
5
+ OnlyOneMainRouterIsAllowedException,
6
+ MissingMainRouterException,
7
+ MissingHandlersForUnknownCommandsOnMainRouterException,
8
+ HandlerForUnknownCommandsCanOnlyBeDeclaredForMainRouterException,
9
+ NoRegisteredRoutersException,
10
+ NoRegisteredHandlersException,
11
+ RepeatedCommandInDifferentRoutersException)
12
+
13
+
14
+ class App:
15
+ def __init__(self,
16
+ prompt: str = 'Enter a command',
17
+ exit_command: str = 'q',
18
+ ignore_exit_command_register: bool = True,
19
+ initial_greeting: str = '\nHello, I am Argenta\n',
20
+ farewell_message: str = '\nGoodBye\n',
21
+ line_separate: str = '',
22
+ command_group_description_separate: str = '',
23
+ ignore_command_register: bool = False,
24
+ print_func: Callable[[str], None] = print) -> None:
25
+ self.prompt = prompt
26
+ self.print_func = print_func
27
+ self.exit_command = exit_command
28
+ self.ignore_exit_command_register = ignore_exit_command_register
29
+ self.farewell_message = farewell_message
30
+ self.initial_greeting = initial_greeting
31
+ self.line_separate = line_separate
32
+ self.command_group_description_separate = command_group_description_separate
33
+ self.ignore_command_register = ignore_command_register
34
+
35
+ self._routers: list[Router] = []
36
+ self._registered_router_entities: list[dict[str, str | list[dict[str, Callable[[], None] | str]] | Router]] = []
37
+ self._app_main_router: Router | None = None
38
+ self._description_message_pattern: str = '[{command}] *=*=* {description}'
39
+
40
+
41
+ def start_polling(self) -> None:
42
+ self._validate_number_of_routers()
43
+ self._validate_included_routers()
44
+ self._validate_main_router()
45
+ self._validate_all_router_commands()
46
+
47
+ self.print_func(self.initial_greeting)
48
+
49
+ while True:
50
+ self._print_command_group_description()
51
+ self.print_func(self.prompt)
52
+
53
+ command: str = input()
54
+
55
+ self._checking_command_for_exit_command(command)
56
+ self.print_func(self.line_separate)
57
+
58
+ is_unknown_command: bool = self._check_is_command_unknown(command)
59
+ if is_unknown_command:
60
+ continue
61
+
62
+ for router in self._routers:
63
+ router.input_command_handler(command)
64
+
65
+ self.print_func(self.line_separate)
66
+ self.print_func(self.command_group_description_separate)
67
+
68
+
69
+ def set_initial_greeting(self, greeting: str) -> None:
70
+ self.initial_greeting: str = greeting
71
+
72
+
73
+ def set_farewell_message(self, message: str) -> None:
74
+ self.farewell_message: str = message
75
+
76
+
77
+ def set_description_message_pattern(self, pattern: str) -> None:
78
+ try:
79
+ pattern.format(command='command',
80
+ description='description')
81
+ except KeyError:
82
+ raise InvalidDescriptionMessagePatternException(pattern)
83
+ self._description_message_pattern: str = pattern
84
+
85
+
86
+ def get_main_router(self) -> Router:
87
+ return self._app_main_router
88
+
89
+
90
+ def get_all_app_commands(self) -> list[str]:
91
+ all_commands: list[str] = []
92
+ for router in self._routers:
93
+ all_commands.extend(router.get_all_commands())
94
+
95
+ return all_commands
96
+
97
+
98
+ def _validate_number_of_routers(self) -> None:
99
+ if not self._routers:
100
+ raise NoRegisteredRoutersException()
101
+
102
+
103
+ def _validate_included_routers(self) -> None:
104
+ for router in self._routers:
105
+ if not router.get_command_entities():
106
+ raise NoRegisteredHandlersException(router.get_name())
107
+
108
+
109
+ def _validate_main_router(self):
110
+ if not self._app_main_router:
111
+ if len(self._routers) > 1:
112
+ raise MissingMainRouterException()
113
+ else:
114
+ router = self._routers[0]
115
+ router.set_router_as_main()
116
+ self._app_main_router = router
117
+
118
+ if not self._app_main_router.unknown_command_func:
119
+ raise MissingHandlersForUnknownCommandsOnMainRouterException()
120
+
121
+ for router in self._routers:
122
+ if router.unknown_command_func and self._app_main_router is not router:
123
+ raise HandlerForUnknownCommandsCanOnlyBeDeclaredForMainRouterException()
124
+
125
+
126
+ def _validate_all_router_commands(self) -> None:
127
+ for idx in range(len(self._registered_router_entities)):
128
+ current_router: Router = self._registered_router_entities[idx]['entity']
129
+ routers_without_current_router = self._registered_router_entities.copy()
130
+ routers_without_current_router.pop(idx)
131
+
132
+ current_router_all_commands: list[str] = current_router.get_all_commands()
133
+
134
+ for router_entity in routers_without_current_router:
135
+ if len(set(current_router_all_commands).intersection(set(router_entity['entity'].get_all_commands()))) > 0:
136
+ raise RepeatedCommandInDifferentRoutersException()
137
+ if self.ignore_command_register:
138
+ if len(set([x.lower() for x in current_router_all_commands]).intersection(set([x.lower() for x in router_entity['entity'].get_all_commands()]))) > 0:
139
+ raise RepeatedCommandInDifferentRoutersException()
140
+
141
+
142
+ def _checking_command_for_exit_command(self, command: str):
143
+ if command.lower() == self.exit_command.lower():
144
+ if self.ignore_exit_command_register:
145
+ self.print_func(self.farewell_message)
146
+ exit(0)
147
+ else:
148
+ if command == self.exit_command:
149
+ self.print_func(self.farewell_message)
150
+ exit(0)
151
+
152
+
153
+ def _check_is_command_unknown(self, command: str):
154
+ registered_router_entities: list[dict[str, str | list[dict[str, Callable[[], None] | str]] | Router]] = self._registered_router_entities
155
+ for router_entity in registered_router_entities:
156
+ for command_entity in router_entity['commands']:
157
+ if command_entity['command'].lower() == command.lower():
158
+ if self.ignore_command_register:
159
+ return False
160
+ else:
161
+ if command_entity['command'] == command:
162
+ return False
163
+ self._app_main_router.unknown_command_handler(command)
164
+ self.print_func(self.line_separate)
165
+ self.print_func(self.command_group_description_separate)
166
+ return True
167
+
168
+
169
+ def _print_command_group_description(self):
170
+ for router_entity in self._registered_router_entities:
171
+ self.print_func(router_entity['title'])
172
+ for command_entity in router_entity['commands']:
173
+ self.print_func(self._description_message_pattern.format(
174
+ command=command_entity['command'],
175
+ description=command_entity['description']
176
+ )
177
+ )
178
+ self.print_func(self.command_group_description_separate)
179
+
180
+
181
+ def include_router(self, router: Router, is_main: True | False = False) -> None:
182
+ if not isinstance(router, Router):
183
+ raise InvalidRouterInstanceException()
184
+
185
+ if is_main:
186
+ if not self._app_main_router:
187
+ self._app_main_router = router
188
+ router.set_router_as_main()
189
+ else:
190
+ raise OnlyOneMainRouterIsAllowedException(self._app_main_router.get_name())
191
+
192
+ router.set_ignore_command_register(self.ignore_command_register)
193
+ self._routers.append(router)
194
+
195
+ command_entities: list[dict[str, Callable[[], None] | str]] = router.get_command_entities()
196
+ self._registered_router_entities.append({'name': router.get_name(),
197
+ 'title': router.get_title(),
198
+ 'entity': router,
199
+ 'commands': command_entities})
200
+
@@ -37,3 +37,20 @@ class MissingHandlersForUnknownCommandsOnMainRouterException(Exception):
37
37
  class HandlerForUnknownCommandsCanOnlyBeDeclaredForMainRouterException(Exception):
38
38
  def __str__(self):
39
39
  return '\nThe handler for unknown commands can only be declared for the main router'
40
+
41
+
42
+ class NoRegisteredRoutersException(Exception):
43
+ def __str__(self):
44
+ return "No Registered Router Found"
45
+
46
+
47
+ class NoRegisteredHandlersException(Exception):
48
+ def __init__(self, router_name):
49
+ self.router_name = router_name
50
+ def __str__(self):
51
+ return f"No Registered Handlers Found For '{self.router_name}'"
52
+
53
+
54
+ class RepeatedCommandInDifferentRoutersException(Exception):
55
+ def __str__(self):
56
+ return "Commands in different handlers cannot be repeated"
@@ -0,0 +1,123 @@
1
+ from typing import Callable, Any
2
+ from ..router.exceptions import (InvalidCommandInstanceException,
3
+ UnknownCommandHandlerHasAlreadyBeenCreatedException,
4
+ InvalidDescriptionInstanceException,
5
+ RepeatedCommandException)
6
+
7
+
8
+ class Router:
9
+ def __init__(self,
10
+ title: str = 'Commands group title:',
11
+ name: str = 'subordinate'):
12
+
13
+ self.title = title
14
+ self.name = name
15
+
16
+ self._command_entities: list[dict[str, Callable[[], None] | str]] = []
17
+ self.unknown_command_func: Callable[[str], None] | None = None
18
+ self._is_main_router: bool = False
19
+ self.ignore_command_register: bool = False
20
+
21
+
22
+ def command(self, command: str, description: str = None) -> Callable[[Any], Any]:
23
+ processed_description = Router._validate_description(command, description)
24
+ self._validate_command(command)
25
+
26
+ def command_decorator(func):
27
+ self._command_entities.append({'handler_func': func,
28
+ 'command': command,
29
+ 'description': processed_description})
30
+ def wrapper(*args, **kwargs):
31
+ return func(*args, **kwargs)
32
+ return wrapper
33
+
34
+ return command_decorator
35
+
36
+
37
+ def unknown_command(self, func):
38
+ if self.unknown_command_func is not None:
39
+ raise UnknownCommandHandlerHasAlreadyBeenCreatedException()
40
+
41
+ self.unknown_command_func: Callable = func
42
+
43
+ def wrapper(*args, **kwargs):
44
+ return func(*args, **kwargs)
45
+ return wrapper
46
+
47
+
48
+ def input_command_handler(self, input_command):
49
+ for command_entity in self._command_entities:
50
+ if input_command.lower() == command_entity['command'].lower():
51
+ if self.ignore_command_register:
52
+ return command_entity['handler_func']()
53
+ else:
54
+ if input_command == command_entity['command']:
55
+ return command_entity['handler_func']()
56
+
57
+
58
+ def unknown_command_handler(self, unknown_command):
59
+ self.unknown_command_func(unknown_command)
60
+
61
+
62
+ def _validate_command(self, command: str):
63
+ if not isinstance(command, str):
64
+ raise InvalidCommandInstanceException()
65
+ if command in self.get_all_commands():
66
+ raise RepeatedCommandException()
67
+ if self.ignore_command_register:
68
+ if command.lower() in [x.lower() for x in self.get_all_commands()]:
69
+ raise RepeatedCommandException()
70
+
71
+
72
+ @staticmethod
73
+ def _validate_description(command: str, description: str):
74
+ if not isinstance(description, str):
75
+ if description is None:
76
+ description = f'description for "{command}" command'
77
+ else:
78
+ raise InvalidDescriptionInstanceException()
79
+ return description
80
+
81
+
82
+ def set_router_as_main(self):
83
+ if self.name == 'subordinate':
84
+ self.name = 'main'
85
+ self._is_main_router = True
86
+
87
+
88
+ def set_ignore_command_register(self, ignore_command_register: bool):
89
+ self.ignore_command_register = ignore_command_register
90
+
91
+
92
+ def get_command_entities(self) -> list[dict[str, Callable[[], None] | str]]:
93
+ return self._command_entities
94
+
95
+
96
+ def get_name(self) -> str:
97
+ return self.name
98
+
99
+
100
+ def get_title(self) -> str:
101
+ return self.title
102
+
103
+
104
+ def get_router_info(self) -> dict:
105
+ return {
106
+ 'title': self.title,
107
+ 'name': self.name,
108
+ 'ignore_command_register': self.ignore_command_register,
109
+ 'attributes': {
110
+ 'command_entities': self._command_entities,
111
+ 'unknown_command_func': self.unknown_command_func,
112
+ 'is_main_router': self._is_main_router
113
+ }
114
+
115
+ }
116
+
117
+
118
+ def get_all_commands(self) -> list[str]:
119
+ all_commands: list[str] = []
120
+ for command_entity in self._command_entities:
121
+ all_commands.append(command_entity['command'])
122
+
123
+ return all_commands
@@ -11,3 +11,8 @@ class InvalidDescriptionInstanceException(Exception):
11
11
  class UnknownCommandHandlerHasAlreadyBeenCreatedException(Exception):
12
12
  def __str__(self):
13
13
  return "Only one unknown command handler can be declared"
14
+
15
+
16
+ class RepeatedCommandException(Exception):
17
+ def __str__(self):
18
+ return "Commands in handler cannot be repeated"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "argenta"
3
- version = "0.1.2"
3
+ version = "0.2.0"
4
4
  description = "python library for creating cli apps"
5
5
  authors = [
6
6
  {name = "kolo",email = "kolo.is.main@gmail.com"}
@@ -15,3 +15,14 @@ dependencies = [
15
15
  [build-system]
16
16
  requires = ["poetry-core>=2.0.0,<3.0.0"]
17
17
  build-backend = "poetry.core.masonry.api"
18
+
19
+ [tool.poetry.group.dev.dependencies]
20
+ art = "^6.4"
21
+ rich = "^13.9.4"
22
+ numpy = "^2.2.2"
23
+ word2number = "^1.1"
24
+ numexpr = "^2.10.2"
25
+ requests = "^2.32.3"
26
+ tqdm = "^4.67.1"
27
+ setuptools = "^75.8.0"
28
+
@@ -1,145 +0,0 @@
1
- from typing import Callable
2
- from ..router.entity import Router
3
- from .exceptions import (InvalidRouterInstanceException,
4
- InvalidDescriptionMessagePatternException,
5
- OnlyOneMainRouterIsAllowedException,
6
- MissingMainRouterException,
7
- MissingHandlersForUnknownCommandsOnMainRouterException,
8
- HandlerForUnknownCommandsCanOnlyBeDeclaredForMainRouterException)
9
-
10
-
11
- class App:
12
- def __init__(self,
13
- prompt: str = 'Enter a command',
14
- exit_command: str = 'q',
15
- ignore_exit_command_register: bool = True,
16
- initial_greeting: str = 'Hello',
17
- goodbye_message: str = 'GoodBye',
18
- line_separate: str = '\n',
19
- command_group_description_separate: str = '\n',
20
- print_func: Callable[[str], None] = print) -> None:
21
- self.prompt = prompt
22
- self.print_func = print_func
23
- self.exit_command = exit_command
24
- self.ignore_exit_command_register = ignore_exit_command_register
25
- self.goodbye_message = goodbye_message
26
- self.initial_greeting = initial_greeting
27
- self.line_separate = line_separate
28
- self.command_group_description_separate = command_group_description_separate
29
-
30
- self.routers: list[Router] = []
31
- self.registered_commands: list[dict[str, str | list[dict[str, Callable[[], None] | str]] | Router]] = []
32
- self.main_app_router: Router | None = None
33
- self._description_message_pattern = '[{command}] *=*=* {description}'
34
-
35
-
36
- def start_polling(self) -> None:
37
- self.print_func(self.initial_greeting)
38
- self.validate_main_router()
39
-
40
- while True:
41
- self.print_command_group_description()
42
- self.print_func(self.prompt)
43
-
44
- command: str = input()
45
-
46
- self.checking_command_for_exit_command(command)
47
- self.print_func(self.line_separate)
48
-
49
- is_unknown_command: bool = self.check_is_command_unknown(command)
50
-
51
- if is_unknown_command:
52
- continue
53
-
54
- for router in self.routers:
55
- router.input_command_handler(command)
56
- self.print_func(self.line_separate)
57
- self.print_func(self.command_group_description_separate)
58
-
59
-
60
- def set_initial_greeting(self, greeting: str) -> None:
61
- self.initial_greeting = greeting
62
-
63
-
64
- def set_goodbye_message(self, message: str) -> None:
65
- self.goodbye_message = message
66
-
67
-
68
- def set_description_message_pattern(self, pattern: str) -> None:
69
- try:
70
- pattern.format(command='command',
71
- description='description')
72
- except KeyError:
73
- raise InvalidDescriptionMessagePatternException(pattern)
74
- self._description_message_pattern = pattern
75
-
76
-
77
- def validate_main_router(self):
78
- if not self.main_app_router:
79
- raise MissingMainRouterException()
80
-
81
- if not self.main_app_router.unknown_command_func:
82
- raise MissingHandlersForUnknownCommandsOnMainRouterException()
83
-
84
- for router in self.routers:
85
- if router.unknown_command_func and self.main_app_router is not router:
86
- raise HandlerForUnknownCommandsCanOnlyBeDeclaredForMainRouterException()
87
-
88
-
89
- def checking_command_for_exit_command(self, command: str):
90
- if command.lower() == self.exit_command.lower():
91
- if self.ignore_exit_command_register:
92
- self.print_func(self.goodbye_message)
93
- exit(0)
94
- else:
95
- if command == self.exit_command:
96
- self.print_func(self.goodbye_message)
97
- exit(0)
98
-
99
-
100
- def check_is_command_unknown(self, command: str):
101
- registered_commands = self.registered_commands
102
- for router in registered_commands:
103
- for command_entity in router['commands']:
104
- if command_entity['command'].lower() == command.lower():
105
- if router['router'].ignore_command_register:
106
- return False
107
- else:
108
- if command_entity['command'] == command:
109
- return False
110
- self.main_app_router.unknown_command_handler(command)
111
- self.print_func(self.line_separate)
112
- self.print_func(self.command_group_description_separate)
113
- return True
114
-
115
-
116
- def print_command_group_description(self):
117
- for router in self.registered_commands:
118
- self.print_func(router['name'])
119
- for command_entity in router['commands']:
120
- self.print_func(self._description_message_pattern.format(
121
- command=command_entity['command'],
122
- description=command_entity['description']
123
- )
124
- )
125
- self.print_func(self.command_group_description_separate)
126
-
127
-
128
- def include_router(self, router: Router, is_main: bool = False) -> None:
129
- if not isinstance(router, Router):
130
- raise InvalidRouterInstanceException()
131
-
132
- if is_main:
133
- if not self.main_app_router:
134
- self.main_app_router = router
135
- router.set_router_as_main()
136
- else:
137
- raise OnlyOneMainRouterIsAllowedException(router)
138
-
139
- self.routers.append(router)
140
-
141
- registered_commands: list[dict[str, Callable[[], None] | str]] = router.get_registered_commands()
142
- self.registered_commands.append({'name': router.get_name(),
143
- 'router': router,
144
- 'commands': registered_commands})
145
-
@@ -1,70 +0,0 @@
1
- from typing import Callable, Any
2
- from ..router.exceptions import (InvalidCommandInstanceException,
3
- UnknownCommandHandlerHasAlreadyBeenCreatedException,
4
- InvalidDescriptionInstanceException)
5
-
6
-
7
- class Router:
8
- def __init__(self,
9
- name: str,
10
- ignore_command_register: bool = False):
11
-
12
- self.ignore_command_register: bool = ignore_command_register
13
- self._name = name
14
-
15
- self.processed_commands: list[dict[str, Callable[[], None] | str]] = []
16
- self.unknown_command_func: Callable[[str], None] | None = None
17
- self._is_main_router: bool = False
18
-
19
-
20
- def command(self, command: str, description: str) -> Callable[[Any], Any]:
21
- if not isinstance(command, str):
22
- raise InvalidCommandInstanceException()
23
- if not isinstance(description, str):
24
- raise InvalidDescriptionInstanceException()
25
- else:
26
- def command_decorator(func):
27
- self.processed_commands.append({'func': func,
28
- 'command': command,
29
- 'description': description})
30
- def wrapper(*args, **kwargs):
31
- return func(*args, **kwargs)
32
- return wrapper
33
- return command_decorator
34
-
35
-
36
- def unknown_command(self, func):
37
- if self.unknown_command_func is not None:
38
- raise UnknownCommandHandlerHasAlreadyBeenCreatedException()
39
-
40
- self.unknown_command_func = func
41
-
42
- def wrapper(*args, **kwargs):
43
- return func(*args, **kwargs)
44
- return wrapper
45
-
46
-
47
- def input_command_handler(self, input_command):
48
- for command_entity in self.processed_commands:
49
- if input_command.lower() == command_entity['command'].lower():
50
- if self.ignore_command_register:
51
- return command_entity['func']()
52
- else:
53
- if input_command == command_entity['command']:
54
- return command_entity['func']()
55
-
56
- def unknown_command_handler(self, unknown_command):
57
- self.unknown_command_func(unknown_command)
58
-
59
-
60
- def set_router_as_main(self):
61
- self._is_main_router = True
62
-
63
-
64
- def get_registered_commands(self) -> list[dict[str, Callable[[], None] | str]]:
65
- return self.processed_commands
66
-
67
-
68
- def get_name(self) -> str:
69
- return self._name
70
-
File without changes
File without changes
File without changes
File without changes