orionis 0.1.0__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 (133) hide show
  1. orionis/__init__.py +0 -0
  2. orionis/cli_manager.py +48 -0
  3. orionis/framework.py +45 -0
  4. orionis/luminate/__init__.py +0 -0
  5. orionis/luminate/app.py +0 -0
  6. orionis/luminate/bootstrap/__init__.py +0 -0
  7. orionis/luminate/bootstrap/parser.py +49 -0
  8. orionis/luminate/bootstrap/register.py +95 -0
  9. orionis/luminate/cache/__init__.py +0 -0
  10. orionis/luminate/cache/app/__init__.py +0 -0
  11. orionis/luminate/cache/app/config.py +96 -0
  12. orionis/luminate/cache/console/__init__.py +0 -0
  13. orionis/luminate/cache/console/commands.py +98 -0
  14. orionis/luminate/config/__init__.py +0 -0
  15. orionis/luminate/config/dataclass/__init__.py +0 -0
  16. orionis/luminate/config/dataclass/app.py +50 -0
  17. orionis/luminate/config/dataclass/auth.py +17 -0
  18. orionis/luminate/config/dataclass/cache.py +51 -0
  19. orionis/luminate/config/dataclass/cors.py +58 -0
  20. orionis/luminate/config/dataclass/database.py +203 -0
  21. orionis/luminate/config/dataclass/filesystems.py +102 -0
  22. orionis/luminate/config/dataclass/logging.py +107 -0
  23. orionis/luminate/config/dataclass/mail.py +81 -0
  24. orionis/luminate/config/dataclass/queue.py +63 -0
  25. orionis/luminate/config/dataclass/session.py +59 -0
  26. orionis/luminate/config/environment.py +110 -0
  27. orionis/luminate/config/sections.py +37 -0
  28. orionis/luminate/console/__init__.py +0 -0
  29. orionis/luminate/console/base/__init__.py +0 -0
  30. orionis/luminate/console/base/command.py +427 -0
  31. orionis/luminate/console/cache.py +132 -0
  32. orionis/luminate/console/command.py +40 -0
  33. orionis/luminate/console/command_filter.py +40 -0
  34. orionis/luminate/console/commands/__init__.py +0 -0
  35. orionis/luminate/console/commands/cache_clear.py +56 -0
  36. orionis/luminate/console/commands/help.py +59 -0
  37. orionis/luminate/console/commands/schedule_work.py +50 -0
  38. orionis/luminate/console/commands/tests.py +40 -0
  39. orionis/luminate/console/commands/version.py +39 -0
  40. orionis/luminate/console/exceptions/__init__.py +0 -0
  41. orionis/luminate/console/exceptions/cli_exception.py +125 -0
  42. orionis/luminate/console/kernel.py +32 -0
  43. orionis/luminate/console/output/__init__.py +0 -0
  44. orionis/luminate/console/output/console.py +426 -0
  45. orionis/luminate/console/output/executor.py +90 -0
  46. orionis/luminate/console/output/progress_bar.py +100 -0
  47. orionis/luminate/console/output/styles.py +95 -0
  48. orionis/luminate/console/parser.py +159 -0
  49. orionis/luminate/console/register.py +98 -0
  50. orionis/luminate/console/runner.py +126 -0
  51. orionis/luminate/console/scripts/__init__.py +0 -0
  52. orionis/luminate/console/scripts/management.py +94 -0
  53. orionis/luminate/console/tasks/__init__.py +0 -0
  54. orionis/luminate/console/tasks/scheduler.py +616 -0
  55. orionis/luminate/contracts/__init__.py +0 -0
  56. orionis/luminate/contracts/bootstrap/parser_interface.py +46 -0
  57. orionis/luminate/contracts/cache/__init__.py +0 -0
  58. orionis/luminate/contracts/cache/cache_commands_interface.py +69 -0
  59. orionis/luminate/contracts/config/__init__.py +0 -0
  60. orionis/luminate/contracts/config/config_interface.py +27 -0
  61. orionis/luminate/contracts/config/environment_interface.py +64 -0
  62. orionis/luminate/contracts/console/__init__.py +0 -0
  63. orionis/luminate/contracts/console/base_command_interface.py +448 -0
  64. orionis/luminate/contracts/console/cli_cache_interface.py +34 -0
  65. orionis/luminate/contracts/console/command_filter_interface.py +32 -0
  66. orionis/luminate/contracts/console/command_interface.py +36 -0
  67. orionis/luminate/contracts/console/console_interface.py +305 -0
  68. orionis/luminate/contracts/console/executor_interface.py +51 -0
  69. orionis/luminate/contracts/console/kernel_interface.py +32 -0
  70. orionis/luminate/contracts/console/management_interface.py +63 -0
  71. orionis/luminate/contracts/console/parser_interface.py +76 -0
  72. orionis/luminate/contracts/console/progress_bar_interface.py +66 -0
  73. orionis/luminate/contracts/console/register_interface.py +32 -0
  74. orionis/luminate/contracts/console/runner_interface.py +50 -0
  75. orionis/luminate/contracts/console/schedule_interface.py +317 -0
  76. orionis/luminate/contracts/console/task_manager_interface.py +37 -0
  77. orionis/luminate/contracts/facades/__init__.py +0 -0
  78. orionis/luminate/contracts/facades/env_interface.py +64 -0
  79. orionis/luminate/contracts/facades/log_interface.py +48 -0
  80. orionis/luminate/contracts/facades/paths_interface.py +141 -0
  81. orionis/luminate/contracts/facades/tests_interface.py +33 -0
  82. orionis/luminate/contracts/files/__init__.py +0 -0
  83. orionis/luminate/contracts/files/paths_interface.py +29 -0
  84. orionis/luminate/contracts/installer/__init__.py +0 -0
  85. orionis/luminate/contracts/installer/output_interface.py +125 -0
  86. orionis/luminate/contracts/installer/setup_interface.py +29 -0
  87. orionis/luminate/contracts/installer/upgrade_interface.py +24 -0
  88. orionis/luminate/contracts/log/__init__.py +0 -0
  89. orionis/luminate/contracts/log/logger_interface.py +33 -0
  90. orionis/luminate/contracts/pipelines/cli_pipeline_interface.py +84 -0
  91. orionis/luminate/contracts/publisher/__init__.py +0 -0
  92. orionis/luminate/contracts/publisher/pypi_publisher_interface.py +36 -0
  93. orionis/luminate/contracts/test/__init__.py +0 -0
  94. orionis/luminate/contracts/test/unit_test_interface.py +51 -0
  95. orionis/luminate/contracts/tools/__init__.py +0 -0
  96. orionis/luminate/contracts/tools/reflection_interface.py +343 -0
  97. orionis/luminate/contracts/tools/std_interface.py +56 -0
  98. orionis/luminate/facades/__init__.py +0 -0
  99. orionis/luminate/facades/environment.py +81 -0
  100. orionis/luminate/facades/log.py +56 -0
  101. orionis/luminate/facades/paths.py +268 -0
  102. orionis/luminate/facades/tests.py +48 -0
  103. orionis/luminate/files/__init__.py +0 -0
  104. orionis/luminate/files/paths.py +56 -0
  105. orionis/luminate/installer/__init__.py +0 -0
  106. orionis/luminate/installer/icon.ascii +11 -0
  107. orionis/luminate/installer/info.ascii +13 -0
  108. orionis/luminate/installer/output.py +188 -0
  109. orionis/luminate/installer/setup.py +191 -0
  110. orionis/luminate/installer/upgrade.py +42 -0
  111. orionis/luminate/log/__init__.py +0 -0
  112. orionis/luminate/log/logger.py +116 -0
  113. orionis/luminate/pipelines/__init__.py +0 -0
  114. orionis/luminate/pipelines/cli_pipeline.py +116 -0
  115. orionis/luminate/publisher/__init__.py +0 -0
  116. orionis/luminate/publisher/pypi.py +206 -0
  117. orionis/luminate/static/logos/flaskavel.png +0 -0
  118. orionis/luminate/test/__init__.py +0 -0
  119. orionis/luminate/test/exception.py +48 -0
  120. orionis/luminate/test/unit_test.py +108 -0
  121. orionis/luminate/tools/__init__.py +0 -0
  122. orionis/luminate/tools/reflection.py +390 -0
  123. orionis/luminate/tools/std.py +53 -0
  124. orionis-0.1.0.dist-info/LICENCE +21 -0
  125. orionis-0.1.0.dist-info/METADATA +27 -0
  126. orionis-0.1.0.dist-info/RECORD +133 -0
  127. orionis-0.1.0.dist-info/WHEEL +5 -0
  128. orionis-0.1.0.dist-info/entry_points.txt +2 -0
  129. orionis-0.1.0.dist-info/top_level.txt +2 -0
  130. tests/__init__.py +0 -0
  131. tests/tools/__init__.py +0 -0
  132. tests/tools/class_example.py +50 -0
  133. tests/tools/test_reflection.py +128 -0
@@ -0,0 +1,426 @@
1
+ import os
2
+ import sys
3
+ import getpass
4
+ import datetime
5
+ from orionis.luminate.console.output.styles import ANSIColors
6
+ from orionis.luminate.contracts.console.console_interface import IConsole
7
+
8
+ class Console(IConsole):
9
+ """
10
+ Utility class for printing formatted messages to the console with ANSI colors.
11
+
12
+ Provides methods to print success, info, warning, and error messages with
13
+ optional timestamps, as well as general text formatting methods.
14
+ """
15
+
16
+ @staticmethod
17
+ def _get_timestamp() -> str:
18
+ """
19
+ Returns the current date and time formatted in a muted color.
20
+
21
+ Returns
22
+ -------
23
+ str
24
+ The formatted timestamp with muted color.
25
+ """
26
+ return f"{ANSIColors.TEXT_MUTED.value}{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}{ANSIColors.DEFAULT.value}"
27
+
28
+ @staticmethod
29
+ def _print_with_background(label: str, bg_color: ANSIColors, message: str, timestamp: bool):
30
+ """
31
+ Prints a formatted message with a background color.
32
+
33
+ Parameters
34
+ ----------
35
+ label : str
36
+ The label to display (e.g., 'SUCCESS', 'INFO').
37
+ bg_color : ANSIColors
38
+ The background color to use.
39
+ message : str
40
+ The message to print.
41
+ timestamp : bool
42
+ Whether to include a timestamp.
43
+ """
44
+ str_time = Console._get_timestamp() if timestamp else ''
45
+ print(f"{bg_color.value}{ANSIColors.TEXT_WHITE.value} {label} {ANSIColors.DEFAULT.value} {str_time} {message}{ANSIColors.DEFAULT.value}")
46
+
47
+ @staticmethod
48
+ def _print_colored(message: str, text_color: ANSIColors):
49
+ """
50
+ Prints a message with a specified text color.
51
+
52
+ Parameters
53
+ ----------
54
+ message : str
55
+ The message to print.
56
+ text_color : ANSIColors
57
+ The text color to use.
58
+ """
59
+ print(f"{text_color.value}{message}{ANSIColors.DEFAULT.value}")
60
+
61
+ # ---- SUCCESS ----
62
+
63
+ @staticmethod
64
+ def success(message: str = '', timestamp: bool = True):
65
+ """
66
+ Prints a success message with a green background.
67
+
68
+ Parameters
69
+ ----------
70
+ message : str, optional
71
+ The success message to print (default is '').
72
+ timestamp : bool, optional
73
+ Whether to include a timestamp (default is True).
74
+ """
75
+ Console._print_with_background("SUCCESS", ANSIColors.BG_SUCCESS, message, timestamp)
76
+
77
+ @staticmethod
78
+ def textSuccess(message: str = ''):
79
+ """Prints a success message in green."""
80
+ Console._print_colored(message, ANSIColors.TEXT_SUCCESS)
81
+
82
+ @staticmethod
83
+ def textSuccessBold(message: str = ''):
84
+ """Prints a bold success message in green."""
85
+ Console._print_colored(message, ANSIColors.TEXT_BOLD_SUCCESS)
86
+
87
+ # ---- INFO ----
88
+
89
+ @staticmethod
90
+ def info(message: str = '', timestamp: bool = True):
91
+ """Prints an informational message with a blue background."""
92
+ Console._print_with_background("INFO", ANSIColors.BG_INFO, message, timestamp)
93
+
94
+ @staticmethod
95
+ def textInfo(message: str = ''):
96
+ """Prints an informational message in blue."""
97
+ Console._print_colored(message, ANSIColors.TEXT_INFO)
98
+
99
+ @staticmethod
100
+ def textInfoBold(message: str = ''):
101
+ """Prints a bold informational message in blue."""
102
+ Console._print_colored(message, ANSIColors.TEXT_BOLD_INFO)
103
+
104
+ # ---- WARNING ----
105
+
106
+ @staticmethod
107
+ def warning(message: str = '', timestamp: bool = True):
108
+ """Prints a warning message with a yellow background."""
109
+ Console._print_with_background("WARNING", ANSIColors.BG_WARNING, message, timestamp)
110
+
111
+ @staticmethod
112
+ def textWarning(message: str = ''):
113
+ """Prints a warning message in yellow."""
114
+ Console._print_colored(message, ANSIColors.TEXT_WARNING)
115
+
116
+ @staticmethod
117
+ def textWarningBold(message: str = ''):
118
+ """Prints a bold warning message in yellow."""
119
+ Console._print_colored(message, ANSIColors.TEXT_BOLD_WARNING)
120
+
121
+ # ---- FAIL ----
122
+
123
+ @staticmethod
124
+ def fail(message: str = '', timestamp: bool = True):
125
+ """Prints an fail message with a red background."""
126
+ Console._print_with_background("FAIL", ANSIColors.BG_FAIL, message, timestamp)
127
+
128
+ # ---- ERROR ----
129
+
130
+ @staticmethod
131
+ def error(message: str = '', timestamp: bool = True):
132
+ """Prints an error message with a red background."""
133
+ Console._print_with_background("ERROR", ANSIColors.BG_ERROR, message, timestamp)
134
+
135
+ @staticmethod
136
+ def textError(message: str = ''):
137
+ """Prints an error message in red."""
138
+ Console._print_colored(message, ANSIColors.TEXT_ERROR)
139
+
140
+ @staticmethod
141
+ def textErrorBold(message: str = ''):
142
+ """Prints a bold error message in red."""
143
+ Console._print_colored(message, ANSIColors.TEXT_BOLD_ERROR)
144
+
145
+ # ---- MUTED ----
146
+
147
+ @staticmethod
148
+ def textMuted(message: str = ''):
149
+ """Prints a muted (gray) message."""
150
+ Console._print_colored(message, ANSIColors.TEXT_MUTED)
151
+
152
+ @staticmethod
153
+ def textMutedBold(message: str = ''):
154
+ """Prints a bold muted (gray) message."""
155
+ Console._print_colored(message, ANSIColors.TEXT_BOLD_MUTED)
156
+
157
+ # ---- UNDERLINE ----
158
+
159
+ @staticmethod
160
+ def textUnderline(message: str = ''):
161
+ """
162
+ Prints an underlined message.
163
+
164
+ Parameters
165
+ ----------
166
+ message : str, optional
167
+ The message to print (default is '').
168
+ """
169
+ print(f"{ANSIColors.TEXT_STYLE_UNDERLINE.value}{message}{ANSIColors.DEFAULT.value}")
170
+
171
+ # ---- CLEAR CONSOLE ----
172
+
173
+ @staticmethod
174
+ def clear():
175
+ """Clears the console screen."""
176
+ os.system('cls' if os.name == 'nt' else 'clear')
177
+
178
+ @staticmethod
179
+ def clearLine():
180
+ """Clears the current console line."""
181
+ sys.stdout.write("\r \r")
182
+ sys.stdout.flush()
183
+
184
+ # ---- EMPTY LINE CONSOLE ----
185
+
186
+ @staticmethod
187
+ def line(message: str = ''):
188
+ """Prints a line of text."""
189
+ print(message)
190
+
191
+ @staticmethod
192
+ def newLine(count: int = 1):
193
+ """
194
+ Prints multiple new lines.
195
+
196
+ Parameters
197
+ ----------
198
+ count : int, optional
199
+ The number of new lines to print (default is 1).
200
+
201
+ Raises
202
+ ------
203
+ ValueError
204
+ If count is less than or equal to 0.
205
+ """
206
+ if count <= 0:
207
+ raise ValueError(f"Unsupported Value '{count}'")
208
+ print("\n" * count, end="")
209
+
210
+ # ---- WRITE CONSOLE ----
211
+
212
+ @staticmethod
213
+ def write(message: str = ''):
214
+ """
215
+ Prints a message without moving to the next line.
216
+
217
+ Parameters
218
+ ----------
219
+ message : str, optional
220
+ The message to print (default is '').
221
+ """
222
+ sys.stdout.write(f"{message}")
223
+ sys.stdout.flush()
224
+
225
+ @staticmethod
226
+ def writeLine(message: str = ''):
227
+ """
228
+ Prints a message and moves to the next line.
229
+
230
+ Parameters
231
+ ----------
232
+ message : str, optional
233
+ The message to print (default is '').
234
+ """
235
+ print(f"{message}")
236
+
237
+ @staticmethod
238
+ def ask(question: str) -> str:
239
+ """
240
+ Prompts the user for input with a message and returns the user's response.
241
+
242
+ Parameters
243
+ ----------
244
+ question : str
245
+ The question to ask the user.
246
+
247
+ Returns
248
+ -------
249
+ str
250
+ The user's input, as a string.
251
+ """
252
+ return input(f"{ANSIColors.TEXT_INFO.value}{str(question).strip()}{ANSIColors.DEFAULT.value} ")
253
+
254
+ @staticmethod
255
+ def confirm(question: str, default: bool = False) -> bool:
256
+ """
257
+ Asks a confirmation question and returns True or False based on the user's response.
258
+
259
+ Parameters
260
+ ----------
261
+ question : str
262
+ The confirmation question to ask.
263
+ default : bool, optional
264
+ The default response if the user presses Enter without typing a response.
265
+ Default is False, which corresponds to a 'No' response.
266
+
267
+ Returns
268
+ -------
269
+ bool
270
+ The user's response, which will be True if 'Y' is entered,
271
+ or False if 'N' is entered or the default is used.
272
+ """
273
+ response = input(f"{ANSIColors.TEXT_INFO.value}{str(question).strip()} (Y/n): {ANSIColors.DEFAULT.value} ").upper()
274
+ return default if not response else response == 'Y'
275
+
276
+ @staticmethod
277
+ def secret(question: str) -> str:
278
+ """
279
+ Prompts the user for hidden input, typically used for password input.
280
+
281
+ Parameters
282
+ ----------
283
+ question : str
284
+ The prompt to ask the user.
285
+
286
+ Returns
287
+ -------
288
+ str
289
+ The user's hidden input, returned as a string.
290
+ """
291
+ return getpass.getpass(f"{ANSIColors.TEXT_INFO.value}{str(question).strip()}{ANSIColors.DEFAULT.value} ")
292
+
293
+ @staticmethod
294
+ def table(headers: list, rows: list):
295
+ """
296
+ Prints a table in the console with the given headers and rows, with bold headers.
297
+
298
+ Parameters
299
+ ----------
300
+ headers : list of str
301
+ The column headers for the table.
302
+ rows : list of list of str
303
+ The rows of the table, where each row is a list of strings representing the columns.
304
+
305
+ Raises
306
+ ------
307
+ ValueError
308
+ If headers or rows are empty.
309
+
310
+ Notes
311
+ -----
312
+ The table adjusts column widths dynamically, includes bold headers, and uses box-drawing characters for formatting.
313
+ """
314
+ if not headers:
315
+ raise ValueError("Headers cannot be empty.")
316
+ if not rows:
317
+ raise ValueError("Rows cannot be empty.")
318
+
319
+ # Determine the maximum width of each column
320
+ col_widths = [max(len(str(item)) for item in col) for col in zip(headers, *rows)]
321
+
322
+ # Define border characters
323
+ top_border = "┌" + "┬".join("─" * (col_width + 2) for col_width in col_widths) + "┐"
324
+ separator = "├" + "┼".join("─" * (col_width + 2) for col_width in col_widths) + "┤"
325
+ bottom_border = "└" + "┴".join("─" * (col_width + 2) for col_width in col_widths) + "┘"
326
+
327
+ # Format the header row with bold text
328
+ header_row = "│ " + " │ ".join(f"{ANSIColors.TEXT_BOLD.value}{header:<{col_width}}{ANSIColors.TEXT_RESET.value}" for header, col_width in zip(headers, col_widths)) + " │"
329
+
330
+ # Print the table
331
+ print(top_border)
332
+ print(header_row)
333
+ print(separator)
334
+
335
+ for row in rows:
336
+ row_text = "│ " + " │ ".join(f"{str(item):<{col_width}}" for item, col_width in zip(row, col_widths)) + " │"
337
+ print(row_text)
338
+
339
+ print(bottom_border)
340
+
341
+ @staticmethod
342
+ def anticipate(question: str, options: list, default=None):
343
+ """
344
+ Provides autocomplete suggestions based on user input.
345
+
346
+ Parameters
347
+ ----------
348
+ question : str
349
+ The prompt for the user.
350
+ options : list of str
351
+ The list of possible options for autocomplete.
352
+ default : str, optional
353
+ The default value if no matching option is found. Defaults to None.
354
+
355
+ Returns
356
+ -------
357
+ str
358
+ The chosen option or the default value.
359
+
360
+ Notes
361
+ -----
362
+ This method allows the user to input a string, and then attempts to provide
363
+ an autocomplete suggestion by matching the beginning of the input with the
364
+ available options. If no match is found, the method returns the default value
365
+ or the user input if no default is provided.
366
+ """
367
+ # Prompt the user for input
368
+ input_value = input(f"{ANSIColors.TEXT_INFO.value}{str(question).strip()}{ANSIColors.DEFAULT.value} ")
369
+
370
+ # Find the first option that starts with the input value, or use the default value
371
+ return next((option for option in options if option.startswith(input_value)), default or input_value)
372
+
373
+ @staticmethod
374
+ def choice(question: str, choices: list, default_index: int = 0) -> str:
375
+ """
376
+ Allows the user to select an option from a list.
377
+
378
+ Parameters
379
+ ----------
380
+ question : str
381
+ The prompt for the user.
382
+ choices : list of str
383
+ The list of available choices.
384
+ default_index : int, optional
385
+ The index of the default choice (zero-based). Defaults to 0.
386
+
387
+ Returns
388
+ -------
389
+ str
390
+ The selected choice.
391
+
392
+ Raises
393
+ ------
394
+ ValueError
395
+ If `default_index` is out of the range of choices.
396
+
397
+ Notes
398
+ -----
399
+ The user is presented with a numbered list of choices and prompted to select
400
+ one by entering the corresponding number. If an invalid input is provided,
401
+ the user will be repeatedly prompted until a valid choice is made.
402
+ """
403
+ if not choices:
404
+ raise ValueError("The choices list cannot be empty.")
405
+
406
+ if not (0 <= default_index < len(choices)):
407
+ raise ValueError(f"Invalid default_index {default_index}. Must be between 0 and {len(choices) - 1}.")
408
+
409
+ # Display the question and the choices
410
+ print(f"{ANSIColors.TEXT_INFO.value}{question.strip()} (default: {choices[default_index]}):{ANSIColors.DEFAULT.value}")
411
+
412
+ for idx, choice in enumerate(choices, 1):
413
+ print(f"{ANSIColors.TEXT_MUTED.value}{idx}: {choice}{ANSIColors.DEFAULT.value}")
414
+
415
+ # Prompt the user for input
416
+ answer = input("Answer: ").strip()
417
+
418
+ # If the user provides no input, select the default choice
419
+ if not answer:
420
+ return choices[default_index]
421
+
422
+ # Validate input: ensure it's a number within range
423
+ while not answer.isdigit() or not (1 <= int(answer) <= len(choices)):
424
+ answer = input("Please select a valid number: ").strip()
425
+
426
+ return choices[int(answer) - 1]
@@ -0,0 +1,90 @@
1
+ from datetime import datetime
2
+ from orionis.luminate.console.output.styles import ANSIColors
3
+ from orionis.luminate.contracts.console.executor_interface import IExecutor
4
+
5
+ class Executor(IExecutor):
6
+ """
7
+ A utility class for logging program execution states with ANSI color formatting.
8
+
9
+ Methods
10
+ -------
11
+ running(program: str, time: str = ''):
12
+ Logs the execution of a program in a "RUNNING" state.
13
+ done(program: str, time: str = ''):
14
+ Logs the execution of a program in a "DONE" state.
15
+ fail(program: str, time: str = ''):
16
+ Logs the execution of a program in a "FAIL" state.
17
+ """
18
+
19
+ @staticmethod
20
+ def _ansi_output(program: str, state: str, state_color: str, time: str = ''):
21
+ """
22
+ Logs a formatted message with timestamp, program name, and execution state.
23
+
24
+ Parameters
25
+ ----------
26
+ program : str
27
+ The name of the program being executed.
28
+ state : str
29
+ The state of execution (e.g., RUNNING, DONE, FAIL).
30
+ state_color : str
31
+ The ANSI color code for the state.
32
+ time : str, optional
33
+ The time duration of execution, default is an empty string, example (30s)
34
+ """
35
+ width = 60
36
+ len_state = len(state)
37
+ len_time = len(time)
38
+ line = '.' * (width - (len(program) + len_state + len_time))
39
+
40
+ timestamp = f"{ANSIColors.TEXT_MUTED.value}{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}{ANSIColors.DEFAULT.value}"
41
+ program_formatted = f"{program}"
42
+ time_formatted = f"{ANSIColors.TEXT_MUTED.value}{time}{ANSIColors.DEFAULT.value}" if time else ""
43
+ state_formatted = f"{state_color}{state}{ANSIColors.DEFAULT.value}"
44
+
45
+ start = "\n\r" if state == 'RUNNING' else ''
46
+ end = "\n\r" if state != 'RUNNING' else ''
47
+
48
+ print(f"{start}{timestamp} | {program_formatted} {line} {time_formatted} {state_formatted}{end}")
49
+
50
+ @staticmethod
51
+ def running(program: str, time: str = ''):
52
+ """
53
+ Logs the execution of a program in a "RUNNING" state.
54
+
55
+ Parameters
56
+ ----------
57
+ program : str
58
+ The name of the program being executed.
59
+ time : str, optional
60
+ The time duration of execution, default is an empty string.
61
+ """
62
+ Executor._ansi_output(program, "RUNNING", ANSIColors.TEXT_BOLD_WARNING.value, time)
63
+
64
+ @staticmethod
65
+ def done(program: str, time: str = ''):
66
+ """
67
+ Logs the execution of a program in a "DONE" state.
68
+
69
+ Parameters
70
+ ----------
71
+ program : str
72
+ The name of the program being executed.
73
+ time : str, optional
74
+ The time duration of execution, default is an empty string.
75
+ """
76
+ Executor._ansi_output(program, "DONE", ANSIColors.TEXT_BOLD_SUCCESS.value, time)
77
+
78
+ @staticmethod
79
+ def fail(program: str, time: str = ''):
80
+ """
81
+ Logs the execution of a program in a "FAIL" state.
82
+
83
+ Parameters
84
+ ----------
85
+ program : str
86
+ The name of the program being executed.
87
+ time : str, optional
88
+ The time duration of execution, default is an empty string.
89
+ """
90
+ Executor._ansi_output(program, "FAIL", ANSIColors.TEXT_BOLD_ERROR.value, time)
@@ -0,0 +1,100 @@
1
+ import sys
2
+ from orionis.luminate.contracts.console.progress_bar_interface import IProgressBar
3
+
4
+ class ProgressBar(IProgressBar):
5
+ """
6
+ A console-based progress bar implementation.
7
+
8
+ This class provides a simple text-based progress bar that updates
9
+ in place without clearing the console.
10
+
11
+ Parameters
12
+ ----------
13
+ total : int, optional
14
+ The total amount of progress (default is 100).
15
+ width : int, optional
16
+ The width of the progress bar in characters (default is 50).
17
+
18
+ Attributes
19
+ ----------
20
+ total : int
21
+ The maximum progress value.
22
+ bar_width : int
23
+ The width of the progress bar in characters.
24
+ progress : int
25
+ The current progress value.
26
+
27
+ Methods
28
+ -------
29
+ start()
30
+ Initializes the progress bar to the starting state.
31
+ advance(increment=1)
32
+ Advances the progress bar by a given increment.
33
+ finish()
34
+ Completes the progress bar and moves to a new line.
35
+ """
36
+
37
+ def __init__(self, total=100, width=50):
38
+ """
39
+ Constructs all the necessary attributes for the progress bar object.
40
+
41
+ Parameters
42
+ ----------
43
+ total : int, optional
44
+ The total amount of progress (default is 100).
45
+ width : int, optional
46
+ The width of the progress bar in characters (default is 50).
47
+ """
48
+ self.total = total
49
+ self.bar_width = width
50
+ self.progress = 0
51
+
52
+ def _update_bar(self):
53
+ """
54
+ Updates the visual representation of the progress bar.
55
+
56
+ This method calculates the percentage of progress and updates the
57
+ console output accordingly.
58
+ """
59
+ percent = self.progress / self.total
60
+ filled_length = int(self.bar_width * percent)
61
+ bar = f"[{'█' * filled_length}{'░' * (self.bar_width - filled_length)}] {int(percent * 100)}%"
62
+
63
+ # Move the cursor to the start of the line and overwrite it
64
+ sys.stdout.write("\r" + bar)
65
+ sys.stdout.flush()
66
+
67
+ def start(self):
68
+ """
69
+ Initializes the progress bar to the starting state.
70
+
71
+ This method resets the progress to zero and displays the initial bar.
72
+ """
73
+ self.progress = 0
74
+ self._update_bar()
75
+
76
+ def advance(self, increment=1):
77
+ """
78
+ Advances the progress bar by a specific increment.
79
+
80
+ Parameters
81
+ ----------
82
+ increment : int, optional
83
+ The amount by which the progress should be increased (default is 1).
84
+ """
85
+ self.progress += increment
86
+ if self.progress > self.total:
87
+ self.progress = self.total
88
+ self._update_bar()
89
+
90
+ def finish(self):
91
+ """
92
+ Completes the progress bar.
93
+
94
+ This method sets the progress to its maximum value, updates the bar,
95
+ and moves the cursor to a new line for cleaner output.
96
+ """
97
+ self.progress = self.total
98
+ self._update_bar()
99
+ sys.stdout.write("\n")
100
+ sys.stdout.flush()