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.
Files changed (85) hide show
  1. orionis/framework.py +1 -1
  2. orionis/luminate/application.py +159 -309
  3. orionis/luminate/console/base/command.py +6 -3
  4. orionis/luminate/console/command_filter.py +1 -1
  5. orionis/luminate/console/commands/cache_clear.py +4 -3
  6. orionis/luminate/console/commands/schedule_work.py +1 -1
  7. orionis/luminate/console/kernel.py +1 -2
  8. orionis/luminate/console/output/console.py +1 -1
  9. orionis/luminate/console/output/executor.py +1 -1
  10. orionis/luminate/console/output/progress_bar.py +1 -1
  11. orionis/luminate/console/parser.py +1 -1
  12. orionis/luminate/container/container.py +361 -272
  13. orionis/luminate/container/container_integrity.py +235 -0
  14. orionis/luminate/container/lifetimes.py +13 -0
  15. orionis/luminate/container/resolve.py +74 -0
  16. orionis/luminate/contracts/application.py +41 -0
  17. orionis/luminate/contracts/console/{i_parser.py → parser.py} +0 -1
  18. orionis/luminate/contracts/container/container.py +346 -0
  19. orionis/luminate/contracts/container/container_integrity.py +168 -0
  20. orionis/luminate/contracts/foundation/providers/{i_service_providers_bootstrapper.py → service_providers_bootstrapper.py} +4 -3
  21. orionis/luminate/facades/commands/commands_facade.py +1 -1
  22. orionis/luminate/facades/commands/scheduler_facade.py +1 -1
  23. orionis/luminate/facades/config/config_facade.py +1 -1
  24. orionis/luminate/facades/environment/environment_facade.py +1 -26
  25. orionis/luminate/facades/files/path_facade.py +1 -1
  26. orionis/luminate/facades/log/log_facade.py +1 -1
  27. orionis/luminate/facades/tests/tests_facade.py +1 -1
  28. orionis/luminate/foundation/config/config_bootstrapper.py +1 -1
  29. orionis/luminate/foundation/console/command_bootstrapper.py +1 -1
  30. orionis/luminate/foundation/environment/environment_bootstrapper.py +1 -1
  31. orionis/luminate/foundation/exceptions/exception_providers.py +54 -0
  32. orionis/luminate/foundation/providers/service_providers_bootstrapper.py +53 -45
  33. orionis/luminate/providers/commands/reactor_commands_service_provider.py +4 -3
  34. orionis/luminate/providers/commands/scheduler_provider.py +2 -10
  35. orionis/luminate/providers/config/config_service_provider.py +2 -10
  36. orionis/luminate/providers/environment/environment__service_provider.py +3 -4
  37. orionis/luminate/providers/files/paths_provider.py +3 -4
  38. orionis/luminate/providers/log/log_service_provider.py +3 -2
  39. orionis/luminate/providers/service_provider.py +2 -6
  40. orionis/luminate/services/commands/reactor_commands_service.py +6 -16
  41. orionis/luminate/services/commands/scheduler_service.py +1 -2
  42. orionis/luminate/services/config/config_service.py +4 -5
  43. orionis/luminate/services/environment/environment_service.py +25 -2
  44. orionis/luminate/services/files/path_resolver_service.py +1 -2
  45. orionis/luminate/services/log/log_service.py +1 -2
  46. orionis/luminate/support/exception_to_dict.py +1 -1
  47. orionis/luminate/support/reflection.py +1 -1
  48. orionis/luminate/support/std.py +1 -1
  49. {orionis-0.139.0.dist-info → orionis-0.152.0.dist-info}/METADATA +1 -1
  50. {orionis-0.139.0.dist-info → orionis-0.152.0.dist-info}/RECORD +82 -78
  51. orionis/luminate/container/types.py +0 -51
  52. orionis/luminate/contracts/container/i_container.py +0 -239
  53. orionis/luminate/contracts/container/i_types.py +0 -16
  54. /orionis/luminate/contracts/console/base/{i_command.py → command.py} +0 -0
  55. /orionis/luminate/contracts/console/{i_command_filter.py → command_filter.py} +0 -0
  56. /orionis/luminate/contracts/console/{i_kernel.py → kernel.py} +0 -0
  57. /orionis/luminate/contracts/console/output/{i_console.py → console.py} +0 -0
  58. /orionis/luminate/contracts/console/output/{i_executor.py → executor.py} +0 -0
  59. /orionis/luminate/contracts/console/output/{i_progress_bar.py → progress_bar.py} +0 -0
  60. /orionis/luminate/contracts/console/{i_task_manager.py → task_manager.py} +0 -0
  61. /orionis/luminate/contracts/facades/commands/{i_commands_facade.py → commands_facade.py} +0 -0
  62. /orionis/luminate/contracts/facades/commands/{i_scheduler_facade.py → scheduler_facade.py} +0 -0
  63. /orionis/luminate/contracts/facades/config/{i_config_facade.py → config_facade.py} +0 -0
  64. /orionis/luminate/contracts/facades/environment/{i_environment_facade.py → environment_facade.py} +0 -0
  65. /orionis/luminate/contracts/facades/files/{i_path_facade.py → path_facade.py} +0 -0
  66. /orionis/luminate/contracts/facades/log/{i_log_facade.py → log_facade.py} +0 -0
  67. /orionis/luminate/contracts/facades/tests/{i_tests_facade.py → tests_facade.py} +0 -0
  68. /orionis/luminate/contracts/foundation/{i_bootstraper.py → bootstraper.py} +0 -0
  69. /orionis/luminate/contracts/foundation/config/{i_config_bootstrapper.py → config_bootstrapper.py} +0 -0
  70. /orionis/luminate/contracts/foundation/console/{i_command_bootstrapper.py → command_bootstrapper.py} +0 -0
  71. /orionis/luminate/contracts/foundation/environment/{i_environment_bootstrapper.py → environment_bootstrapper.py} +0 -0
  72. /orionis/luminate/contracts/providers/{i_service_provider.py → service_provider.py} +0 -0
  73. /orionis/luminate/contracts/services/commands/{i_reactor_commands_service.py → reactor_commands_service.py} +0 -0
  74. /orionis/luminate/contracts/services/commands/{i_schedule_service.py → schedule_service.py} +0 -0
  75. /orionis/luminate/contracts/services/config/{i_config_service.py → config_service.py} +0 -0
  76. /orionis/luminate/contracts/services/environment/{i_environment_service.py → environment_service.py} +0 -0
  77. /orionis/luminate/contracts/services/files/{i_path_resolver_service.py → path_resolver_service.py} +0 -0
  78. /orionis/luminate/contracts/services/log/{i_log_service.py → log_service.py} +0 -0
  79. /orionis/luminate/contracts/support/{i_exception_to_dict.py → exception_to_dict.py} +0 -0
  80. /orionis/luminate/contracts/support/{i_reflection.py → reflection.py} +0 -0
  81. /orionis/luminate/contracts/support/{i_std.py → std.py} +0 -0
  82. {orionis-0.139.0.dist-info → orionis-0.152.0.dist-info}/LICENCE +0 -0
  83. {orionis-0.139.0.dist-info → orionis-0.152.0.dist-info}/WHEEL +0 -0
  84. {orionis-0.139.0.dist-info → orionis-0.152.0.dist-info}/entry_points.txt +0 -0
  85. {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
@@ -2,7 +2,6 @@ from abc import ABC, abstractmethod
2
2
  from typing import List, Tuple, Dict, Any
3
3
  import argparse
4
4
 
5
-
6
5
  class IParser(ABC):
7
6
  """
8
7
  Interface for a command-line argument parser.