orionis 0.246.0__py3-none-any.whl → 0.247.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.
- orionis/framework.py +1 -1
- orionis/luminate/config/app/__init__.py +10 -0
- orionis/luminate/config/app/entities/app.py +205 -0
- orionis/luminate/config/app/enums/ciphers.py +34 -0
- orionis/luminate/config/app/enums/environments.py +15 -0
- orionis/luminate/config/auth/__init__.py +7 -0
- orionis/luminate/config/auth/entities/auth.py +11 -0
- orionis/luminate/config/cache/__init__.py +9 -0
- orionis/luminate/config/cache/entities/cache.py +58 -0
- orionis/luminate/config/cache/entities/file.py +29 -0
- orionis/luminate/config/cache/entities/stores.py +35 -0
- orionis/luminate/config/cache/enums/drivers.py +12 -0
- orionis/luminate/config/entities/testing.py +192 -14
- orionis/luminate/config/exceptions/integrity_exception.py +30 -0
- orionis/luminate/console/dumper/dump_die.py +418 -0
- orionis/luminate/contracts/facades/commands/scheduler_facade.py +1 -1
- orionis/luminate/facades/files/path_facade.py +1 -1
- orionis/luminate/patterns/__init__.py +4 -0
- orionis/luminate/patterns/singleton/__init__.py +10 -0
- orionis/luminate/patterns/singleton/meta_class.py +56 -0
- orionis/luminate/providers/commands/reactor_commands_service_provider.py +3 -3
- orionis/luminate/providers/commands/scheduler_provider.py +1 -1
- orionis/luminate/providers/config/config_service_provider.py +1 -1
- orionis/luminate/providers/environment/environment__service_provider.py +2 -2
- orionis/luminate/providers/files/paths_provider.py +1 -1
- orionis/luminate/providers/log/log_service_provider.py +2 -2
- orionis/luminate/services/environment/__init__.py +10 -0
- orionis/luminate/services/environment/contracts/__init__.py +5 -0
- orionis/luminate/services/environment/contracts/env.py +93 -0
- orionis/luminate/services/environment/dot_env.py +293 -0
- orionis/luminate/services/environment/env.py +77 -0
- orionis/luminate/services/paths/__init__.py +9 -0
- orionis/luminate/services/paths/contracts/resolver.py +67 -0
- orionis/luminate/services/paths/resolver.py +83 -0
- orionis/luminate/services/workers/__init__.py +10 -0
- orionis/luminate/services/workers/maximum_workers.py +36 -0
- orionis/luminate/services_/commands/__init__.py +0 -0
- orionis/luminate/services_/config/__init__.py +0 -0
- orionis/luminate/services_/log/__init__.py +0 -0
- orionis/luminate/test/__init__.py +11 -1
- orionis/luminate/test/cases/test_async.py +1 -10
- orionis/luminate/test/cases/test_case.py +8 -3
- orionis/luminate/test/cases/test_sync.py +1 -0
- orionis/luminate/test/core/contracts/test_suite.py +19 -31
- orionis/luminate/test/core/contracts/test_unit.py +4 -0
- orionis/luminate/test/core/test_suite.py +27 -26
- orionis/luminate/test/core/test_unit.py +28 -45
- orionis/luminate/test/entities/test_result.py +13 -16
- orionis/luminate/test/exceptions/test_exception.py +1 -1
- orionis/luminate/test/output/contracts/test_std_out.py +22 -11
- orionis/luminate/test/output/test_std_out.py +69 -80
- {orionis-0.246.0.dist-info → orionis-0.247.0.dist-info}/METADATA +4 -1
- {orionis-0.246.0.dist-info → orionis-0.247.0.dist-info}/RECORD +80 -51
- tests/config/__init__.py +0 -0
- tests/config/test_app.py +122 -0
- tests/config/test_auth.py +21 -0
- tests/config/test_cache.py +20 -0
- tests/patterns/__init__.py +0 -0
- tests/patterns/singleton/__init__.py +0 -0
- tests/patterns/singleton/test_singleton.py +18 -0
- tests/services/__init__.py +0 -0
- tests/services/environment/__init__.py +0 -0
- tests/services/environment/test_env.py +33 -0
- orionis/luminate/config/entities/app.py +0 -47
- orionis/luminate/config/entities/auth.py +0 -15
- orionis/luminate/config/entities/cache.py +0 -51
- orionis/luminate/support/environment/contracts/env.py +0 -68
- orionis/luminate/support/environment/env.py +0 -139
- orionis/luminate/support/environment/functions.py +0 -49
- orionis/luminate/support/environment/helper.py +0 -26
- orionis/luminate/support/patterns/singleton.py +0 -44
- tests/support/environment/test_env.py +0 -91
- tests/support/patterns/test_singleton.py +0 -18
- /orionis/luminate/config/{entities → app/entities}/__init__.py +0 -0
- /orionis/luminate/{services/commands → config/app/enums}/__init__.py +0 -0
- /orionis/luminate/{services/config → config/auth/entities}/__init__.py +0 -0
- /orionis/luminate/{services/log → config/cache/entities}/__init__.py +0 -0
- /orionis/luminate/{support/environment → config/cache/enums}/__init__.py +0 -0
- /orionis/luminate/{support/environment/contracts → config/exceptions}/__init__.py +0 -0
- /orionis/luminate/{support/patterns → console/dumper}/__init__.py +0 -0
- {tests/support/environment → orionis/luminate/services/paths/contracts}/__init__.py +0 -0
- {tests/support/patterns → orionis/luminate/services_}/__init__.py +0 -0
- /orionis/luminate/{services → services_}/commands/reactor_commands_service.py +0 -0
- /orionis/luminate/{services → services_}/commands/scheduler_service.py +0 -0
- /orionis/luminate/{services → services_}/config/config_service.py +0 -0
- /orionis/luminate/{services → services_}/log/log_service.py +0 -0
- {orionis-0.246.0.dist-info → orionis-0.247.0.dist-info}/LICENCE +0 -0
- {orionis-0.246.0.dist-info → orionis-0.247.0.dist-info}/WHEEL +0 -0
- {orionis-0.246.0.dist-info → orionis-0.247.0.dist-info}/entry_points.txt +0 -0
- {orionis-0.246.0.dist-info → orionis-0.247.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
class OrionisIntegrityException(Exception):
|
2
|
+
"""
|
3
|
+
Exception raised for integrity-related errors within the Orionis framework configuration.
|
4
|
+
This exception is intended to signal issues or inconsistencies detected in the test configuration,
|
5
|
+
helping developers quickly identify and resolve configuration problems. It provides a clear,
|
6
|
+
contextual error message to facilitate debugging and maintain the integrity of the framework's setup.
|
7
|
+
Attributes:
|
8
|
+
msg (str): Human-readable description of the integrity error.
|
9
|
+
Example:
|
10
|
+
raise OrionisIntegrityException("Duplicate test case identifier found in configuration.")
|
11
|
+
msg (str): Detailed explanation of the integrity violation encountered.
|
12
|
+
"""
|
13
|
+
|
14
|
+
def __init__(self, msg: str):
|
15
|
+
"""
|
16
|
+
Initializes the exception with a custom error message.
|
17
|
+
|
18
|
+
Args:
|
19
|
+
msg (str): The error message describing the exception.
|
20
|
+
"""
|
21
|
+
super().__init__(msg)
|
22
|
+
|
23
|
+
def __str__(self) -> str:
|
24
|
+
"""
|
25
|
+
Return a string representation of the exception, including the class name and the first argument.
|
26
|
+
|
27
|
+
Returns:
|
28
|
+
str: A string in the format '<ClassName>: <first argument>'.
|
29
|
+
"""
|
30
|
+
return f"{self.__class__.__name__}: {self.args[0]}"
|
@@ -0,0 +1,418 @@
|
|
1
|
+
import os
|
2
|
+
import sys
|
3
|
+
import inspect
|
4
|
+
import json
|
5
|
+
from typing import Any
|
6
|
+
from datetime import datetime
|
7
|
+
from dataclasses import is_dataclass
|
8
|
+
from rich.console import Console
|
9
|
+
from rich.panel import Panel
|
10
|
+
from rich.table import Table
|
11
|
+
from rich.syntax import Syntax
|
12
|
+
from rich.traceback import install
|
13
|
+
|
14
|
+
class Debug:
|
15
|
+
"""
|
16
|
+
Debugging utility class for enhanced output and inspection of Python objects.
|
17
|
+
This class provides methods for dumping and inspecting data in various formats,
|
18
|
+
including plain text, JSON, and tabular representations. It also supports
|
19
|
+
rendering nested structures with recursion handling and customizable indentation.
|
20
|
+
"""
|
21
|
+
|
22
|
+
def __init__(self, line:str = None) -> None:
|
23
|
+
"""
|
24
|
+
Initializes the class instance.
|
25
|
+
|
26
|
+
This constructor sets up the necessary components for the class, including:
|
27
|
+
- Installing required dependencies or configurations.
|
28
|
+
- Initializing a console for output handling.
|
29
|
+
- Setting the default indentation size for formatting.
|
30
|
+
- Creating a set to guard against recursion during operations.
|
31
|
+
"""
|
32
|
+
install()
|
33
|
+
self.console = Console()
|
34
|
+
self.indent_size = 4
|
35
|
+
self._recursion_guard = set()
|
36
|
+
self.line_tcbk = line
|
37
|
+
|
38
|
+
def dd(self, *args: Any) -> None:
|
39
|
+
"""
|
40
|
+
Dumps the provided arguments to the output and exits the program.
|
41
|
+
|
42
|
+
Args:
|
43
|
+
*args (Any): Variable length argument list to be processed and output.
|
44
|
+
|
45
|
+
Returns:
|
46
|
+
None
|
47
|
+
"""
|
48
|
+
self.__processOutput(*args, exit_after=True)
|
49
|
+
|
50
|
+
def dump(self, *args: Any) -> None:
|
51
|
+
"""
|
52
|
+
Dumps the provided arguments for debugging or logging purposes.
|
53
|
+
|
54
|
+
Args:
|
55
|
+
*args (Any): Variable length argument list to be processed and output.
|
56
|
+
|
57
|
+
Returns:
|
58
|
+
None
|
59
|
+
"""
|
60
|
+
self.__processOutput(*args, exit_after=False)
|
61
|
+
|
62
|
+
def __processOutput(self, *args: Any, exit_after: bool) -> None:
|
63
|
+
"""
|
64
|
+
Processes the output based on the provided arguments and determines the appropriate
|
65
|
+
format for displaying the data (tabular, JSON, or raw dump). Handles exceptions
|
66
|
+
during processing and optionally exits the program.
|
67
|
+
|
68
|
+
Args:
|
69
|
+
*args (Any): Variable-length arguments representing the data to be processed.
|
70
|
+
exit_after (bool): If True, the program will exit after processing the output.
|
71
|
+
|
72
|
+
Raises:
|
73
|
+
Exception: Catches and logs any exception that occurs during processing. If
|
74
|
+
`exit_after` is True, the program will terminate with an exit code of 1.
|
75
|
+
"""
|
76
|
+
try:
|
77
|
+
if not args:
|
78
|
+
raise ValueError("No arguments were provided, or the arguments are null or invalid")
|
79
|
+
elif len(args) == 1:
|
80
|
+
arg = args[0]
|
81
|
+
if self.__isJsonSerializable(arg) and self.__isTabular(arg) and isinstance(arg, (list)):
|
82
|
+
self.__printTable(arg)
|
83
|
+
elif self.__isJsonSerializable(arg):
|
84
|
+
self.__printJson(arg)
|
85
|
+
else:
|
86
|
+
self.__printDump(args)
|
87
|
+
else:
|
88
|
+
self.__printDump(args)
|
89
|
+
except Exception as e:
|
90
|
+
self.__printStandardPanel(
|
91
|
+
f"[bold red]An error occurred while processing the debug output: {str(e)}[/]",
|
92
|
+
border_style="red",
|
93
|
+
)
|
94
|
+
finally:
|
95
|
+
if exit_after:
|
96
|
+
os._exit(1)
|
97
|
+
|
98
|
+
def __printDump(self, args: tuple) -> None:
|
99
|
+
"""
|
100
|
+
Prints a formatted dump of the provided arguments to the console and optionally exits the program.
|
101
|
+
Args:
|
102
|
+
args (tuple): A tuple containing the objects to be dumped and displayed.
|
103
|
+
Returns:
|
104
|
+
None
|
105
|
+
"""
|
106
|
+
content = []
|
107
|
+
for arg in args:
|
108
|
+
self._recursion_guard.clear()
|
109
|
+
content.append(self.__render(arg))
|
110
|
+
|
111
|
+
self.__printStandardPanel(
|
112
|
+
Syntax(
|
113
|
+
"\n".join(content),
|
114
|
+
"python",
|
115
|
+
line_numbers=False,
|
116
|
+
background_color="default",
|
117
|
+
word_wrap=True
|
118
|
+
),
|
119
|
+
border_style="cyan bold",
|
120
|
+
)
|
121
|
+
|
122
|
+
def __printJson(self, data: Any) -> None:
|
123
|
+
"""
|
124
|
+
Prints a JSON representation of the given data to the console using a styled panel.
|
125
|
+
Args:
|
126
|
+
data (Any): The data to be serialized and displayed as JSON.
|
127
|
+
Raises:
|
128
|
+
TypeError: If the data cannot be serialized to JSON, falls back to a generic dump method.
|
129
|
+
Notes:
|
130
|
+
- Uses the `rich` library to format and display the JSON output with syntax highlighting.
|
131
|
+
- Retrieves and displays the caller's line information for context.
|
132
|
+
- Handles non-serializable objects using a custom JSON serializer.
|
133
|
+
"""
|
134
|
+
try:
|
135
|
+
if not isinstance(data, (dict, list)):
|
136
|
+
raise TypeError("Data must be a dictionary or a list for JSON serialization.")
|
137
|
+
|
138
|
+
json_str = json.dumps(data, ensure_ascii=False, indent=2, default=self.__jsonSerializer)
|
139
|
+
self.__printStandardPanel(
|
140
|
+
Syntax(
|
141
|
+
json_str,
|
142
|
+
"json",
|
143
|
+
line_numbers=True,
|
144
|
+
background_color="default",
|
145
|
+
word_wrap=True
|
146
|
+
),
|
147
|
+
border_style="green",
|
148
|
+
)
|
149
|
+
except TypeError as e:
|
150
|
+
self.__printDump((data,))
|
151
|
+
|
152
|
+
def __printTable(self, data: Any) -> None:
|
153
|
+
"""
|
154
|
+
Prints a formatted table representation of the given data using the `rich` library.
|
155
|
+
Args:
|
156
|
+
data (Any): The data to be displayed in the table. It can be a list, dictionary,
|
157
|
+
or an object with attributes.
|
158
|
+
Behavior:
|
159
|
+
- If `data` is a list:
|
160
|
+
- If the list is empty, prints a message indicating an empty list.
|
161
|
+
- If the list contains dictionaries, uses the dictionary keys as column headers.
|
162
|
+
- If the list contains objects with attributes, uses the attribute names as column headers.
|
163
|
+
- Otherwise, displays the index and value of each item in the list.
|
164
|
+
- If `data` is a dictionary:
|
165
|
+
- Displays the keys and values as two columns.
|
166
|
+
- If an exception occurs during processing, calls `__printDump` to handle the error.
|
167
|
+
Note:
|
168
|
+
This method relies on the `rich.Table` class for rendering the table and assumes
|
169
|
+
the presence of a `console` object for output and a `__printStandardPanel` method
|
170
|
+
for displaying the table with a border.
|
171
|
+
"""
|
172
|
+
try:
|
173
|
+
table = Table(
|
174
|
+
show_header=True,
|
175
|
+
header_style="bold white on blue",
|
176
|
+
min_width=(self.console.width // 4) * 3
|
177
|
+
)
|
178
|
+
|
179
|
+
if isinstance(data, list):
|
180
|
+
if not data:
|
181
|
+
self.console.print("[yellow]Empty list[/]")
|
182
|
+
return
|
183
|
+
|
184
|
+
first = data[0]
|
185
|
+
if isinstance(first, dict):
|
186
|
+
columns = list(first.keys())
|
187
|
+
elif hasattr(first, '__dict__'):
|
188
|
+
columns = list(vars(first).keys())
|
189
|
+
else:
|
190
|
+
columns = ["Index", "Value"]
|
191
|
+
|
192
|
+
for col in columns:
|
193
|
+
table.add_column(str(col))
|
194
|
+
|
195
|
+
for i, item in enumerate(data):
|
196
|
+
if isinstance(item, dict):
|
197
|
+
table.add_row(*[str(item.get(col, '')) for col in columns])
|
198
|
+
elif hasattr(item, '__dict__'):
|
199
|
+
item_dict = vars(item)
|
200
|
+
table.add_row(*[str(item_dict.get(col, '')) for col in columns])
|
201
|
+
else:
|
202
|
+
table.add_row(str(i), str(item))
|
203
|
+
|
204
|
+
elif isinstance(data, dict):
|
205
|
+
table.add_column("Key", style="magenta")
|
206
|
+
table.add_column("Value")
|
207
|
+
|
208
|
+
for k, v in data.items():
|
209
|
+
table.add_row(str(k), str(v))
|
210
|
+
|
211
|
+
self.__printStandardPanel(
|
212
|
+
table,
|
213
|
+
border_style="blue",
|
214
|
+
)
|
215
|
+
except Exception as e:
|
216
|
+
self.__printDump((data,))
|
217
|
+
|
218
|
+
def __printStandardPanel(self, renderable, border_style: str, padding=(0, 1)) -> None:
|
219
|
+
"""
|
220
|
+
Renders a standard panel with the given content and styling options.
|
221
|
+
Args:
|
222
|
+
renderable: The content to be displayed inside the panel. This can be any renderable object.
|
223
|
+
border_style (str): The style of the border for the panel.
|
224
|
+
padding (tuple, optional): A tuple specifying the padding inside the panel as (vertical, horizontal). Defaults to (0, 0).
|
225
|
+
expand (bool, optional): Whether the panel should expand to fill available space. Defaults to False.
|
226
|
+
Returns:
|
227
|
+
None
|
228
|
+
"""
|
229
|
+
if self.line_tcbk is None:
|
230
|
+
frame = inspect.currentframe()
|
231
|
+
caller_frame = frame.f_back.f_back if frame else None
|
232
|
+
line_info = f"[blue underline]{self.__getLineInfo(caller_frame) if caller_frame else 'Unknown location'}[/]"
|
233
|
+
else:
|
234
|
+
line_info = f"[blue underline]{self.line_tcbk}[/]"
|
235
|
+
|
236
|
+
subtitle = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
237
|
+
|
238
|
+
self.console.print()
|
239
|
+
self.console.print(Panel(
|
240
|
+
renderable,
|
241
|
+
title=f"Debugger - {line_info}",
|
242
|
+
title_align='left',
|
243
|
+
subtitle=subtitle,
|
244
|
+
subtitle_align='right',
|
245
|
+
border_style=border_style,
|
246
|
+
highlight=True,
|
247
|
+
padding=padding,
|
248
|
+
width=(self.console.width // 4) * 3,
|
249
|
+
))
|
250
|
+
self.console.print()
|
251
|
+
|
252
|
+
def __isTabular(self, data: Any) -> bool:
|
253
|
+
"""
|
254
|
+
Determines if the given data is in a tabular format.
|
255
|
+
|
256
|
+
A data structure is considered tabular if it is a list or a dictionary.
|
257
|
+
For lists, it further checks if the first element is either a dictionary
|
258
|
+
or an object with attributes (i.e., has a `__dict__` attribute).
|
259
|
+
|
260
|
+
Args:
|
261
|
+
data (Any): The data to be checked.
|
262
|
+
|
263
|
+
Returns:
|
264
|
+
bool: True if the data is tabular, False otherwise.
|
265
|
+
"""
|
266
|
+
|
267
|
+
if isinstance(data, list):
|
268
|
+
if all(isinstance(item, dict) for item in data):
|
269
|
+
keys = set(data[0].keys())
|
270
|
+
return all(set(item.keys()) == keys for item in data)
|
271
|
+
if len(data) > 0 and hasattr(data[0], '__dict__'):
|
272
|
+
return True
|
273
|
+
elif isinstance(data, dict):
|
274
|
+
return True
|
275
|
+
return False
|
276
|
+
|
277
|
+
def __isJsonSerializable(self, data: Any) -> bool:
|
278
|
+
"""
|
279
|
+
Determines if the given data is JSON serializable.
|
280
|
+
|
281
|
+
This method attempts to serialize the provided data into a JSON string
|
282
|
+
using a custom serializer. If the serialization succeeds, the data is
|
283
|
+
considered JSON serializable. Otherwise, it is not.
|
284
|
+
|
285
|
+
Args:
|
286
|
+
data (Any): The data to check for JSON serializability.
|
287
|
+
|
288
|
+
Returns:
|
289
|
+
bool: True if the data is JSON serializable, False otherwise.
|
290
|
+
"""
|
291
|
+
try:
|
292
|
+
json.dumps(data, default=self.__jsonSerializer)
|
293
|
+
return True
|
294
|
+
except (TypeError, OverflowError):
|
295
|
+
return False
|
296
|
+
|
297
|
+
def __render(self, value: Any, indent: int = 0, key: Any = None, depth: int = 0) -> str:
|
298
|
+
"""
|
299
|
+
Recursively renders a string representation of a given value with customizable indentation,
|
300
|
+
handling various data types, recursion, and depth limits.
|
301
|
+
Args:
|
302
|
+
value (Any): The value to render. Can be of any type, including dict, list, tuple, set,
|
303
|
+
dataclass, or objects with a `__dict__` attribute.
|
304
|
+
indent (int, optional): The current indentation level. Defaults to 0.
|
305
|
+
key (Any, optional): The key or index associated with the value, if applicable. Defaults to None.
|
306
|
+
depth (int, optional): The current recursion depth. Defaults to 0.
|
307
|
+
Returns:
|
308
|
+
str: A string representation of the value, formatted with indentation and type information.
|
309
|
+
Notes:
|
310
|
+
- Limits recursion depth to 10 to prevent infinite loops.
|
311
|
+
- Detects and handles recursive references to avoid infinite recursion.
|
312
|
+
- Supports rendering of common Python data structures, dataclasses, and objects with attributes.
|
313
|
+
- Formats datetime objects and callable objects with additional details.
|
314
|
+
"""
|
315
|
+
|
316
|
+
if depth > 10:
|
317
|
+
return "... (max depth)"
|
318
|
+
|
319
|
+
obj_id = id(value)
|
320
|
+
if obj_id in self._recursion_guard:
|
321
|
+
return "... (recursive)"
|
322
|
+
self._recursion_guard.add(obj_id)
|
323
|
+
|
324
|
+
space = ' ' * indent
|
325
|
+
prefix = f"{space}"
|
326
|
+
|
327
|
+
if key is not None:
|
328
|
+
prefix += f"{self.__formatKey(key)} => "
|
329
|
+
|
330
|
+
if value is None:
|
331
|
+
result = f"{prefix}None"
|
332
|
+
elif isinstance(value, dict):
|
333
|
+
result = f"{prefix}dict({len(value)})"
|
334
|
+
for k, v in value.items():
|
335
|
+
result += "\n" + self.__render(v, indent + self.indent_size, k, depth + 1)
|
336
|
+
elif isinstance(value, (list, tuple, set)):
|
337
|
+
type_name = type(value).__name__
|
338
|
+
result = f"{prefix}{type_name}({len(value)})"
|
339
|
+
for i, item in enumerate(value):
|
340
|
+
result += "\n" + self.__render(
|
341
|
+
item,
|
342
|
+
indent + self.indent_size,
|
343
|
+
i if isinstance(value, (list, tuple)) else None,
|
344
|
+
depth + 1
|
345
|
+
)
|
346
|
+
elif is_dataclass(value):
|
347
|
+
result = f"{prefix}{value.__class__.__name__}"
|
348
|
+
for k, v in vars(value).items():
|
349
|
+
result += "\n" + self.__render(v, indent + self.indent_size, k, depth + 1)
|
350
|
+
elif hasattr(value, "__dict__"):
|
351
|
+
result = f"{prefix}{value.__class__.__name__}"
|
352
|
+
for k, v in vars(value).items():
|
353
|
+
result += "\n" + self.__render(v, indent + self.indent_size, k, depth + 1)
|
354
|
+
elif isinstance(value, datetime):
|
355
|
+
result = f"{prefix}datetime({value.isoformat()})"
|
356
|
+
elif callable(value):
|
357
|
+
result = f"{prefix}callable({value.__name__ if hasattr(value, '__name__') else repr(value)})"
|
358
|
+
else:
|
359
|
+
result = f"{prefix}{type(value).__name__}({repr(value)})"
|
360
|
+
|
361
|
+
self._recursion_guard.discard(obj_id)
|
362
|
+
return result
|
363
|
+
|
364
|
+
@staticmethod
|
365
|
+
def __jsonSerializer(obj):
|
366
|
+
"""
|
367
|
+
Serialize an object into a JSON-compatible format.
|
368
|
+
Args:
|
369
|
+
obj: The object to serialize. Supported types include:
|
370
|
+
- datetime: Converted to ISO 8601 string format.
|
371
|
+
- Objects with a `__dict__` attribute: Converted to a dictionary of their attributes.
|
372
|
+
- set or tuple: Converted to a list.
|
373
|
+
Returns:
|
374
|
+
A JSON-serializable representation of the input object.
|
375
|
+
Raises:
|
376
|
+
TypeError: If the object type is not supported for JSON serialization.
|
377
|
+
"""
|
378
|
+
if isinstance(obj, datetime):
|
379
|
+
return obj.isoformat()
|
380
|
+
elif hasattr(obj, '__dict__'):
|
381
|
+
return vars(obj)
|
382
|
+
elif isinstance(obj, (set, tuple)):
|
383
|
+
return list(obj)
|
384
|
+
raise TypeError(f"Object of type {obj.__class__.__name__} is not JSON serializable")
|
385
|
+
|
386
|
+
@staticmethod
|
387
|
+
def __formatKey(key: Any) -> str:
|
388
|
+
"""
|
389
|
+
Formats a given key into a string representation.
|
390
|
+
|
391
|
+
Args:
|
392
|
+
key (Any): The key to be formatted. It can be of any type.
|
393
|
+
|
394
|
+
Returns:
|
395
|
+
str: A string representation of the key. If the key is a string, it is
|
396
|
+
enclosed in double quotes. Otherwise, the string representation of the
|
397
|
+
key is returned as-is.
|
398
|
+
"""
|
399
|
+
if isinstance(key, str):
|
400
|
+
return f'"{key}"'
|
401
|
+
return str(key)
|
402
|
+
|
403
|
+
@staticmethod
|
404
|
+
def __getLineInfo(frame: inspect.FrameInfo) -> str:
|
405
|
+
"""
|
406
|
+
Extracts and formats line information from a given frame.
|
407
|
+
|
408
|
+
Args:
|
409
|
+
frame (inspect.FrameInfo): The frame object containing code context.
|
410
|
+
|
411
|
+
Returns:
|
412
|
+
str: A string in the format "filename:line_no", where `filename` is the
|
413
|
+
name of the file (excluding the path) and `line_no` is the line number
|
414
|
+
in the file where the frame is located.
|
415
|
+
"""
|
416
|
+
filename = frame.f_code.co_filename.split('/')[-1]
|
417
|
+
line_no = frame.f_lineno
|
418
|
+
return f"{filename}:{line_no}"
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import os
|
2
2
|
from orionis.luminate.contracts.facades.files.path_facade import IPath
|
3
3
|
from orionis.luminate.contracts.services.files.path_resolver_service import IPathResolverService
|
4
|
-
from orionis.luminate.
|
4
|
+
from orionis.luminate.services_.files.path_resolver_service import PathResolverService
|
5
5
|
|
6
6
|
class Path(IPath):
|
7
7
|
"""
|
@@ -0,0 +1,10 @@
|
|
1
|
+
from orionis.luminate.patterns.singleton.meta_class import Singleton
|
2
|
+
|
3
|
+
__all__ = [
|
4
|
+
"Singleton",
|
5
|
+
]
|
6
|
+
__author__ = "Raúl Mauricio Uñate Castro"
|
7
|
+
__description__ = (
|
8
|
+
"This module provides a singleton class to manage environment variables. "
|
9
|
+
"It allows setting, getting, and deleting environment variables."
|
10
|
+
)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import threading
|
2
|
+
import asyncio
|
3
|
+
from typing import Dict, Type, Any, TypeVar
|
4
|
+
|
5
|
+
T = TypeVar('T')
|
6
|
+
|
7
|
+
class Singleton(type):
|
8
|
+
"""
|
9
|
+
Thread-safe + Async-safe singleton metaclass.
|
10
|
+
Works for both synchronous and asynchronous contexts.
|
11
|
+
"""
|
12
|
+
|
13
|
+
_instances: Dict[Type[T], T] = {}
|
14
|
+
_lock = threading.Lock()
|
15
|
+
_async_lock = asyncio.Lock()
|
16
|
+
|
17
|
+
def __call__(cls: Type[T], *args: Any, **kwargs: Any) -> T:
|
18
|
+
"""
|
19
|
+
Creates and returns a singleton instance of the class.
|
20
|
+
|
21
|
+
If an instance of the class does not already exist, this method acquires a lock to ensure thread safety,
|
22
|
+
creates a new instance using the provided arguments, and stores it in the class-level _instances dictionary.
|
23
|
+
Subsequent calls return the existing instance.
|
24
|
+
|
25
|
+
Args:
|
26
|
+
*args: Positional arguments to pass to the class constructor.
|
27
|
+
**kwargs: Keyword arguments to pass to the class constructor.
|
28
|
+
|
29
|
+
Returns:
|
30
|
+
T: The singleton instance of the class.
|
31
|
+
"""
|
32
|
+
if cls not in cls._instances:
|
33
|
+
with cls._lock:
|
34
|
+
if cls not in cls._instances:
|
35
|
+
cls._instances[cls] = super().__call__(*args, **kwargs)
|
36
|
+
return cls._instances[cls]
|
37
|
+
|
38
|
+
async def __acall__(cls: Type[T], *args: Any, **kwargs: Any) -> T:
|
39
|
+
"""
|
40
|
+
Asynchronously creates or retrieves a singleton instance of the class.
|
41
|
+
|
42
|
+
If an instance of the class does not exist, acquires an asynchronous lock to ensure thread safety,
|
43
|
+
creates the instance, and stores it. Subsequent calls return the existing instance.
|
44
|
+
|
45
|
+
Args:
|
46
|
+
*args: Positional arguments to pass to the class constructor.
|
47
|
+
**kwargs: Keyword arguments to pass to the class constructor.
|
48
|
+
|
49
|
+
Returns:
|
50
|
+
T: The singleton instance of the class.
|
51
|
+
"""
|
52
|
+
if cls not in cls._instances:
|
53
|
+
async with cls._async_lock:
|
54
|
+
if cls not in cls._instances:
|
55
|
+
cls._instances[cls] = super().__call__(*args, **kwargs)
|
56
|
+
return cls._instances[cls]
|
@@ -2,9 +2,9 @@ from orionis.luminate.contracts.services.commands.reactor_commands_service impor
|
|
2
2
|
from orionis.luminate.contracts.services.config.config_service import IConfigService
|
3
3
|
from orionis.luminate.contracts.services.log.log_service import ILogguerService
|
4
4
|
from orionis.luminate.providers.service_provider import ServiceProvider
|
5
|
-
from orionis.luminate.
|
6
|
-
from orionis.luminate.
|
7
|
-
from orionis.luminate.
|
5
|
+
from orionis.luminate.services_.commands.reactor_commands_service import ReactorCommandsService
|
6
|
+
from orionis.luminate.services_.config.config_service import ConfigService
|
7
|
+
from orionis.luminate.services_.log.log_service import LogguerService
|
8
8
|
|
9
9
|
class ReactorCommandsServiceProvider(ServiceProvider):
|
10
10
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from orionis.luminate.contracts.services.commands.schedule_service import IScheduleService
|
2
2
|
from orionis.luminate.providers.service_provider import ServiceProvider
|
3
|
-
from orionis.luminate.
|
3
|
+
from orionis.luminate.services_.commands.scheduler_service import ScheduleService
|
4
4
|
|
5
5
|
class ScheduleServiceProvider(ServiceProvider):
|
6
6
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from orionis.luminate.contracts.services.config.config_service import IConfigService
|
2
2
|
from orionis.luminate.providers.service_provider import ServiceProvider
|
3
|
-
from orionis.luminate.
|
3
|
+
from orionis.luminate.services_.config.config_service import ConfigService
|
4
4
|
|
5
5
|
class ConfigServiceProvider(ServiceProvider):
|
6
6
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from orionis.luminate.contracts.services.environment.environment_service import IEnvironmentService
|
2
2
|
from orionis.luminate.providers.service_provider import ServiceProvider
|
3
|
-
from orionis.luminate.
|
4
|
-
from orionis.luminate.
|
3
|
+
from orionis.luminate.services_.environment.environment_service import EnvironmentService
|
4
|
+
from orionis.luminate.services_.files.path_resolver_service import PathResolverService
|
5
5
|
|
6
6
|
class EnvironmentServiceProvider(ServiceProvider):
|
7
7
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from orionis.luminate.contracts.services.files.path_resolver_service import IPathResolverService
|
2
2
|
from orionis.luminate.providers.service_provider import ServiceProvider
|
3
|
-
from orionis.luminate.
|
3
|
+
from orionis.luminate.services_.files.path_resolver_service import PathResolverService
|
4
4
|
|
5
5
|
class PathResolverProvider(ServiceProvider):
|
6
6
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
from orionis.luminate.contracts.services.config.config_service import IConfigService
|
2
2
|
from orionis.luminate.contracts.services.log.log_service import ILogguerService
|
3
3
|
from orionis.luminate.providers.service_provider import ServiceProvider
|
4
|
-
from orionis.luminate.
|
5
|
-
from orionis.luminate.
|
4
|
+
from orionis.luminate.services_.config.config_service import ConfigService
|
5
|
+
from orionis.luminate.services_.log.log_service import LogguerService
|
6
6
|
|
7
7
|
class LogServiceProvider(ServiceProvider):
|
8
8
|
|
@@ -0,0 +1,10 @@
|
|
1
|
+
from orionis.luminate.services.environment.env import Env
|
2
|
+
|
3
|
+
__all__ = [
|
4
|
+
"Env",
|
5
|
+
]
|
6
|
+
__author__ = "Raúl Mauricio Uñate Castro"
|
7
|
+
__description__ = (
|
8
|
+
"This module provides a singleton class to manage environment variables. "
|
9
|
+
"It allows setting, getting, and deleting environment variables."
|
10
|
+
)
|