orionis 0.318.0__py3-none-any.whl → 0.319.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.
@@ -1,4 +1,6 @@
1
+ import threading
1
2
  from typing import Any, Callable
3
+ from orionis.container.contracts.container import IContainer
2
4
  from orionis.container.entities.binding import Binding
3
5
  from orionis.container.enums.lifetimes import Lifetime
4
6
  from orionis.container.exceptions.container_exception import OrionisContainerException
@@ -6,11 +8,11 @@ from orionis.container.exceptions.type_error_exception import OrionisContainerTy
6
8
  from orionis.services.introspection.abstract.reflection_abstract import ReflectionAbstract
7
9
  from orionis.services.introspection.callables.reflection_callable import ReflectionCallable
8
10
  from orionis.services.introspection.concretes.reflection_concrete import ReflectionConcrete
11
+ from orionis.services.introspection.dependencies.entities.resolved_dependencies import ResolvedDependency
9
12
  from orionis.services.introspection.instances.reflection_instance import ReflectionInstance
10
13
  from orionis.services.introspection.reflection import Reflection
11
- import threading
12
14
 
13
- class Container:
15
+ class Container(IContainer):
14
16
 
15
17
  # Singleton instance of the container.
16
18
  # This is a class variable that holds the single instance of the Container class.
@@ -26,7 +28,11 @@ class Container:
26
28
  # regardless of how many times the class is instantiated.
27
29
  _initialized = False
28
30
 
29
- def __new__(cls, *args, **kwargs):
31
+ def __new__(
32
+ cls,
33
+ *args,
34
+ **kwargs
35
+ ) -> 'Container':
30
36
  """
31
37
  Creates and returns a singleton instance of the class.
32
38
 
@@ -51,24 +57,29 @@ class Container:
51
57
  cls._instance = super(Container, cls).__new__(cls)
52
58
  return cls._instance
53
59
 
54
- def __init__(self):
60
+ def __init__(
61
+ self
62
+ ) -> None:
55
63
  """
56
64
  Initializes a new instance of the container.
57
65
 
58
66
  This constructor sets up the internal dictionaries for bindings and aliases,
59
67
  ensuring that these are only initialized once per class. The initialization
60
68
  is guarded by the `_initialized` class attribute to prevent redundant setup.
69
+ The container also registers itself as a service to allow for injection.
61
70
 
62
71
  Notes
63
72
  -----
64
73
  - The `__bindings` dictionary is used to store service bindings.
65
74
  - The `__aliasses` dictionary is used to store service aliases.
66
75
  - Initialization occurs only once per class, regardless of the number of instances.
76
+ - The container registers itself under the IContainer interface to allow for dependency injection.
67
77
  """
68
78
  if not self.__class__._initialized:
69
79
  self.__bindings = {}
70
80
  self.__aliasses = {}
71
81
  self.__class__._initialized = True
82
+ self.instance(IContainer, self)
72
83
 
73
84
  def __dropService(
74
85
  self,
@@ -379,6 +390,48 @@ class Container:
379
390
  "Please ensure that all abstract methods are implemented."
380
391
  )
381
392
 
393
+ def __getService(
394
+ self,
395
+ abstract_or_alias: Any
396
+ ) -> Binding:
397
+ """
398
+ Retrieves the binding for the requested abstract type or alias.
399
+
400
+ Parameters
401
+ ----------
402
+ abstract_or_alias : Any
403
+ The abstract class, interface, or alias (str) to retrieve.
404
+
405
+ Returns
406
+ -------
407
+ Binding
408
+ The binding associated with the requested abstract type or alias.
409
+ """
410
+ return self.__bindings.get(abstract_or_alias) or self.__aliasses.get(abstract_or_alias)
411
+
412
+ def __getFirstService(
413
+ self,
414
+ abstract_or_aliasses: list
415
+ ) -> Binding:
416
+ """
417
+ Retrieves the first binding from a list of abstract types or aliases.
418
+
419
+ Parameters
420
+ ----------
421
+ abstract_or_aliasses : list
422
+ A list of abstract classes, interfaces, or aliases (str) to retrieve.
423
+
424
+ Returns
425
+ -------
426
+ Binding
427
+ The first binding found in the container for the provided abstract types or aliases.
428
+ """
429
+ for item in abstract_or_aliasses:
430
+ binding = self.__getService(item)
431
+ if binding:
432
+ return binding
433
+ return None
434
+
382
435
  def transient(
383
436
  self,
384
437
  abstract: Callable[..., Any],
@@ -715,7 +768,7 @@ class Container:
715
768
  def function(
716
769
  self,
717
770
  alias: str,
718
- function: Callable[..., Any],
771
+ fn: Callable[..., Any],
719
772
  *,
720
773
  lifetime: Lifetime = Lifetime.TRANSIENT
721
774
  ) -> bool:
@@ -726,7 +779,7 @@ class Container:
726
779
  ----------
727
780
  alias : str
728
781
  The alias to register the function under.
729
- function : Callable[..., Any]
782
+ fn : Callable[..., Any]
730
783
  The function or factory to register.
731
784
  lifetime : Lifetime, optional
732
785
  The lifetime of the function registration (default is TRANSIENT).
@@ -763,10 +816,10 @@ class Container:
763
816
  self.__ensureAliasType(alias)
764
817
 
765
818
  # Validate that the function is callable
766
- self.__ensureIsCallable(function)
819
+ self.__ensureIsCallable(fn)
767
820
 
768
821
  # Inspect the function signature
769
- params = ReflectionCallable(function).getDependencies()
822
+ params = ReflectionCallable(fn).getDependencies()
770
823
 
771
824
  # If the function requires arguments, only allow TRANSIENT
772
825
  if (len(params.resolved) + len(params.unresolved)) > 0 and lifetime != Lifetime.TRANSIENT:
@@ -779,7 +832,7 @@ class Container:
779
832
 
780
833
  # Register the function with the specified alias and lifetime
781
834
  self.__bindings[alias] = Binding(
782
- function=function,
835
+ function=fn,
783
836
  lifetime=lifetime,
784
837
  alias=alias
785
838
  )
@@ -819,8 +872,8 @@ class Container:
819
872
  def make(
820
873
  self,
821
874
  abstract_or_alias: Any,
822
- *args,
823
- **kwargs
875
+ *args: tuple,
876
+ **kwargs: dict
824
877
  ) -> Any:
825
878
  """
826
879
  Resolves and returns an instance of the requested service.
@@ -844,11 +897,341 @@ class Container:
844
897
  OrionisContainerException
845
898
  If the requested service is not registered in the container.
846
899
  """
847
- if not self.bound(abstract_or_alias):
900
+ # Retrieve the binding for the requested abstract or alias
901
+ binding = self.__getService(abstract_or_alias)
902
+
903
+ # Check if the requested service is registered in the container
904
+ if not binding:
848
905
  raise OrionisContainerException(
849
906
  f"The requested service '{abstract_or_alias}' is not registered in the container."
850
907
  )
851
908
 
852
- binding = self.__bindings.get(abstract_or_alias) or self.__aliasses.get(abstract_or_alias)
909
+ # Handle based on binding type and lifetime
910
+ if binding.lifetime == Lifetime.TRANSIENT:
911
+ return self.__resolveTransient(binding, *args, **kwargs)
912
+ elif binding.lifetime == Lifetime.SINGLETON:
913
+ return self.__resolveSingleton(binding, *args, **kwargs)
914
+ elif binding.lifetime == Lifetime.SCOPED:
915
+ # TODO: Implement scoped lifetime resolution
916
+ raise OrionisContainerException(
917
+ "Scoped lifetime resolution is not yet implemented."
918
+ )
919
+
920
+ def __resolveTransient(self, binding: Binding, *args, **kwargs) -> Any:
921
+ """
922
+ Resolves a service with transient lifetime.
923
+
924
+ Parameters
925
+ ----------
926
+ binding : Binding
927
+ The binding to resolve.
928
+ *args : tuple
929
+ Positional arguments to pass to the constructor.
930
+ **kwargs : dict
931
+ Keyword arguments to pass to the constructor.
932
+
933
+ Returns
934
+ -------
935
+ Any
936
+ A new instance of the requested service.
937
+ """
938
+
939
+ # Check if the binding has a concrete class or function defined
940
+ if binding.concrete:
941
+ if args or kwargs:
942
+ return self.__instantiateConcreteWithArgs(binding.concrete, *args, **kwargs)
943
+ else:
944
+ return self.__instantiateConcreteReflective(binding.concrete)
945
+
946
+ # If the binding has a function defined
947
+ elif binding.function:
948
+ if args or kwargs:
949
+ return self.__instantiateCallableWithArgs(binding.function, *args, **kwargs)
950
+ else:
951
+ return self.__instantiateCallableReflective(binding.function)
952
+
953
+ # If neither concrete class nor function is defined
954
+ else:
955
+ raise OrionisContainerException(
956
+ "Cannot resolve transient binding: neither a concrete class nor a function is defined."
957
+ )
958
+
959
+ def __resolveSingleton(self, binding: Binding, *args, **kwargs) -> Any:
960
+ """
961
+ Resolves a service with singleton lifetime.
962
+
963
+ Parameters
964
+ ----------
965
+ binding : Binding
966
+ The binding to resolve.
967
+ *args : tuple
968
+ Positional arguments to pass to the constructor (only used if instance doesn't exist yet).
969
+ **kwargs : dict
970
+ Keyword arguments to pass to the constructor (only used if instance doesn't exist yet).
971
+
972
+ Returns
973
+ -------
974
+ Any
975
+ The singleton instance of the requested service.
976
+ """
977
+ # Return existing instance if available
978
+ if binding.instance:
979
+ return binding.instance
980
+
981
+ # Create instance if needed
982
+ if binding.concrete:
983
+ if args or kwargs:
984
+ binding.instance = self.__instantiateConcreteWithArgs(binding.concrete, *args, **kwargs)
985
+ else:
986
+ binding.instance = self.__instantiateConcreteReflective(binding.concrete)
987
+ return binding.instance
988
+
989
+ # If the binding has a function defined
990
+ elif binding.function:
991
+ if args or kwargs:
992
+ result = self.__instantiateCallableWithArgs(binding.function, *args, **kwargs)
993
+ else:
994
+ result = self.__instantiateCallableReflective(binding.function)
995
+
996
+ # Store the result directly as the singleton instance
997
+ # We don't automatically invoke factory function results anymore
998
+ binding.instance = result
999
+ return binding.instance
1000
+
1001
+ # If neither concrete class nor function is defined
1002
+ else:
1003
+ raise OrionisContainerException(
1004
+ "Cannot resolve singleton binding: neither a concrete class, instance, nor function is defined."
1005
+ )
1006
+
1007
+ def __instantiateConcreteWithArgs(self, concrete: Callable[..., Any], *args, **kwargs) -> Any:
1008
+ """
1009
+ Instantiates a concrete class with the provided arguments.
1010
+
1011
+ Parameters
1012
+ ----------
1013
+ concrete : Callable[..., Any]
1014
+ Class to instantiate.
1015
+ *args : tuple
1016
+ Positional arguments to pass to the constructor.
1017
+ **kwargs : dict
1018
+ Keyword arguments to pass to the constructor.
853
1019
 
854
- print(binding)
1020
+ Returns
1021
+ -------
1022
+ object
1023
+ A new instance of the specified concrete class.
1024
+ """
1025
+
1026
+ # try to instantiate the concrete class with the provided arguments
1027
+ try:
1028
+
1029
+ # If the concrete is a class, instantiate it directly
1030
+ return concrete(*args, **kwargs)
1031
+
1032
+ except TypeError as e:
1033
+
1034
+ # If instantiation fails, use ReflectionConcrete to get class name and constructor signature
1035
+ rf_concrete = ReflectionConcrete(concrete)
1036
+ class_name = rf_concrete.getClassName()
1037
+ signature = rf_concrete.getConstructorSignature()
1038
+
1039
+ # Raise an exception with detailed information about the failure
1040
+ raise OrionisContainerException(
1041
+ f"Failed to instantiate [{class_name}] with the provided arguments: {e}\n"
1042
+ f"Expected constructor signature: [{signature}]"
1043
+ ) from e
1044
+
1045
+ def __instantiateCallableWithArgs(self, fn: Callable[..., Any], *args, **kwargs) -> Any:
1046
+ """
1047
+ Invokes a callable with the provided arguments.
1048
+
1049
+ Parameters
1050
+ ----------
1051
+ fn : Callable[..., Any]
1052
+ The callable to invoke.
1053
+ *args : tuple
1054
+ Positional arguments to pass to the callable.
1055
+ **kwargs : dict
1056
+ Keyword arguments to pass to the callable.
1057
+
1058
+ Returns
1059
+ -------
1060
+ Any
1061
+ The result of the callable.
1062
+ """
1063
+
1064
+ # Try to invoke the callable with the provided arguments
1065
+ try:
1066
+
1067
+ # If the callable is a function, invoke it directly
1068
+ return fn(*args, **kwargs)
1069
+
1070
+ except TypeError as e:
1071
+
1072
+ # If invocation fails, use ReflectionCallable to get function name and signature
1073
+ rf_callable = ReflectionCallable(fn)
1074
+ function_name = rf_callable.getName()
1075
+ signature = rf_callable.getSignature()
1076
+
1077
+ # Raise an exception with detailed information about the failure
1078
+ raise OrionisContainerException(
1079
+ f"Failed to invoke function [{function_name}] with the provided arguments: {e}\n"
1080
+ f"Expected function signature: [{signature}]"
1081
+ ) from e
1082
+
1083
+ def __instantiateConcreteReflective(self, concrete: Callable[..., Any]) -> Any:
1084
+ """
1085
+ Instantiates a concrete class reflectively, resolving its dependencies from the container.
1086
+
1087
+ Parameters
1088
+ ----------
1089
+ concrete : Callable[..., Any]
1090
+ The concrete class to instantiate.
1091
+
1092
+ Returns
1093
+ -------
1094
+ Any
1095
+ A new instance of the concrete class.
1096
+ """
1097
+ # Resolve dependencies for the concrete class
1098
+ params = self.__resolveDependencies(concrete, is_class=True)
1099
+
1100
+ # Instantiate the concrete class with resolved dependencies
1101
+ return concrete(**params)
1102
+
1103
+ def __instantiateCallableReflective(self, fn: Callable[..., Any]) -> Any:
1104
+ """
1105
+ Invokes a callable reflectively, resolving its dependencies from the container.
1106
+
1107
+ Parameters
1108
+ ----------
1109
+ fn : Callable[..., Any]
1110
+ The callable to invoke.
1111
+
1112
+ Returns
1113
+ -------
1114
+ Any
1115
+ The result of the callable.
1116
+ """
1117
+
1118
+ # Resolve dependencies for the callable
1119
+ params = self.__resolveDependencies(fn, is_class=False)
1120
+
1121
+ # Invoke the callable with resolved dependencies
1122
+ return fn(**params)
1123
+
1124
+ def __resolveDependencies(
1125
+ self,
1126
+ target: Callable[..., Any],
1127
+ *,
1128
+ is_class: bool = False
1129
+ ) -> dict:
1130
+ """
1131
+ Resolves dependencies for a target callable or class.
1132
+
1133
+ Parameters
1134
+ ----------
1135
+ target : Callable[..., Any]
1136
+ The target callable or class whose dependencies to resolve.
1137
+ is_class : bool, optional
1138
+ Whether the target is a class (True) or a callable (False).
1139
+
1140
+ Returns
1141
+ -------
1142
+ dict
1143
+ A dictionary of resolved dependencies.
1144
+ """
1145
+ try:
1146
+
1147
+ # Use ReflectionConcrete for classes and ReflectionCallable for callables
1148
+ if is_class:
1149
+ reflection = ReflectionConcrete(target)
1150
+ dependencies = reflection.getConstructorDependencies()
1151
+ name = reflection.getClassName()
1152
+
1153
+ # If the target is a callable, use ReflectionCallable
1154
+ else:
1155
+ reflection = ReflectionCallable(target)
1156
+ dependencies = reflection.getDependencies()
1157
+ name = reflection.getName()
1158
+
1159
+ # Check for unresolved dependencies
1160
+ if dependencies.unresolved:
1161
+ unresolved_args = ', '.join(dependencies.unresolved)
1162
+ raise OrionisContainerException(
1163
+ f"Cannot resolve '{name}' because the following required arguments are missing: [{unresolved_args}]."
1164
+ )
1165
+
1166
+ # Resolve dependencies
1167
+ params = {}
1168
+ for param_name, dep in dependencies.resolved.items():
1169
+
1170
+ # If the dependency is a ResolvedDependency, resolve it
1171
+ if isinstance(dep, ResolvedDependency):
1172
+
1173
+ # If the dependency is a built-in type, raise an exception
1174
+ if dep.module_name == 'builtins':
1175
+ raise OrionisContainerException(
1176
+ f"Cannot resolve '{name}' because parameter '{param_name}' depends on built-in type '{dep.type.__name__}'."
1177
+ )
1178
+
1179
+ # Try to resolve from container
1180
+ service = self.__getFirstService([dep.type, dep.full_class_path])
1181
+ if service:
1182
+ params[param_name] = self.make(service.alias)
1183
+
1184
+ # Try to instantiate directly if it's a concrete class
1185
+ elif ReflectionConcrete.isConcreteClass(dep.type):
1186
+ params[param_name] = dep.type(**self.__resolveDependencies(dep.type, is_class=True))
1187
+
1188
+ # Try to call directly if it's a callable
1189
+ elif callable(dep.type) and not isinstance(dep.type, type):
1190
+ params[param_name] = dep.type(**self.__resolveDependencies(dep.type, is_class=False))
1191
+
1192
+ # If the dependency cannot be resolved, raise an exception
1193
+ else:
1194
+ raise OrionisContainerException(
1195
+ f"Cannot resolve dependency '{param_name}' of type '{dep.type.__name__}' for '{name}'."
1196
+ )
1197
+ else:
1198
+ # Use default value
1199
+ params[param_name] = dep
1200
+
1201
+ # Return the resolved parameters
1202
+ return params
1203
+
1204
+ except ImportError as e:
1205
+
1206
+ # Extract module name from the error message if possible
1207
+ import_msg = str(e)
1208
+ module_name = target.__module__ if hasattr(target, '__module__') else "unknown module"
1209
+
1210
+ # Check for potential circular import patterns
1211
+ if "circular import" in import_msg.lower() or "cannot import name" in import_msg.lower():
1212
+ raise OrionisContainerException(
1213
+ f"Circular import detected while resolving dependencies for '{target.__name__}' in module '{module_name}'.\n"
1214
+ f"This typically happens when two modules import each other. Consider:\n"
1215
+ f"1. Restructuring your code to avoid circular dependencies\n"
1216
+ f"2. Using delayed imports inside methods rather than at module level\n"
1217
+ f"3. Using dependency injection to break the cycle\n"
1218
+ f"Original error: {import_msg}"
1219
+ ) from e
1220
+ else:
1221
+ raise OrionisContainerException(
1222
+ f"Import error while resolving dependencies for '{target.__name__}' in module '{module_name}':\n"
1223
+ f"{import_msg}"
1224
+ ) from e
1225
+
1226
+ except Exception as e:
1227
+
1228
+ # Get more context about where the error occurred
1229
+ target_type = "class" if isinstance(target, type) else "function"
1230
+ target_name = target.__name__ if hasattr(target, '__name__') else str(target)
1231
+ module_name = target.__module__ if hasattr(target, '__module__') else "unknown module"
1232
+
1233
+ raise OrionisContainerException(
1234
+ f"Error resolving dependencies for {target_type} '{target_name}' in '{module_name}':\n"
1235
+ f"{str(e)}\n"
1236
+ f"Check that all dependencies are properly registered in the container."
1237
+ ) from e
@@ -0,0 +1,202 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any, Callable
3
+ from orionis.container.enums.lifetimes import Lifetime
4
+
5
+ class IContainer(ABC):
6
+ """
7
+ IContainer is an interface that defines the structure for a dependency injection container.
8
+ It provides methods for registering and resolving services with different lifetimes.
9
+ """
10
+
11
+ @abstractmethod
12
+ def singleton(
13
+ self,
14
+ abstract: Callable[..., Any],
15
+ concrete: Callable[..., Any],
16
+ *,
17
+ alias: str = None,
18
+ enforce_decoupling: bool = False
19
+ ) -> bool:
20
+ """
21
+ Register a service as a singleton.
22
+
23
+ Parameters
24
+ ----------
25
+ abstract : Callable[..., Any]
26
+ The abstract base type or interface to be bound.
27
+ concrete : Callable[..., Any]
28
+ The concrete implementation to associate with the abstract type.
29
+ alias : str, optional
30
+ An alternative name to register the service under.
31
+ enforce_decoupling : bool, optional
32
+ Whether to enforce that concrete is not a subclass of abstract.
33
+
34
+ Returns
35
+ -------
36
+ bool
37
+ True if the service was registered successfully.
38
+ """
39
+ pass
40
+
41
+ @abstractmethod
42
+ def transient(
43
+ self,
44
+ abstract: Callable[..., Any],
45
+ concrete: Callable[..., Any],
46
+ *,
47
+ alias: str = None,
48
+ enforce_decoupling: bool = False
49
+ ) -> bool:
50
+ """
51
+ Register a service as transient.
52
+
53
+ Parameters
54
+ ----------
55
+ abstract : Callable[..., Any]
56
+ The abstract base type or interface to be bound.
57
+ concrete : Callable[..., Any]
58
+ The concrete implementation to associate with the abstract type.
59
+ alias : str, optional
60
+ An alternative name to register the service under.
61
+ enforce_decoupling : bool, optional
62
+ Whether to enforce that concrete is not a subclass of abstract.
63
+
64
+ Returns
65
+ -------
66
+ bool
67
+ True if the service was registered successfully.
68
+ """
69
+ pass
70
+
71
+ @abstractmethod
72
+ def scoped(
73
+ self,
74
+ abstract: Callable[..., Any],
75
+ concrete: Callable[..., Any],
76
+ *,
77
+ alias: str = None,
78
+ enforce_decoupling: bool = False
79
+ ) -> bool:
80
+ """
81
+ Register a service as scoped.
82
+
83
+ Parameters
84
+ ----------
85
+ abstract : Callable[..., Any]
86
+ The abstract base type or interface to be bound.
87
+ concrete : Callable[..., Any]
88
+ The concrete implementation to associate with the abstract type.
89
+ alias : str, optional
90
+ An alternative name to register the service under.
91
+ enforce_decoupling : bool, optional
92
+ Whether to enforce that concrete is not a subclass of abstract.
93
+
94
+ Returns
95
+ -------
96
+ bool
97
+ True if the service was registered successfully.
98
+ """
99
+ pass
100
+
101
+ @abstractmethod
102
+ def instance(
103
+ self,
104
+ abstract: Callable[..., Any],
105
+ instance: Any,
106
+ *,
107
+ alias: str = None,
108
+ enforce_decoupling: bool = False
109
+ ) -> bool:
110
+ """
111
+ Register an instance of a service.
112
+
113
+ Parameters
114
+ ----------
115
+ abstract : Callable[..., Any]
116
+ The abstract class or interface to associate with the instance.
117
+ instance : Any
118
+ The concrete instance to register.
119
+ alias : str, optional
120
+ An optional alias to register the instance under.
121
+ enforce_decoupling : bool, optional
122
+ Whether to enforce that instance's class is not a subclass of abstract.
123
+
124
+ Returns
125
+ -------
126
+ bool
127
+ True if the instance was successfully registered.
128
+ """
129
+ pass
130
+
131
+ @abstractmethod
132
+ def function(
133
+ self,
134
+ alias: str,
135
+ fn: Callable[..., Any],
136
+ *,
137
+ lifetime: Lifetime = Lifetime.TRANSIENT
138
+ ) -> bool:
139
+ """
140
+ Register a function as a service.
141
+
142
+ Parameters
143
+ ----------
144
+ alias : str
145
+ The alias to register the function under.
146
+ fn : Callable[..., Any]
147
+ The function or factory to register.
148
+ lifetime : Lifetime, optional
149
+ The lifetime of the function registration (default is TRANSIENT).
150
+
151
+ Returns
152
+ -------
153
+ bool
154
+ True if the function was registered successfully.
155
+ """
156
+ pass
157
+
158
+ @abstractmethod
159
+ def make(
160
+ self,
161
+ abstract_or_alias: Any,
162
+ *args: tuple,
163
+ **kwargs: dict
164
+ ) -> Any:
165
+ """
166
+ Resolve a service from the container.
167
+
168
+ Parameters
169
+ ----------
170
+ abstract_or_alias : Any
171
+ The abstract class, interface, or alias (str) to resolve.
172
+ *args : tuple
173
+ Positional arguments to pass to the constructor.
174
+ **kwargs : dict
175
+ Keyword arguments to pass to the constructor.
176
+
177
+ Returns
178
+ -------
179
+ Any
180
+ An instance of the requested service.
181
+ """
182
+ pass
183
+
184
+ @abstractmethod
185
+ def bound(
186
+ self,
187
+ abstract_or_alias: Any
188
+ ) -> bool:
189
+ """
190
+ Check if a service is registered in the container.
191
+
192
+ Parameters
193
+ ----------
194
+ abstract_or_alias : Any
195
+ The abstract class, interface, or alias (str) to check.
196
+
197
+ Returns
198
+ -------
199
+ bool
200
+ True if the service is registered, False otherwise.
201
+ """
202
+ pass
@@ -5,7 +5,7 @@
5
5
  NAME = "orionis"
6
6
 
7
7
  # Current version of the framework
8
- VERSION = "0.318.0"
8
+ VERSION = "0.319.0"
9
9
 
10
10
  # Full name of the author or maintainer of the project
11
11
  AUTHOR = "Raul Mauricio Uñate Castro"
@@ -130,6 +130,20 @@ class ReflectionCallable:
130
130
  return Coroutine(self.__function(*args, **kwargs)).run()
131
131
  return self.__function(*args, **kwargs)
132
132
 
133
+ def getSignature(self) -> inspect.Signature:
134
+ """
135
+ Retrieve the signature of the callable function.
136
+ Returns
137
+ -------
138
+ inspect.Signature
139
+ An `inspect.Signature` object representing the callable's signature.
140
+ Notes
141
+ -----
142
+ This method provides detailed information about the parameters of the callable,
143
+ including their names, default values, and annotations.
144
+ """
145
+ return inspect.signature(self.__function)
146
+
133
147
  def getDependencies(self) -> CallableDependency:
134
148
  """
135
149
  Analyzes the callable associated with this instance and retrieves its dependencies.
@@ -1442,6 +1442,17 @@ class ReflectionConcrete(IReflectionConcrete):
1442
1442
 
1443
1443
  return prop.fget.__doc__ if prop.fget else None
1444
1444
 
1445
+ def getConstructorSignature(self) -> inspect.Signature:
1446
+ """
1447
+ Get the signature of the constructor of the instance's class.
1448
+
1449
+ Returns
1450
+ -------
1451
+ inspect.Signature
1452
+ The signature of the constructor
1453
+ """
1454
+ return inspect.signature(self._concrete.__init__)
1455
+
1445
1456
  def getConstructorDependencies(self) -> ClassDependency:
1446
1457
  """
1447
1458
  Get the resolved and unresolved dependencies from the constructor of the instance's class.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orionis
3
- Version: 0.318.0
3
+ Version: 0.319.0
4
4
  Summary: Orionis Framework – Elegant, Fast, and Powerful.
5
5
  Home-page: https://github.com/orionis-framework/framework
6
6
  Author: Raul Mauricio Uñate Castro
@@ -135,7 +135,8 @@ orionis/console/output/console.py,sha256=TE_Hl720ADd82dbERFSWhkoQRukDQZmETSw4nkw
135
135
  orionis/console/output/executor.py,sha256=bdvkzW2-buy0BPpy2r5qUGrRFW2Ay6k-5rSeHb0gQ3o,3352
136
136
  orionis/console/output/progress_bar.py,sha256=vFy582z6VJS46LV6tuyrmr9qvdVeTEtw3hyNcEHezeg,3088
137
137
  orionis/console/output/styles.py,sha256=6a4oQCOBOKMh2ARdeq5GlIskJ3wjiylYmh66tUKKmpQ,4053
138
- orionis/container/container.py,sha256=TNnevmbvK2e664bl8r1HYk5CHGDsP9J9N_3ZuAHKb6c,30105
138
+ orionis/container/container.py,sha256=ZL3S0HyAt8Hm58dPjltNMCSMNNP30VR61ByslzmCGgs,45066
139
+ orionis/container/contracts/container.py,sha256=LkZ5til_3Um8ctCVTwuO36HkysL59saKwUzXR5cWUBs,5750
139
140
  orionis/container/entities/binding.py,sha256=Qp6Lf4XUDp2NjqXDAC2lzvhOFQWiBDKiGFcKfwb4axw,4342
140
141
  orionis/container/enums/lifetimes.py,sha256=RqQmugMIB1Ev_j_vFLcWorndm-to7xg4stQ7yKFDdDw,190
141
142
  orionis/container/exceptions/container_exception.py,sha256=goTDEwC70xTMD2qppN8KV-xyR0Nps218OD4D1LZ2-3s,470
@@ -232,7 +233,7 @@ orionis/foundation/contracts/config.py,sha256=Rpz6U6t8OXHO9JJKSTnCimytXE-tfCB-1i
232
233
  orionis/foundation/exceptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
233
234
  orionis/foundation/exceptions/integrity.py,sha256=mc4pL1UMoYRHEmphnpW2oGk5URhu7DJRREyzHaV-cs8,472
234
235
  orionis/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
235
- orionis/metadata/framework.py,sha256=W5PbEW1Zw29V6NsVuzd9ZafK7iR0638kO2Jm0wIwNGw,4960
236
+ orionis/metadata/framework.py,sha256=MyXQ31_zvD5irlN_XvuSicVccDNBPb64XCKc8qujCEc,4960
236
237
  orionis/metadata/package.py,sha256=tqLfBRo-w1j_GN4xvzUNFyweWYFS-qhSgAEc-AmCH1M,5452
237
238
  orionis/patterns/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
238
239
  orionis/patterns/singleton/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -259,9 +260,9 @@ orionis/services/introspection/reflection.py,sha256=6z4VkDICohMIkm9jEd7nmFABwVuU
259
260
  orionis/services/introspection/abstract/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
260
261
  orionis/services/introspection/abstract/reflection_abstract.py,sha256=SPK2X11VvGORxxPOYloaD6hPAvky--obRU4CO1DE4zM,43865
261
262
  orionis/services/introspection/callables/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
262
- orionis/services/introspection/callables/reflection_callable.py,sha256=wjztKcqXIT4J-LPXK_Iszv-VzqHoT9MLp0n-GDMtmgA,5633
263
+ orionis/services/introspection/callables/reflection_callable.py,sha256=0B2B6ZV-ql_aZk97W4Q12MVvi0gwErjekgWaMBxjfV0,6147
263
264
  orionis/services/introspection/concretes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
264
- orionis/services/introspection/concretes/reflection_concrete.py,sha256=1GxD-y8LPGL6kI4Y3XbeLcFjR5Y8cOqbVEPCtPnsuYA,50982
265
+ orionis/services/introspection/concretes/reflection_concrete.py,sha256=SdE2IWEgt30eO9-f_VRNdIZ_OWWidauQzQZQVrXjcXY,51310
265
266
  orionis/services/introspection/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
266
267
  orionis/services/introspection/contracts/reflect_dependencies.py,sha256=5fdImZarC1ixoFM-1JSBx28RvYbY3GGZhDGjar7cvHc,1771
267
268
  orionis/services/introspection/contracts/reflection_abstract.py,sha256=-ugpFcAkGTlk0Md5ft8NrvupnlfVji8QZjGYqWBxqeY,22370
@@ -344,7 +345,7 @@ orionis/test/suite/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
344
345
  orionis/test/suite/test_unit.py,sha256=MWgW8dRCRyT1XZ5LsbXQ7-KVPReasoXwzEEL1EWWfE4,52190
345
346
  orionis/test/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
346
347
  orionis/test/view/render.py,sha256=jXZkbITBknbUwm_mD8bcTiwLDvsFkrO9qrf0ZgPwqxc,4903
347
- orionis-0.318.0.dist-info/licenses/LICENCE,sha256=-_4cF2EBKuYVS_SQpy1uapq0oJPUU1vl_RUWSy2jJTo,1111
348
+ orionis-0.319.0.dist-info/licenses/LICENCE,sha256=-_4cF2EBKuYVS_SQpy1uapq0oJPUU1vl_RUWSy2jJTo,1111
348
349
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
349
350
  tests/example/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
350
351
  tests/example/test_example.py,sha256=kvWgiW3ADEZf718dGsMPtDh_rmOSx1ypEInKm7_6ZPQ,601
@@ -445,8 +446,8 @@ tests/support/wrapper/test_services_wrapper_docdict.py,sha256=yeVwl-VcwkWSQYyxZu
445
446
  tests/testing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
446
447
  tests/testing/test_testing_result.py,sha256=MrGK3ZimedL0b5Ydu69Dg8Iul017AzLTm7VPxpXlpfU,4315
447
448
  tests/testing/test_testing_unit.py,sha256=DjLBtvVn8B1KlVJNNkstBT8_csA1yeaMqnGrbanN_J4,7438
448
- orionis-0.318.0.dist-info/METADATA,sha256=_bC7iHlD1eWAOWCuGO8KoLXLlrBz_2nEO7fsbBa2uvI,4772
449
- orionis-0.318.0.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
450
- orionis-0.318.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
451
- orionis-0.318.0.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
452
- orionis-0.318.0.dist-info/RECORD,,
449
+ orionis-0.319.0.dist-info/METADATA,sha256=426gql1AFezl4n3-_ORGM8wdkUYcEsZr8n3ykl6ruOI,4772
450
+ orionis-0.319.0.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
451
+ orionis-0.319.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
452
+ orionis-0.319.0.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
453
+ orionis-0.319.0.dist-info/RECORD,,