orionis 0.139.0__py3-none-any.whl → 0.152.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/application.py +159 -309
- orionis/luminate/console/base/command.py +6 -3
- orionis/luminate/console/command_filter.py +1 -1
- orionis/luminate/console/commands/cache_clear.py +4 -3
- orionis/luminate/console/commands/schedule_work.py +1 -1
- orionis/luminate/console/kernel.py +1 -2
- orionis/luminate/console/output/console.py +1 -1
- orionis/luminate/console/output/executor.py +1 -1
- orionis/luminate/console/output/progress_bar.py +1 -1
- orionis/luminate/console/parser.py +1 -1
- orionis/luminate/container/container.py +361 -272
- orionis/luminate/container/container_integrity.py +235 -0
- orionis/luminate/container/lifetimes.py +13 -0
- orionis/luminate/container/resolve.py +74 -0
- orionis/luminate/contracts/application.py +41 -0
- orionis/luminate/contracts/console/{i_parser.py → parser.py} +0 -1
- orionis/luminate/contracts/container/container.py +346 -0
- orionis/luminate/contracts/container/container_integrity.py +168 -0
- orionis/luminate/contracts/foundation/providers/{i_service_providers_bootstrapper.py → service_providers_bootstrapper.py} +4 -3
- orionis/luminate/facades/commands/commands_facade.py +1 -1
- orionis/luminate/facades/commands/scheduler_facade.py +1 -1
- orionis/luminate/facades/config/config_facade.py +1 -1
- orionis/luminate/facades/environment/environment_facade.py +1 -26
- orionis/luminate/facades/files/path_facade.py +1 -1
- orionis/luminate/facades/log/log_facade.py +1 -1
- orionis/luminate/facades/tests/tests_facade.py +1 -1
- orionis/luminate/foundation/config/config_bootstrapper.py +1 -1
- orionis/luminate/foundation/console/command_bootstrapper.py +1 -1
- orionis/luminate/foundation/environment/environment_bootstrapper.py +1 -1
- orionis/luminate/foundation/exceptions/exception_providers.py +54 -0
- orionis/luminate/foundation/providers/service_providers_bootstrapper.py +53 -45
- orionis/luminate/providers/commands/reactor_commands_service_provider.py +4 -3
- orionis/luminate/providers/commands/scheduler_provider.py +2 -10
- orionis/luminate/providers/config/config_service_provider.py +2 -10
- orionis/luminate/providers/environment/environment__service_provider.py +3 -4
- orionis/luminate/providers/files/paths_provider.py +3 -4
- orionis/luminate/providers/log/log_service_provider.py +3 -2
- orionis/luminate/providers/service_provider.py +2 -6
- orionis/luminate/services/commands/reactor_commands_service.py +6 -16
- orionis/luminate/services/commands/scheduler_service.py +1 -2
- orionis/luminate/services/config/config_service.py +4 -5
- orionis/luminate/services/environment/environment_service.py +25 -2
- orionis/luminate/services/files/path_resolver_service.py +1 -2
- orionis/luminate/services/log/log_service.py +1 -2
- orionis/luminate/support/exception_to_dict.py +1 -1
- orionis/luminate/support/reflection.py +1 -1
- orionis/luminate/support/std.py +1 -1
- {orionis-0.139.0.dist-info → orionis-0.152.0.dist-info}/METADATA +1 -1
- {orionis-0.139.0.dist-info → orionis-0.152.0.dist-info}/RECORD +82 -78
- orionis/luminate/container/types.py +0 -51
- orionis/luminate/contracts/container/i_container.py +0 -239
- orionis/luminate/contracts/container/i_types.py +0 -16
- /orionis/luminate/contracts/console/base/{i_command.py → command.py} +0 -0
- /orionis/luminate/contracts/console/{i_command_filter.py → command_filter.py} +0 -0
- /orionis/luminate/contracts/console/{i_kernel.py → kernel.py} +0 -0
- /orionis/luminate/contracts/console/output/{i_console.py → console.py} +0 -0
- /orionis/luminate/contracts/console/output/{i_executor.py → executor.py} +0 -0
- /orionis/luminate/contracts/console/output/{i_progress_bar.py → progress_bar.py} +0 -0
- /orionis/luminate/contracts/console/{i_task_manager.py → task_manager.py} +0 -0
- /orionis/luminate/contracts/facades/commands/{i_commands_facade.py → commands_facade.py} +0 -0
- /orionis/luminate/contracts/facades/commands/{i_scheduler_facade.py → scheduler_facade.py} +0 -0
- /orionis/luminate/contracts/facades/config/{i_config_facade.py → config_facade.py} +0 -0
- /orionis/luminate/contracts/facades/environment/{i_environment_facade.py → environment_facade.py} +0 -0
- /orionis/luminate/contracts/facades/files/{i_path_facade.py → path_facade.py} +0 -0
- /orionis/luminate/contracts/facades/log/{i_log_facade.py → log_facade.py} +0 -0
- /orionis/luminate/contracts/facades/tests/{i_tests_facade.py → tests_facade.py} +0 -0
- /orionis/luminate/contracts/foundation/{i_bootstraper.py → bootstraper.py} +0 -0
- /orionis/luminate/contracts/foundation/config/{i_config_bootstrapper.py → config_bootstrapper.py} +0 -0
- /orionis/luminate/contracts/foundation/console/{i_command_bootstrapper.py → command_bootstrapper.py} +0 -0
- /orionis/luminate/contracts/foundation/environment/{i_environment_bootstrapper.py → environment_bootstrapper.py} +0 -0
- /orionis/luminate/contracts/providers/{i_service_provider.py → service_provider.py} +0 -0
- /orionis/luminate/contracts/services/commands/{i_reactor_commands_service.py → reactor_commands_service.py} +0 -0
- /orionis/luminate/contracts/services/commands/{i_schedule_service.py → schedule_service.py} +0 -0
- /orionis/luminate/contracts/services/config/{i_config_service.py → config_service.py} +0 -0
- /orionis/luminate/contracts/services/environment/{i_environment_service.py → environment_service.py} +0 -0
- /orionis/luminate/contracts/services/files/{i_path_resolver_service.py → path_resolver_service.py} +0 -0
- /orionis/luminate/contracts/services/log/{i_log_service.py → log_service.py} +0 -0
- /orionis/luminate/contracts/support/{i_exception_to_dict.py → exception_to_dict.py} +0 -0
- /orionis/luminate/contracts/support/{i_reflection.py → reflection.py} +0 -0
- /orionis/luminate/contracts/support/{i_std.py → std.py} +0 -0
- {orionis-0.139.0.dist-info → orionis-0.152.0.dist-info}/LICENCE +0 -0
- {orionis-0.139.0.dist-info → orionis-0.152.0.dist-info}/WHEEL +0 -0
- {orionis-0.139.0.dist-info → orionis-0.152.0.dist-info}/entry_points.txt +0 -0
- {orionis-0.139.0.dist-info → orionis-0.152.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,235 @@
|
|
1
|
+
import re
|
2
|
+
import inspect
|
3
|
+
from abc import ABC
|
4
|
+
from typing import Any, Callable, Type
|
5
|
+
from orionis.luminate.container.exception import OrionisContainerValueError, OrionisContainerTypeError
|
6
|
+
from orionis.luminate.contracts.container.container_integrity import IContainerIntegrity
|
7
|
+
|
8
|
+
class ContainerIntegrity(IContainerIntegrity):
|
9
|
+
|
10
|
+
@staticmethod
|
11
|
+
def ensureImplementation(abstract: Type, concrete: Type) -> None:
|
12
|
+
"""
|
13
|
+
Verify at runtime if `concrete` implements all methods of `abstract`.
|
14
|
+
|
15
|
+
:param abstract: Abstract class or interface.
|
16
|
+
:param concrete: Concrete class that should implement the abstract class.
|
17
|
+
:raises TypeError: If `concrete` does not implement all methods of `abstract`.
|
18
|
+
"""
|
19
|
+
# Get public methods of the interface (excluding magic methods)
|
20
|
+
interface_methods = {
|
21
|
+
name for name, func in inspect.getmembers(abstract, predicate=inspect.isfunction)
|
22
|
+
if not name.startswith("_")
|
23
|
+
}
|
24
|
+
|
25
|
+
# Get public methods of the concrete class
|
26
|
+
class_methods = {
|
27
|
+
name for name, func in inspect.getmembers(concrete, predicate=inspect.isfunction)
|
28
|
+
if not name.startswith("_")
|
29
|
+
}
|
30
|
+
|
31
|
+
# Verify that all interface methods are in the concrete class
|
32
|
+
if not interface_methods.issubset(class_methods):
|
33
|
+
missing_methods = interface_methods - class_methods
|
34
|
+
raise OrionisContainerTypeError(f"{concrete.__name__} does not implement the required methods of {abstract.__name__}: {missing_methods}")
|
35
|
+
|
36
|
+
|
37
|
+
@staticmethod
|
38
|
+
def ensureIsAbstract(abstract: Callable[..., Any]) -> None:
|
39
|
+
"""
|
40
|
+
Ensure that the given abstract is a valid abstract class.
|
41
|
+
|
42
|
+
:param abstract: Class to check
|
43
|
+
:raises OrionisContainerValueError: If the class is not a valid abstract interface
|
44
|
+
"""
|
45
|
+
if not isinstance(abstract, type) or not issubclass(abstract, ABC) or abstract is ABC:
|
46
|
+
raise OrionisContainerValueError("The provided class must inherit from ABC and not be ABC itself.")
|
47
|
+
|
48
|
+
if not any(getattr(attr, "__isabstractmethod__", False) for attr in abstract.__dict__.values()):
|
49
|
+
raise OrionisContainerValueError("The provided class must define at least one abstract method.")
|
50
|
+
|
51
|
+
@staticmethod
|
52
|
+
def ensureIsCallable(concrete: Callable[..., Any]) -> None:
|
53
|
+
"""
|
54
|
+
Ensure that the given implementation is callable or instantiable.
|
55
|
+
|
56
|
+
Parameters
|
57
|
+
----------
|
58
|
+
concrete : Callable[..., Any]
|
59
|
+
The implementation to check.
|
60
|
+
|
61
|
+
Raises
|
62
|
+
------
|
63
|
+
OrionisContainerTypeError
|
64
|
+
If the implementation is not callable.
|
65
|
+
"""
|
66
|
+
if not callable(concrete):
|
67
|
+
raise OrionisContainerTypeError(f"The implementation '{str(concrete)}' must be callable or an instantiable class.")
|
68
|
+
|
69
|
+
@staticmethod
|
70
|
+
def ensureIsInstance(instance: Any) -> None:
|
71
|
+
"""
|
72
|
+
Ensure that the given instance is a valid object.
|
73
|
+
|
74
|
+
Parameters
|
75
|
+
----------
|
76
|
+
instance : Any
|
77
|
+
The instance to check.
|
78
|
+
|
79
|
+
Raises
|
80
|
+
------
|
81
|
+
OrionisContainerValueError
|
82
|
+
If the instance is not a valid object.
|
83
|
+
"""
|
84
|
+
if not isinstance(instance, object):
|
85
|
+
raise OrionisContainerValueError(f"The instance '{str(instance)}' must be a valid object.")
|
86
|
+
|
87
|
+
module = type(instance).__module__
|
88
|
+
if module in ['builtins', 'abc']:
|
89
|
+
raise OrionisContainerValueError(f"The instance '{str(instance)}' is not a valid user-defined object. It belongs to the '{module}' module.")
|
90
|
+
|
91
|
+
@staticmethod
|
92
|
+
def ensureNotMain(concrete: Callable[..., Any]) -> str:
|
93
|
+
"""
|
94
|
+
Ensure that a class is not defined in the main script.
|
95
|
+
|
96
|
+
Parameters
|
97
|
+
----------
|
98
|
+
concrete : Callable[..., Any]
|
99
|
+
The class or function to check.
|
100
|
+
|
101
|
+
Returns
|
102
|
+
-------
|
103
|
+
str
|
104
|
+
The fully qualified name of the class.
|
105
|
+
|
106
|
+
Raises
|
107
|
+
------
|
108
|
+
OrionisContainerValueError
|
109
|
+
If the class is defined in the main module.
|
110
|
+
"""
|
111
|
+
if concrete.__module__ == "__main__":
|
112
|
+
raise OrionisContainerValueError("Cannot register a class from the (__main__) module in the container.")
|
113
|
+
|
114
|
+
@staticmethod
|
115
|
+
def ensureIsAlias(name: str) -> bool:
|
116
|
+
"""
|
117
|
+
Ensure that the given alias name is a valid string, with no special characters or spaces,
|
118
|
+
and it is not a primitive type.
|
119
|
+
|
120
|
+
Parameters
|
121
|
+
----------
|
122
|
+
name : str
|
123
|
+
The alias name to check.
|
124
|
+
|
125
|
+
Raises
|
126
|
+
------
|
127
|
+
OrionisContainerValueError
|
128
|
+
If the alias is invalid.
|
129
|
+
"""
|
130
|
+
if not isinstance(name, str):
|
131
|
+
raise OrionisContainerValueError(f"The alias '{name}' must be a string.")
|
132
|
+
|
133
|
+
if not re.match(r'^[a-zA-Z0-9_]+$', name):
|
134
|
+
raise OrionisContainerValueError(f"The alias '{name}' can only contain letters, numbers, and underscores, without spaces or other special characters.")
|
135
|
+
|
136
|
+
if name in {
|
137
|
+
int, "int",
|
138
|
+
float, "float",
|
139
|
+
str, "str",
|
140
|
+
bool, "bool",
|
141
|
+
bytes, "bytes",
|
142
|
+
type(None), "None",
|
143
|
+
complex, "complex",
|
144
|
+
list, "list",
|
145
|
+
tuple, "tuple",
|
146
|
+
dict, "dict",
|
147
|
+
set, "set",
|
148
|
+
frozenset, "frozenset"
|
149
|
+
}:
|
150
|
+
raise OrionisContainerValueError(f"The alias '{name}' cannot be a primitive type.")
|
151
|
+
|
152
|
+
@staticmethod
|
153
|
+
def isAlias(name: str) -> bool:
|
154
|
+
"""
|
155
|
+
Check if the given alias name is a valid string, with no special characters or spaces,
|
156
|
+
and it is not a primitive type.
|
157
|
+
|
158
|
+
Parameters
|
159
|
+
----------
|
160
|
+
name : str
|
161
|
+
The alias name to check.
|
162
|
+
|
163
|
+
Returns
|
164
|
+
-------
|
165
|
+
bool
|
166
|
+
True if the alias is valid, False otherwise.
|
167
|
+
"""
|
168
|
+
try:
|
169
|
+
ContainerIntegrity.ensureIsAlias(name)
|
170
|
+
return True
|
171
|
+
except OrionisContainerValueError:
|
172
|
+
return False
|
173
|
+
|
174
|
+
@staticmethod
|
175
|
+
def isCallable(concrete: Callable[..., Any]) -> bool:
|
176
|
+
"""
|
177
|
+
Check if the given implementation is callable or instantiable.
|
178
|
+
|
179
|
+
Parameters
|
180
|
+
----------
|
181
|
+
concrete : Callable[..., Any]
|
182
|
+
The implementation to check.
|
183
|
+
|
184
|
+
Returns
|
185
|
+
-------
|
186
|
+
bool
|
187
|
+
True if the implementation is callable, False otherwise.
|
188
|
+
"""
|
189
|
+
try:
|
190
|
+
ContainerIntegrity.ensureIsCallable(concrete)
|
191
|
+
return True
|
192
|
+
except OrionisContainerTypeError:
|
193
|
+
return False
|
194
|
+
|
195
|
+
@staticmethod
|
196
|
+
def isInstance(instance: Any) -> bool:
|
197
|
+
"""
|
198
|
+
Check if the given instance is a valid object.
|
199
|
+
|
200
|
+
Parameters
|
201
|
+
----------
|
202
|
+
instance : Any
|
203
|
+
The instance to check.
|
204
|
+
|
205
|
+
Returns
|
206
|
+
-------
|
207
|
+
bool
|
208
|
+
True if the instance is valid, False otherwise.
|
209
|
+
"""
|
210
|
+
try:
|
211
|
+
ContainerIntegrity.ensureIsInstance(instance)
|
212
|
+
return True
|
213
|
+
except OrionisContainerValueError:
|
214
|
+
return False
|
215
|
+
|
216
|
+
@staticmethod
|
217
|
+
def isAbstract(abstract: Callable[..., Any]) -> bool:
|
218
|
+
"""
|
219
|
+
Check if the given abstract is a valid abstract class.
|
220
|
+
|
221
|
+
Parameters
|
222
|
+
----------
|
223
|
+
abstract : Callable[..., Any]
|
224
|
+
The class to check.
|
225
|
+
|
226
|
+
Returns
|
227
|
+
-------
|
228
|
+
bool
|
229
|
+
True if the class is a valid abstract interface, False otherwise.
|
230
|
+
"""
|
231
|
+
try:
|
232
|
+
ContainerIntegrity.ensureIsAbstract(abstract)
|
233
|
+
return True
|
234
|
+
except OrionisContainerValueError:
|
235
|
+
return False
|
@@ -0,0 +1,13 @@
|
|
1
|
+
from enum import Enum
|
2
|
+
|
3
|
+
class Lifetime(Enum):
|
4
|
+
"""Defines the lifecycle types for dependency injection."""
|
5
|
+
|
6
|
+
# Creates a new instance every time it is requested
|
7
|
+
TRANSIENT = "transient"
|
8
|
+
|
9
|
+
# A single instance is shared throughout the application
|
10
|
+
SINGLETON = "singleton"
|
11
|
+
|
12
|
+
# A new instance is created per request or context
|
13
|
+
SCOPED = "scoped"
|
@@ -0,0 +1,74 @@
|
|
1
|
+
import asyncio
|
2
|
+
from typing import Any, Callable
|
3
|
+
from orionis.luminate.container.container import Container
|
4
|
+
from orionis.luminate.container.exception import OrionisContainerValueError
|
5
|
+
|
6
|
+
class Resolve:
|
7
|
+
"""
|
8
|
+
A class to resolve dependencies from the dependency injection container.
|
9
|
+
|
10
|
+
This class ensures that a given abstract class or alias exists in the container
|
11
|
+
and resolves the associated service when an instance is created.
|
12
|
+
|
13
|
+
Parameters
|
14
|
+
----------
|
15
|
+
abstract_or_alias : Callable[..., Any] or str
|
16
|
+
The abstract class, alias, or callable to resolve from the container.
|
17
|
+
|
18
|
+
Returns
|
19
|
+
-------
|
20
|
+
Any
|
21
|
+
The service associated with the abstract class or alias.
|
22
|
+
|
23
|
+
Raises
|
24
|
+
------
|
25
|
+
OrionisContainerValueError
|
26
|
+
If the abstract class or alias is not found in the container.
|
27
|
+
|
28
|
+
Examples
|
29
|
+
--------
|
30
|
+
>>> container = Container()
|
31
|
+
>>> container.bind("my_service", MyService)
|
32
|
+
>>> container.alias("my_alias", "my_service")
|
33
|
+
>>> service = Resolve("my_alias") # Returns the service associated with "my_alias"
|
34
|
+
>>> service = Resolve(MyService) # Returns the service associated with MyService
|
35
|
+
"""
|
36
|
+
|
37
|
+
def __new__(cls, abstract_or_alias: Callable[..., Any] | str):
|
38
|
+
"""
|
39
|
+
Create an instance of Resolve and return the resolved service.
|
40
|
+
|
41
|
+
Parameters
|
42
|
+
----------
|
43
|
+
abstract_or_alias : Callable[..., Any] or str
|
44
|
+
The abstract class, alias, or callable to resolve from the container.
|
45
|
+
|
46
|
+
Returns
|
47
|
+
-------
|
48
|
+
Any
|
49
|
+
The service associated with the abstract class or alias.
|
50
|
+
|
51
|
+
Raises
|
52
|
+
------
|
53
|
+
OrionisContainerValueError
|
54
|
+
If the abstract class or alias is not found in the container.
|
55
|
+
"""
|
56
|
+
container = Container()
|
57
|
+
|
58
|
+
# Validate that the abstract or alias exists in the container
|
59
|
+
if not container.bound(abstract_or_alias):
|
60
|
+
raise OrionisContainerValueError(
|
61
|
+
f"Service or alias '{abstract_or_alias}' not found in the container."
|
62
|
+
)
|
63
|
+
|
64
|
+
# Resolve and return the service associated with the abstract or alias
|
65
|
+
try:
|
66
|
+
# Try to get the running event loop
|
67
|
+
loop = asyncio.get_running_loop()
|
68
|
+
# If there is a running event loop, resolve the service asynchronously
|
69
|
+
return loop.run_until_complete(container.make(abstract_or_alias))
|
70
|
+
except RuntimeError:
|
71
|
+
# If no event loop is running, create a new one and resolve the service
|
72
|
+
loop = asyncio.new_event_loop()
|
73
|
+
asyncio.set_event_loop(loop)
|
74
|
+
return loop.run_until_complete(container.make(abstract_or_alias))
|
@@ -0,0 +1,41 @@
|
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
from typing import List, Type
|
3
|
+
from orionis.luminate.contracts.container.container import IContainer
|
4
|
+
from orionis.luminate.contracts.providers.service_provider import IServiceProvider
|
5
|
+
|
6
|
+
class IApplication(ABC):
|
7
|
+
"""
|
8
|
+
Abstract base class for the Application.
|
9
|
+
"""
|
10
|
+
|
11
|
+
@abstractmethod
|
12
|
+
def withProviders(self, providers: List[Type["IServiceProvider"]]) -> None:
|
13
|
+
"""
|
14
|
+
Sets custom service providers.
|
15
|
+
|
16
|
+
Parameters
|
17
|
+
----------
|
18
|
+
providers : List[Type[ServiceProvider]]
|
19
|
+
List of service providers.
|
20
|
+
"""
|
21
|
+
pass
|
22
|
+
|
23
|
+
@abstractmethod
|
24
|
+
def container(self) -> "IContainer":
|
25
|
+
"""
|
26
|
+
Returns the service container instance.
|
27
|
+
|
28
|
+
Returns
|
29
|
+
-------
|
30
|
+
IContainer
|
31
|
+
The service container.
|
32
|
+
"""
|
33
|
+
pass
|
34
|
+
|
35
|
+
@abstractmethod
|
36
|
+
def create(self) -> None:
|
37
|
+
"""
|
38
|
+
Initializes and boots the application, including loading commands
|
39
|
+
and service providers.
|
40
|
+
"""
|
41
|
+
pass
|