argenta 0.5.0b2__py3-none-any.whl → 1.0.0a0__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.
@@ -3,13 +3,25 @@ import readline
3
3
 
4
4
 
5
5
  class AutoCompleter:
6
- def __init__(self, history_filename: str = False, autocomplete_button: str = 'tab'):
6
+ def __init__(self, history_filename: str = False, autocomplete_button: str = 'tab') -> None:
7
+ """
8
+ Public. Configures and implements auto-completion of input command
9
+ :param history_filename: the name of the file for saving the history of the autocompleter
10
+ :param autocomplete_button: the button for auto-completion
11
+ :return: None
12
+ """
7
13
  self.history_filename = history_filename
8
14
  self.autocomplete_button = autocomplete_button
9
- self.matches = []
15
+ self.matches: list[str] = []
10
16
 
11
- def complete(self, text, state):
12
- matches = sorted(cmd for cmd in self.get_history_items() if cmd.startswith(text))
17
+ def complete(self, text, state) -> str | None:
18
+ """
19
+ Private. Auto-completion function
20
+ :param text: part of the command being entered
21
+ :param state: the current cursor position is relative to the beginning of the line
22
+ :return: the desired candidate as str or None
23
+ """
24
+ matches: list[str] = sorted(cmd for cmd in self.get_history_items() if cmd.startswith(text))
13
25
  if len(matches) > 1:
14
26
  common_prefix = matches[0]
15
27
  for match in matches[1:]:
@@ -26,7 +38,12 @@ class AutoCompleter:
26
38
  else:
27
39
  return None
28
40
 
29
- def initial_setup(self, all_commands: list[str]):
41
+ def initial_setup(self, all_commands: list[str]) -> None:
42
+ """
43
+ Private. Initial setup function
44
+ :param all_commands: Registered commands for adding them to the autocomplete history
45
+ :return: None
46
+ """
30
47
  if self.history_filename:
31
48
  if os.path.exists(self.history_filename):
32
49
  readline.read_history_file(self.history_filename)
@@ -38,10 +55,18 @@ class AutoCompleter:
38
55
  readline.set_completer_delims(readline.get_completer_delims().replace(' ', ''))
39
56
  readline.parse_and_bind(f'{self.autocomplete_button}: complete')
40
57
 
41
- def exit_setup(self):
58
+ def exit_setup(self) -> None:
59
+ """
60
+ Private. Exit setup function
61
+ :return: None
62
+ """
42
63
  if self.history_filename:
43
64
  readline.write_history_file(self.history_filename)
44
65
 
45
66
  @staticmethod
46
- def get_history_items():
67
+ def get_history_items() -> list[str] | list:
68
+ """
69
+ Private. Returns a list of all commands entered by the user
70
+ :return: all commands entered by the user as list[str]
71
+ """
47
72
  return [readline.get_history_item(i) for i in range(1, readline.get_current_history_length() + 1)]
argenta/app/defaults.py CHANGED
@@ -2,7 +2,10 @@ from dataclasses import dataclass
2
2
 
3
3
 
4
4
  @dataclass
5
- class PredeterminedMessages:
5
+ class PredefinedMessages:
6
+ """
7
+ Public. A dataclass with predetermined messages for quick use
8
+ """
6
9
  USAGE = '[b dim]Usage[/b dim]: [i]<command> <[green]flags[/green]>[/i]'
7
10
  HELP = '[b dim]Help[/b dim]: [i]<command>[/i] [b red]--help[/b red]'
8
11
  AUTOCOMPLETE = '[b dim]Autocomplete[/b dim]: [i]<part>[/i] [bold]<tab>'
@@ -1,24 +1,68 @@
1
- class BaseDividingLine:
2
- def __init__(self, unit_part: str = '-'):
3
- self.unit_part = unit_part
1
+ from abc import ABC
4
2
 
5
- def get_unit_part(self):
6
- if len(self.unit_part) == 0:
3
+
4
+ class BaseDividingLine(ABC):
5
+ def __init__(self, unit_part: str = '-') -> None:
6
+ """
7
+ Private. The basic dividing line
8
+ :param unit_part: the single part of the dividing line
9
+ :return: None
10
+ """
11
+ self._unit_part = unit_part
12
+
13
+ def get_unit_part(self) -> str:
14
+ """
15
+ Private. Returns the unit part of the dividing line
16
+ :return: unit_part of dividing line as str
17
+ """
18
+ if len(self._unit_part) == 0:
7
19
  return ' '
8
20
  else:
9
- return self.unit_part[0]
21
+ return self._unit_part[0]
22
+
10
23
 
11
24
  class StaticDividingLine(BaseDividingLine):
12
- def __init__(self, unit_part: str = '-', length: int = 25):
25
+ def __init__(self, unit_part: str = '-', length: int = 25) -> None:
26
+ """
27
+ Public. The static dividing line
28
+ :param unit_part: the single part of the dividing line
29
+ :param length: the length of the dividing line
30
+ :return: None
31
+ """
13
32
  super().__init__(unit_part)
14
33
  self.length = length
15
34
 
16
- def get_full_line(self):
17
- return f'\n[dim]{self.length * self.get_unit_part()}[/dim]\n'
35
+ def get_full_static_line(self, is_override: bool) -> str:
36
+ """
37
+ Private. Returns the full line of the dividing line
38
+ :param is_override: has the default text layout been redefined
39
+ :return: full line of dividing line as str
40
+ """
41
+ if is_override:
42
+ return f'\n{self.length * self.get_unit_part()}\n'
43
+ else:
44
+ return f'\n[dim]{self.length * self.get_unit_part()}[/dim]\n'
18
45
 
19
46
 
20
47
  class DynamicDividingLine(BaseDividingLine):
21
- def get_full_line(self, length: int):
22
- return f'\n[dim]{self.get_unit_part() * length}[/dim]\n'
48
+ def __init__(self, unit_part: str = '-') -> None:
49
+ """
50
+ Public. The dynamic dividing line
51
+ :param unit_part: the single part of the dividing line
52
+ :return: None
53
+ """
54
+ super().__init__(unit_part)
55
+
56
+ def get_full_dynamic_line(self, length: int, is_override: bool) -> str:
57
+ """
58
+ Private. Returns the full line of the dividing line
59
+ :param length: the length of the dividing line
60
+ :param is_override: has the default text layout been redefined
61
+ :return: full line of dividing line as str
62
+ """
63
+ if is_override:
64
+ return f'\n{length * self.get_unit_part()}\n'
65
+ else:
66
+ return f'\n[dim]{self.get_unit_part() * length}[/dim]\n'
23
67
 
24
68
 
argenta/app/exceptions.py CHANGED
@@ -1,10 +1,8 @@
1
- class NoRegisteredRoutersException(Exception):
2
- def __str__(self):
3
- return "No Registered Router Found"
4
-
5
-
6
1
  class NoRegisteredHandlersException(Exception):
7
- def __init__(self, router_name):
2
+ """
3
+ The router has no registered handlers
4
+ """
5
+ def __init__(self, router_name) -> None:
8
6
  self.router_name = router_name
9
7
  def __str__(self):
10
8
  return f"No Registered Handlers Found For '{self.router_name}'"
argenta/app/models.py CHANGED
@@ -15,29 +15,29 @@ from argenta.command.exceptions import (UnprocessedInputFlagException,
15
15
  RepeatedInputFlagsException,
16
16
  EmptyInputCommandException,
17
17
  BaseInputCommandException)
18
- from argenta.app.exceptions import (NoRegisteredRoutersException,
19
- NoRegisteredHandlersException)
18
+ from argenta.app.exceptions import NoRegisteredHandlersException
20
19
  from argenta.app.registered_routers.entity import RegisteredRouters
21
20
 
22
21
 
23
22
 
24
- class AppInit:
23
+ class BaseApp:
25
24
  def __init__(self,
26
- prompt: str = '[italic dim bold]What do you want to do?\n',
27
- initial_message: str = '\nArgenta\n',
28
- farewell_message: str = '\nSee you\n',
29
- exit_command: Command = Command('Q', 'Exit command'),
30
- system_points_title: str | None = 'System points:',
31
- ignore_command_register: bool = True,
32
- dividing_line: StaticDividingLine | DynamicDividingLine = StaticDividingLine(),
33
- repeat_command_groups: bool = True,
34
- override_system_messages: bool = False,
35
- autocompleter: AutoCompleter = AutoCompleter(),
36
- print_func: Callable[[str], None] = Console().print) -> None:
25
+ prompt: str,
26
+ initial_message: str,
27
+ farewell_message: str,
28
+ exit_command: Command,
29
+ system_router_title: str | None,
30
+ ignore_command_register: bool,
31
+ dividing_line: StaticDividingLine | DynamicDividingLine,
32
+ repeat_command_groups: bool,
33
+ override_system_messages: bool,
34
+ autocompleter: AutoCompleter,
35
+ print_func: Callable[[str], None]) -> None:
36
+
37
37
  self._prompt = prompt
38
38
  self._print_func = print_func
39
39
  self._exit_command = exit_command
40
- self._system_points_title = system_points_title
40
+ self._system_router_title = system_router_title
41
41
  self._dividing_line = dividing_line
42
42
  self._ignore_command_register = ignore_command_register
43
43
  self._repeat_command_groups_description = repeat_command_groups
@@ -48,44 +48,79 @@ class AppInit:
48
48
  self._initial_message = initial_message
49
49
 
50
50
 
51
- self._description_message_gen: Callable[[str, str], str] = lambda command, description: f'[bold red]{escape('['+command+']')}[/bold red] [blue dim]*=*=*[/blue dim] [bold yellow italic]{escape(description)}'
51
+ self._description_message_gen: Callable[[str, str], str] = lambda command, description: f'[{command}] *=*=* {description}'
52
52
  self._registered_routers: RegisteredRouters = RegisteredRouters()
53
- self._messages_on_startup = []
53
+ self._messages_on_startup: list[str] = []
54
+
55
+ self._all_registered_triggers_in_lower: list[str] = []
56
+ self._all_registered_triggers_in_default_case: list[str] = []
54
57
 
55
- self._invalid_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'[red bold]Incorrect flag syntax: {escape(raw_command)}')
56
- self._repeated_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'[red bold]Repeated input flags: {escape(raw_command)}')
57
- self._empty_input_command_handler: Callable[[], None] = lambda: print_func('[red bold]Empty input command')
58
- self._unknown_command_handler: Callable[[InputCommand], None] = lambda command: print_func(f"[red bold]Unknown command: {escape(command.get_trigger())}")
58
+ self._invalid_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'Incorrect flag syntax: {raw_command}')
59
+ self._repeated_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'Repeated input flags: {raw_command}')
60
+ self._empty_input_command_handler: Callable[[], None] = lambda: print_func('Empty input command')
61
+ self._unknown_command_handler: Callable[[InputCommand], None] = lambda command: print_func(f"Unknown command: {command.get_trigger()}")
59
62
  self._exit_command_handler: Callable[[], None] = lambda: print_func(self._farewell_message)
60
63
 
61
64
 
62
- class AppSetters(AppInit):
63
65
  def set_description_message_pattern(self, pattern: Callable[[str, str], str]) -> None:
66
+ """
67
+ Public. Sets the output pattern of the available commands
68
+ :param pattern: output pattern of the available commands
69
+ :return: None
70
+ """
64
71
  self._description_message_gen: Callable[[str, str], str] = pattern
65
72
 
66
73
 
67
74
  def set_invalid_input_flags_handler(self, handler: Callable[[str], None]) -> None:
75
+ """
76
+ Public. Sets the handler for incorrect flags when entering a command
77
+ :param handler: handler for incorrect flags when entering a command
78
+ :return: None
79
+ """
68
80
  self._invalid_input_flags_handler = handler
69
81
 
70
82
 
71
83
  def set_repeated_input_flags_handler(self, handler: Callable[[str], None]) -> None:
84
+ """
85
+ Public. Sets the handler for repeated flags when entering a command
86
+ :param handler: handler for repeated flags when entering a command
87
+ :return: None
88
+ """
72
89
  self._repeated_input_flags_handler = handler
73
90
 
74
91
 
75
92
  def set_unknown_command_handler(self, handler: Callable[[str], None]) -> None:
93
+ """
94
+ Public. Sets the handler for unknown commands when entering a command
95
+ :param handler: handler for unknown commands when entering a command
96
+ :return: None
97
+ """
76
98
  self._unknown_command_handler = handler
77
99
 
78
100
 
79
101
  def set_empty_command_handler(self, handler: Callable[[], None]) -> None:
102
+ """
103
+ Public. Sets the handler for empty commands when entering a command
104
+ :param handler: handler for empty commands when entering a command
105
+ :return: None
106
+ """
80
107
  self._empty_input_command_handler = handler
81
108
 
82
109
 
83
110
  def set_exit_command_handler(self, handler: Callable[[], None]) -> None:
111
+ """
112
+ Public. Sets the handler for exit command when entering a command
113
+ :param handler: handler for exit command when entering a command
114
+ :return: None
115
+ """
84
116
  self._exit_command_handler = handler
85
117
 
86
118
 
87
- class AppPrinters(AppInit):
88
- def _print_command_group_description(self):
119
+ def _print_command_group_description(self) -> None:
120
+ """
121
+ Private. Prints the description of the available commands
122
+ :return: None
123
+ """
89
124
  for registered_router in self._registered_routers:
90
125
  if registered_router.get_title():
91
126
  self._print_func(registered_router.get_title())
@@ -96,54 +131,74 @@ class AppPrinters(AppInit):
96
131
  self._print_func('')
97
132
 
98
133
 
99
- def _print_framed_text_with_dynamic_line(self, text: str):
100
- clear_text = re.sub(r'\u001b\[[0-9;]*m', '', text)
101
- max_length_line = max([len(line) for line in clear_text.split('\n')])
102
- max_length_line = max_length_line if 10 <= max_length_line <= 80 else 80 if max_length_line > 80 else 10
103
- self._print_func(self._dividing_line.get_full_line(max_length_line))
104
- print(text.strip('\n'))
105
- self._print_func(self._dividing_line.get_full_line(max_length_line))
106
-
134
+ def _print_framed_text(self, text: str) -> None:
135
+ """
136
+ Private. Outputs text by framing it in a static or dynamic split strip
137
+ :param text: framed text
138
+ :return: None
139
+ """
140
+ if isinstance(self._dividing_line, StaticDividingLine):
141
+ self._print_func(self._dividing_line.get_full_static_line(self._override_system_messages))
142
+ self._print_func(text)
143
+ self._print_func(self._dividing_line.get_full_static_line(self._override_system_messages))
107
144
 
108
- class AppNonStandardHandlers(AppPrinters):
109
- def _is_exit_command(self, command: InputCommand):
110
- if command.get_trigger().lower() == self._exit_command.get_trigger().lower():
111
- if self._ignore_command_register:
112
- system_router.input_command_handler(command)
145
+ elif isinstance(self._dividing_line, DynamicDividingLine):
146
+ clear_text = re.sub(r'\u001b\[[0-9;]*m', '', text)
147
+ max_length_line = max([len(line) for line in clear_text.split('\n')])
148
+ max_length_line = max_length_line if 10 <= max_length_line <= 80 else 80 if max_length_line > 80 else 10
149
+
150
+ self._print_func(self._dividing_line.get_full_dynamic_line(max_length_line, self._override_system_messages))
151
+ print(text.strip('\n'))
152
+ self._print_func(self._dividing_line.get_full_dynamic_line(max_length_line, self._override_system_messages))
153
+
154
+
155
+ def _is_exit_command(self, command: InputCommand) -> bool:
156
+ """
157
+ Private. Checks if the given command is an exit command
158
+ :param command: command to check
159
+ :return: is it an exit command or not as bool
160
+ """
161
+ if self._ignore_command_register:
162
+ if command.get_trigger().lower() == self._exit_command.get_trigger().lower():
113
163
  return True
114
- elif command.get_trigger() == self._exit_command.get_trigger():
115
- system_router.input_command_handler(command)
164
+ elif command.get_trigger().lower() in [x.lower() for x in self._exit_command.get_aliases()]:
165
+ return True
166
+ else:
167
+ if command.get_trigger() == self._exit_command.get_trigger():
168
+ return True
169
+ elif command.get_trigger() in self._exit_command.get_aliases():
116
170
  return True
117
171
  return False
118
172
 
119
173
 
120
- def _is_unknown_command(self, command: InputCommand):
121
- for router_entity in self._registered_routers:
122
- for command_handler in router_entity.get_command_handlers():
123
- handled_command_trigger = command_handler.get_handled_command().get_trigger()
124
- handled_command_aliases = command_handler.get_handled_command().get_aliases()
125
- if handled_command_trigger.lower() == command.get_trigger().lower() and self._ignore_command_register:
126
- return False
127
- elif handled_command_trigger == command.get_trigger():
128
- return False
129
- elif handled_command_aliases:
130
- if (command.get_trigger().lower() in [x.lower() for x in handled_command_aliases]) and self._ignore_command_register:
131
- return False
132
- elif command.get_trigger() in handled_command_trigger:
133
- return False
134
- if isinstance(self._dividing_line, StaticDividingLine):
135
- self._print_func(self._dividing_line.get_full_line())
174
+ def _is_unknown_command(self, command: InputCommand) -> bool:
175
+ """
176
+ Private. Checks if the given command is an unknown command
177
+ :param command: command to check
178
+ :return: is it an unknown command or not as bool
179
+ """
180
+ input_command_trigger = command.get_trigger()
181
+ if self._ignore_command_register:
182
+ if input_command_trigger.lower() in self._all_registered_triggers_in_lower:
183
+ return False
184
+ else:
185
+ if input_command_trigger in self._all_registered_triggers_in_default_case:
186
+ return False
187
+
188
+ with redirect_stdout(io.StringIO()) as f:
136
189
  self._unknown_command_handler(command)
137
- self._print_func(self._dividing_line.get_full_line())
138
- elif isinstance(self._dividing_line, DynamicDividingLine):
139
- with redirect_stdout(io.StringIO()) as f:
140
- self._unknown_command_handler(command)
141
- res: str = f.getvalue()
142
- self._print_framed_text_with_dynamic_line(res)
190
+ res: str = f.getvalue()
191
+ self._print_framed_text(res)
143
192
  return True
144
193
 
145
194
 
146
195
  def _error_handler(self, error: BaseInputCommandException, raw_command: str) -> None:
196
+ """
197
+ Private. Handles parsing errors of the entered command
198
+ :param error: error being handled
199
+ :param raw_command: the raw input command
200
+ :return: None
201
+ """
147
202
  match error:
148
203
  case UnprocessedInputFlagException():
149
204
  self._invalid_input_flags_handler(raw_command)
@@ -153,61 +208,127 @@ class AppNonStandardHandlers(AppPrinters):
153
208
  self._empty_input_command_handler()
154
209
 
155
210
 
156
- class AppValidators(AppInit):
157
- def _validate_number_of_routers(self) -> None:
158
- if not self._registered_routers:
159
- raise NoRegisteredRoutersException()
160
-
161
-
162
211
  def _validate_included_routers(self) -> None:
212
+ """
213
+ Private. Validates included routers
214
+ :return: None
215
+ """
163
216
  for router in self._registered_routers:
164
217
  if not router.get_command_handlers():
165
218
  raise NoRegisteredHandlersException(router.get_name())
166
219
 
167
220
 
168
- class AppSetups(AppValidators, AppPrinters):
169
- def _setup_system_router(self):
170
- system_router.set_title(self._system_points_title)
221
+ def _setup_system_router(self) -> None:
222
+ """
223
+ Private. Sets up system router
224
+ :return: None
225
+ """
226
+ system_router.set_title(self._system_router_title)
171
227
 
172
228
  @system_router.command(self._exit_command)
173
229
  def exit_command():
174
230
  self._exit_command_handler()
175
231
 
176
232
  if system_router not in self._registered_routers.get_registered_routers():
177
- system_router.set_ignore_command_register(self._ignore_command_register)
233
+ system_router.set_command_register_ignore(self._ignore_command_register)
178
234
  self._registered_routers.add_registered_router(system_router)
179
235
 
180
- def _setup_default_view(self):
181
- if not self._override_system_messages:
182
- self._initial_message = f'\n[bold red]{text2art(self._initial_message, font='tarty1')}\n\n'
183
- self._farewell_message = (
184
- f'[bold red]\n{text2art(f'\n{self._farewell_message}\n', font='chanky')}[/bold red]\n'
185
- f'[red i]github.com/koloideal/Argenta[/red i] | [red bold i]made by kolo[/red bold i]\n')
186
236
 
187
- def _pre_cycle_setup(self):
237
+ def _setup_default_view(self) -> None:
238
+ """
239
+ Private. Sets up default app view
240
+ :return: None
241
+ """
242
+ if not self._override_system_messages:
243
+ self._initial_message = f'\n[bold red]{text2art(self._initial_message, font="tarty1")}\n\n'
244
+ self._farewell_message = (f'[bold red]\n{text2art(f"\n{self._farewell_message}\n", font="chanky")}[/bold red]\n'
245
+ f'[red i]github.com/koloideal/Argenta[/red i] | [red bold i]made by kolo[/red bold i]\n')
246
+ self._description_message_gen = lambda command, description: (f'[bold red]{escape("[" + command + "]")}[/bold red] '
247
+ f'[blue dim]*=*=*[/blue dim] '
248
+ f'[bold yellow italic]{escape(description)}')
249
+ self._invalid_input_flags_handler = lambda raw_command: self._print_func(f'[red bold]Incorrect flag syntax: {escape(raw_command)}')
250
+ self._repeated_input_flags_handler = lambda raw_command: self._print_func(f'[red bold]Repeated input flags: {escape(raw_command)}')
251
+ self._empty_input_command_handler = lambda: self._print_func('[red bold]Empty input command')
252
+ self._unknown_command_handler = lambda command: self._print_func(f"[red bold]Unknown command: {escape(command.get_trigger())}")
253
+
254
+
255
+ def _pre_cycle_setup(self) -> None:
256
+ """
257
+ Private. Configures various aspects of the application before the start of the cycle
258
+ :return: None
259
+ """
188
260
  self._setup_default_view()
189
261
  self._setup_system_router()
190
- self._validate_number_of_routers()
191
262
  self._validate_included_routers()
192
263
 
193
- all_triggers: list[str] = []
194
264
  for router_entity in self._registered_routers:
195
- all_triggers.extend(router_entity.get_triggers())
196
- all_triggers.extend(router_entity.get_aliases())
197
- self._autocompleter.initial_setup(all_triggers)
265
+ self._all_registered_triggers_in_default_case.extend(router_entity.get_triggers())
266
+ self._all_registered_triggers_in_default_case.extend(router_entity.get_aliases())
267
+
268
+ self._all_registered_triggers_in_lower.extend([x.lower() for x in router_entity.get_triggers()])
269
+ self._all_registered_triggers_in_lower.extend([x.lower() for x in router_entity.get_aliases()])
270
+
271
+ self._autocompleter.initial_setup(self._all_registered_triggers_in_lower)
198
272
 
199
273
  self._print_func(self._initial_message)
200
274
 
201
275
  for message in self._messages_on_startup:
202
276
  self._print_func(message)
203
- print('\n\n')
277
+ if self._messages_on_startup:
278
+ print('\n\n')
204
279
 
205
280
  if not self._repeat_command_groups_description:
206
281
  self._print_command_group_description()
207
282
 
208
283
 
209
- class App(AppSetters, AppNonStandardHandlers, AppSetups):
210
- def start_polling(self) -> None:
284
+
285
+ class App(BaseApp):
286
+ def __init__(self,
287
+ prompt: str = '[italic dim bold]What do you want to do?\n',
288
+ initial_message: str = '\nArgenta\n',
289
+ farewell_message: str = '\nSee you\n',
290
+ exit_command: Command = Command('Q', 'Exit command'),
291
+ system_router_title: str | None = 'System points:',
292
+ ignore_command_register: bool = True,
293
+ dividing_line: StaticDividingLine | DynamicDividingLine = StaticDividingLine(),
294
+ repeat_command_groups: bool = True,
295
+ override_system_messages: bool = False,
296
+ autocompleter: AutoCompleter = AutoCompleter(),
297
+ print_func: Callable[[str], None] = Console().print) -> None:
298
+ """
299
+ Public. The essence of the application itself.
300
+ Configures and manages all aspects of the behavior and presentation of the user interacting with the user
301
+ :param prompt: displayed before entering the command
302
+ :param initial_message: displayed at the start of the app
303
+ :param farewell_message: displayed at the end of the app
304
+ :param exit_command: the entity of the command that will be terminated when entered
305
+ :param system_router_title: system router title
306
+ :param ignore_command_register: whether to ignore the case of the entered commands
307
+ :param dividing_line: the entity of the dividing line
308
+ :param repeat_command_groups: whether to repeat the available commands and their description
309
+ :param override_system_messages: whether to redefine the default formatting of system messages
310
+ :param autocompleter: the entity of the autocompleter
311
+ :param print_func: system messages text output function
312
+ :return: None
313
+ """
314
+ super().__init__(prompt=prompt,
315
+ initial_message=initial_message,
316
+ farewell_message=farewell_message,
317
+ exit_command=exit_command,
318
+ system_router_title=system_router_title,
319
+ ignore_command_register=ignore_command_register,
320
+ dividing_line=dividing_line,
321
+ repeat_command_groups=repeat_command_groups,
322
+ override_system_messages=override_system_messages,
323
+ autocompleter=autocompleter,
324
+ print_func=print_func)
325
+
326
+
327
+ def run_polling(self) -> None:
328
+ """
329
+ Private. Starts the user input processing cycle
330
+ :return: None
331
+ """
211
332
  self._pre_cycle_setup()
212
333
  while True:
213
334
  if self._repeat_command_groups_description:
@@ -218,50 +339,55 @@ class App(AppSetters, AppNonStandardHandlers, AppSetups):
218
339
  try:
219
340
  input_command: InputCommand = InputCommand.parse(raw_command=raw_command)
220
341
  except BaseInputCommandException as error:
221
- if isinstance(self._dividing_line, StaticDividingLine):
222
- self._print_func(self._dividing_line.get_full_line())
342
+ with redirect_stdout(io.StringIO()) as f:
223
343
  self._error_handler(error, raw_command)
224
- self._print_func(self._dividing_line.get_full_line())
225
- elif isinstance(self._dividing_line, DynamicDividingLine):
226
- with redirect_stdout(io.StringIO()) as f:
227
- self._error_handler(error, raw_command)
228
- res: str = f.getvalue()
229
- self._print_framed_text_with_dynamic_line(res)
344
+ res: str = f.getvalue()
345
+ self._print_framed_text(res)
230
346
  continue
231
347
 
232
348
  if self._is_exit_command(input_command):
349
+ system_router.finds_appropriate_handler(input_command)
233
350
  self._autocompleter.exit_setup()
234
351
  return
235
352
 
236
353
  if self._is_unknown_command(input_command):
237
354
  continue
238
355
 
239
- if isinstance(self._dividing_line, StaticDividingLine):
240
- self._print_func(self._dividing_line.get_full_line())
356
+ with redirect_stdout(io.StringIO()) as f:
241
357
  for registered_router in self._registered_routers:
242
- registered_router.input_command_handler(input_command)
243
- self._print_func(self._dividing_line.get_full_line())
244
- elif isinstance(self._dividing_line, DynamicDividingLine):
245
- with redirect_stdout(io.StringIO()) as f:
246
- for registered_router in self._registered_routers:
247
- registered_router.input_command_handler(input_command)
248
- res: str = f.getvalue()
249
- self._print_framed_text_with_dynamic_line(res)
358
+ registered_router.finds_appropriate_handler(input_command)
359
+ res: str = f.getvalue()
360
+ self._print_framed_text(res)
250
361
 
251
362
  if not self._repeat_command_groups_description:
252
363
  self._print_func(self._prompt)
253
364
 
254
365
 
255
366
  def include_router(self, router: Router) -> None:
256
- router.set_ignore_command_register(self._ignore_command_register)
367
+ """
368
+ Public. Registers the router in the application
369
+ :param router: registered router
370
+ :return: None
371
+ """
372
+ router.set_command_register_ignore(self._ignore_command_register)
257
373
  self._registered_routers.add_registered_router(router)
258
374
 
259
375
 
260
376
  def include_routers(self, *routers: Router) -> None:
377
+ """
378
+ Public. Registers the routers in the application
379
+ :param routers: registered routers
380
+ :return: None
381
+ """
261
382
  for router in routers:
262
383
  self.include_router(router)
263
384
 
264
385
 
265
386
  def add_message_on_startup(self, message: str) -> None:
387
+ """
388
+ Public. Adds a message that will be displayed when the application is launched
389
+ :param message: the message being added
390
+ :return: None
391
+ """
266
392
  self._messages_on_startup.append(message)
267
393