orionis 0.21.0__py3-none-any.whl → 0.23.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/bootstrap/config/register.py +1 -1
- orionis/luminate/container/container.py +337 -302
- orionis/luminate/container/exception.py +18 -0
- orionis/luminate/contracts/bootstrap/config/register_interface.py +2 -2
- orionis/luminate/contracts/container/container_interface.py +158 -88
- {orionis-0.21.0.dist-info → orionis-0.23.0.dist-info}/METADATA +1 -1
- {orionis-0.21.0.dist-info → orionis-0.23.0.dist-info}/RECORD +12 -12
- {orionis-0.21.0.dist-info → orionis-0.23.0.dist-info}/LICENCE +0 -0
- {orionis-0.21.0.dist-info → orionis-0.23.0.dist-info}/WHEEL +0 -0
- {orionis-0.21.0.dist-info → orionis-0.23.0.dist-info}/entry_points.txt +0 -0
- {orionis-0.21.0.dist-info → orionis-0.23.0.dist-info}/top_level.txt +0 -0
    
        orionis/framework.py
    CHANGED
    
    
| @@ -1,385 +1,420 @@ | |
| 1 1 | 
             
            import inspect
         | 
| 2 | 
            -
            from  | 
| 2 | 
            +
            from collections import deque
         | 
| 3 | 
            +
            from threading import Lock
         | 
| 4 | 
            +
            from typing import Callable, Any, Dict
         | 
| 5 | 
            +
            from orionis.luminate.container.exception import OrionisContainerException, OrionisContainerValueError, OrionisContainerTypeError
         | 
| 3 6 | 
             
            from orionis.luminate.container.types import Types
         | 
| 4 | 
            -
            from orionis.luminate.tools.dot_dict import DotDict
         | 
| 5 7 | 
             
            from orionis.luminate.contracts.container.container_interface import IContainer
         | 
| 6 | 
            -
             | 
| 8 | 
            +
             | 
| 9 | 
            +
            BINDING = 'binding'
         | 
| 10 | 
            +
            TRANSIENT = 'transient'
         | 
| 11 | 
            +
            SINGLETON = 'singleton'
         | 
| 12 | 
            +
            SCOPED = 'scoped'
         | 
| 13 | 
            +
            INSTANCE = 'instance'
         | 
| 7 14 |  | 
| 8 15 | 
             
            class Container(IContainer):
         | 
| 9 | 
            -
                """ | 
| 16 | 
            +
                """
         | 
| 17 | 
            +
                Service container and dependency injection manager.
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                This class follows the singleton pattern to manage service bindings, instances,
         | 
| 20 | 
            +
                and different lifecycle types such as transient, singleton, and scoped.
         | 
| 21 | 
            +
                """
         | 
| 10 22 |  | 
| 11 23 | 
             
                _instance = None
         | 
| 24 | 
            +
                _lock = Lock()
         | 
| 12 25 |  | 
| 13 26 | 
             
                def __new__(cls):
         | 
| 14 27 | 
             
                    if cls._instance is None:
         | 
| 15 | 
            -
                        cls. | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
                        # Initialize the PrimitiveTypes validator
         | 
| 27 | 
            -
                        cls._instance._primitive_types_validator = Types()
         | 
| 28 | 
            +
                        with cls._lock:
         | 
| 29 | 
            +
                            if cls._instance is None:
         | 
| 30 | 
            +
                                cls._instance = super().__new__(cls)
         | 
| 31 | 
            +
                                cls._instance._bindings = {}
         | 
| 32 | 
            +
                                cls._instance._transients = {}
         | 
| 33 | 
            +
                                cls._instance._singletons = {}
         | 
| 34 | 
            +
                                cls._instance._scoped_services = {}
         | 
| 35 | 
            +
                                cls._instance._instances = {}
         | 
| 36 | 
            +
                                cls._instance._aliases = {}
         | 
| 37 | 
            +
                                cls._instance._scoped_instances = {}
         | 
| 38 | 
            +
                                cls._instance._validate_types = Types()
         | 
| 28 39 | 
             
                    return cls._instance
         | 
| 29 40 |  | 
| 30 | 
            -
                def  | 
| 41 | 
            +
                def _newRequest(self) -> None:
         | 
| 31 42 | 
             
                    """
         | 
| 32 | 
            -
                     | 
| 33 | 
            -
             | 
| 34 | 
            -
                    Args:
         | 
| 35 | 
            -
                        section (str): _description_
         | 
| 36 | 
            -
                        data (dict): _description_
         | 
| 43 | 
            +
                    Reset scoped instances at the beginning of a new request.
         | 
| 37 44 | 
             
                    """
         | 
| 45 | 
            +
                    self._scoped_instances = {}
         | 
| 38 46 |  | 
| 39 | 
            -
             | 
| 40 | 
            -
                     | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
                     | 
| 44 | 
            -
                     | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
                     | 
| 50 | 
            -
             | 
| 47 | 
            +
                def _ensureNotMain(self, concrete: Callable[..., Any]) -> str:
         | 
| 48 | 
            +
                    """
         | 
| 49 | 
            +
                    Ensure that a class is not defined in the main script.
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                    Parameters
         | 
| 52 | 
            +
                    ----------
         | 
| 53 | 
            +
                    concrete : Callable[..., Any]
         | 
| 54 | 
            +
                        The class or function to check.
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                    Returns
         | 
| 57 | 
            +
                    -------
         | 
| 58 | 
            +
                    str
         | 
| 59 | 
            +
                        The fully qualified name of the class.
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                    Raises
         | 
| 62 | 
            +
                    ------
         | 
| 63 | 
            +
                    OrionisContainerValueError
         | 
| 64 | 
            +
                        If the class is defined in the main module.
         | 
| 65 | 
            +
                    """
         | 
| 66 | 
            +
                    if concrete.__module__ == "__main__":
         | 
| 67 | 
            +
                        raise OrionisContainerValueError(
         | 
| 68 | 
            +
                            "Cannot register a class from the main module in the container."
         | 
| 69 | 
            +
                        )
         | 
| 70 | 
            +
                    return f"{concrete.__module__}.{concrete.__name__}"
         | 
| 51 71 |  | 
| 52 | 
            -
                def  | 
| 53 | 
            -
                    """ | 
| 72 | 
            +
                def _ensureUniqueService(self, obj: Any) -> None:
         | 
| 73 | 
            +
                    """
         | 
| 74 | 
            +
                    Ensure that a service is not already registered.
         | 
| 54 75 |  | 
| 55 | 
            -
                     | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 76 | 
            +
                    Parameters
         | 
| 77 | 
            +
                    ----------
         | 
| 78 | 
            +
                    obj : Any
         | 
| 79 | 
            +
                        The service to check.
         | 
| 58 80 |  | 
| 59 | 
            -
                    Raises | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 81 | 
            +
                    Raises
         | 
| 82 | 
            +
                    ------
         | 
| 83 | 
            +
                    OrionisContainerValueError
         | 
| 84 | 
            +
                        If the service is already registered.
         | 
| 62 85 | 
             
                    """
         | 
| 86 | 
            +
                    if self.has(obj):
         | 
| 87 | 
            +
                        raise OrionisContainerValueError("The service is already registered in the container.")
         | 
| 63 88 |  | 
| 64 | 
            -
             | 
| 65 | 
            -
                     | 
| 89 | 
            +
                def _ensureIsCallable(self, concrete: Callable[..., Any]) -> None:
         | 
| 90 | 
            +
                    """
         | 
| 91 | 
            +
                    Ensure that the given implementation is callable or instantiable.
         | 
| 66 92 |  | 
| 67 | 
            -
                     | 
| 68 | 
            -
             | 
| 93 | 
            +
                    Parameters
         | 
| 94 | 
            +
                    ----------
         | 
| 95 | 
            +
                    concrete : Callable[..., Any]
         | 
| 96 | 
            +
                        The implementation to check.
         | 
| 69 97 |  | 
| 98 | 
            +
                    Raises
         | 
| 99 | 
            +
                    ------
         | 
| 100 | 
            +
                    OrionisContainerTypeError
         | 
| 101 | 
            +
                        If the implementation is not callable.
         | 
| 102 | 
            +
                    """
         | 
| 70 103 | 
             
                    if not callable(concrete):
         | 
| 71 | 
            -
                        raise  | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
                def transient(self, abstract: str, concrete: Callable[..., Any]) -> None:
         | 
| 76 | 
            -
                    """Registers a service as Transient, creating a new instance on each request.
         | 
| 104 | 
            +
                        raise OrionisContainerTypeError(
         | 
| 105 | 
            +
                            f"The implementation '{str(concrete)}' must be callable or an instantiable class."
         | 
| 106 | 
            +
                        )
         | 
| 77 107 |  | 
| 78 | 
            -
             | 
| 79 | 
            -
                        abstract (str): Name or key of the service to register.
         | 
| 80 | 
            -
                        concrete (Callable[..., Any]): Concrete implementation of the service.
         | 
| 81 | 
            -
             | 
| 82 | 
            -
                    Raises:
         | 
| 83 | 
            -
                        OrionisContainerException: If the service is already registered.
         | 
| 84 | 
            -
                        TypeError: If the implementation is not a callable or instantiable class.
         | 
| 108 | 
            +
                def _ensureIsInstance(self, instance: Any) -> None:
         | 
| 85 109 | 
             
                    """
         | 
| 110 | 
            +
                    Ensure that the given instance is a valid object.
         | 
| 86 111 |  | 
| 87 | 
            -
                     | 
| 88 | 
            -
                     | 
| 112 | 
            +
                    Parameters
         | 
| 113 | 
            +
                    ----------
         | 
| 114 | 
            +
                    instance : Any
         | 
| 115 | 
            +
                        The instance to check.
         | 
| 89 116 |  | 
| 90 | 
            -
                     | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
                    """Registers a service as Singleton, ensuring a single shared instance.
         | 
| 117 | 
            +
                    Raises
         | 
| 118 | 
            +
                    ------
         | 
| 119 | 
            +
                    OrionisContainerValueError
         | 
| 120 | 
            +
                        If the instance is not a valid object.
         | 
| 121 | 
            +
                    """
         | 
| 122 | 
            +
                    if not isinstance(instance, object) or instance.__class__.__module__ in ['builtins', 'abc']:
         | 
| 123 | 
            +
                        raise OrionisContainerValueError(
         | 
| 124 | 
            +
                            f"The instance '{str(instance)}' must be a valid object."
         | 
| 125 | 
            +
                        )
         | 
| 100 126 |  | 
| 127 | 
            +
                def bind(self, concrete: Callable[..., Any]) -> str:
         | 
| 128 | 
            +
                    """
         | 
| 129 | 
            +
                    Bind a callable to the container.
         | 
| 130 | 
            +
                    This method ensures that the provided callable is not the main function,
         | 
| 131 | 
            +
                    is unique within the container, and is indeed callable. It then creates
         | 
| 132 | 
            +
                    a unique key for the callable based on its module and name, and stores
         | 
| 133 | 
            +
                    the callable in the container's bindings.
         | 
| 101 134 | 
             
                    Args:
         | 
| 102 | 
            -
                         | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
                    Raises:
         | 
| 106 | 
            -
                        OrionisContainerException: If the service is already registered.
         | 
| 107 | 
            -
                        TypeError: If the implementation is not a callable or instantiable class.
         | 
| 135 | 
            +
                        concrete (Callable[..., Any]): The callable to be bound to the container.
         | 
| 136 | 
            +
                    Returns:
         | 
| 137 | 
            +
                        str: The unique key generated for the callable.
         | 
| 108 138 | 
             
                    """
         | 
| 139 | 
            +
                    self._ensureNotMain(concrete)
         | 
| 140 | 
            +
                    self._ensureUniqueService(concrete)
         | 
| 141 | 
            +
                    self._ensureIsCallable(concrete)
         | 
| 109 142 |  | 
| 110 | 
            -
                     | 
| 111 | 
            -
                    self. | 
| 112 | 
            -
             | 
| 113 | 
            -
             | 
| 114 | 
            -
                         | 
| 115 | 
            -
             | 
| 116 | 
            -
                     | 
| 117 | 
            -
                        raise TypeError(f"The implementation of '{abstract}' must be a callable or instantiable class.")
         | 
| 118 | 
            -
             | 
| 119 | 
            -
                    self._singletons[abstract] = concrete
         | 
| 143 | 
            +
                    key = f"{concrete.__module__}.{concrete.__name__}"
         | 
| 144 | 
            +
                    self._bindings[key] = {
         | 
| 145 | 
            +
                        'callback': concrete,
         | 
| 146 | 
            +
                        'module': concrete.__module__,
         | 
| 147 | 
            +
                        'name': concrete.__name__,
         | 
| 148 | 
            +
                        'type': BINDING
         | 
| 149 | 
            +
                    }
         | 
| 120 150 |  | 
| 121 | 
            -
             | 
| 122 | 
            -
                    """Registers a service as Scoped, shared within the same request.
         | 
| 151 | 
            +
                    return key
         | 
| 123 152 |  | 
| 153 | 
            +
                def transient(self, concrete: Callable[..., Any]) -> str:
         | 
| 154 | 
            +
                    """
         | 
| 155 | 
            +
                    Registers a transient service in the container.
         | 
| 156 | 
            +
                    A transient service is created each time it is requested.
         | 
| 124 157 | 
             
                    Args:
         | 
| 125 | 
            -
                         | 
| 126 | 
            -
             | 
| 127 | 
            -
             | 
| 128 | 
            -
                    Raises:
         | 
| 129 | 
            -
                        OrionisContainerException: If the service is already registered.
         | 
| 130 | 
            -
                        TypeError: If the implementation is not a callable or instantiable class.
         | 
| 158 | 
            +
                        concrete (Callable[..., Any]): The callable that defines the service.
         | 
| 159 | 
            +
                    Returns:
         | 
| 160 | 
            +
                        str: The unique key generated for the callable.
         | 
| 131 161 | 
             
                    """
         | 
| 162 | 
            +
                    self._ensureNotMain(concrete)
         | 
| 163 | 
            +
                    self._ensureUniqueService(concrete)
         | 
| 164 | 
            +
                    self._ensureIsCallable(concrete)
         | 
| 132 165 |  | 
| 133 | 
            -
                     | 
| 134 | 
            -
                    self. | 
| 166 | 
            +
                    key = f"{concrete.__module__}.{concrete.__name__}"
         | 
| 167 | 
            +
                    self._transients[key] = {
         | 
| 168 | 
            +
                        'callback': concrete,
         | 
| 169 | 
            +
                        'module': concrete.__module__,
         | 
| 170 | 
            +
                        'name': concrete.__name__,
         | 
| 171 | 
            +
                        'type': TRANSIENT
         | 
| 172 | 
            +
                    }
         | 
| 135 173 |  | 
| 136 | 
            -
                     | 
| 137 | 
            -
                        raise OrionisContainerException(f"The service '{abstract}' is already registered in the container.")
         | 
| 138 | 
            -
             | 
| 139 | 
            -
                    if not callable(concrete):
         | 
| 140 | 
            -
                        raise TypeError(f"The implementation of '{abstract}' must be a callable or instantiable class.")
         | 
| 141 | 
            -
             | 
| 142 | 
            -
                    self._scoped_services[abstract] = concrete
         | 
| 143 | 
            -
             | 
| 144 | 
            -
                def instance(self, abstract: str, instance: Any) -> None:
         | 
| 145 | 
            -
                    """Registers a specific instance in the container, allowing it to be reused.
         | 
| 174 | 
            +
                    return key
         | 
| 146 175 |  | 
| 176 | 
            +
                def singleton(self, concrete: Callable[..., Any]) -> str:
         | 
| 177 | 
            +
                    """
         | 
| 178 | 
            +
                    Registers a callable as a singleton in the container.
         | 
| 179 | 
            +
                    This method ensures that the provided callable is not the main module,
         | 
| 180 | 
            +
                    is unique within the container, and is indeed callable. It then registers
         | 
| 181 | 
            +
                    the callable as a singleton, storing it in the container's singleton registry.
         | 
| 147 182 | 
             
                    Args:
         | 
| 148 | 
            -
                         | 
| 149 | 
            -
             | 
| 150 | 
            -
             | 
| 151 | 
            -
                    Raises:
         | 
| 152 | 
            -
                        OrionisContainerException: If the instance is already registered.
         | 
| 153 | 
            -
                        ValueError: If the provided instance is of an unexpected or invalid type.
         | 
| 183 | 
            +
                        concrete (Callable[..., Any]): The callable to be registered as a singleton.
         | 
| 184 | 
            +
                    Returns:
         | 
| 185 | 
            +
                        str: The key under which the singleton is registered in the container.
         | 
| 154 186 | 
             
                    """
         | 
| 187 | 
            +
                    self._ensureNotMain(concrete)
         | 
| 188 | 
            +
                    self._ensureUniqueService(concrete)
         | 
| 189 | 
            +
                    self._ensureIsCallable(concrete)
         | 
| 155 190 |  | 
| 156 | 
            -
                     | 
| 157 | 
            -
                    self. | 
| 158 | 
            -
             | 
| 159 | 
            -
             | 
| 160 | 
            -
                         | 
| 161 | 
            -
             | 
| 162 | 
            -
                     | 
| 163 | 
            -
                        raise ValueError(f"The instance of '{abstract}' must be a valid object.")
         | 
| 164 | 
            -
             | 
| 165 | 
            -
                    self._instances[abstract] = instance
         | 
| 191 | 
            +
                    key = f"{concrete.__module__}.{concrete.__name__}"
         | 
| 192 | 
            +
                    self._singletons[key] = {
         | 
| 193 | 
            +
                        'callback': concrete,
         | 
| 194 | 
            +
                        'module': concrete.__module__,
         | 
| 195 | 
            +
                        'name': concrete.__name__,
         | 
| 196 | 
            +
                        'type': SINGLETON
         | 
| 197 | 
            +
                    }
         | 
| 166 198 |  | 
| 167 | 
            -
             | 
| 168 | 
            -
                    """Checks if a service is registered in the container.
         | 
| 199 | 
            +
                    return key
         | 
| 169 200 |  | 
| 170 | 
            -
             | 
| 171 | 
            -
                        abstract (str): Name or key of the service to check.
         | 
| 172 | 
            -
             | 
| 173 | 
            -
                    Returns:
         | 
| 174 | 
            -
                        bool: True if the service is registered, False otherwise.
         | 
| 175 | 
            -
             | 
| 176 | 
            -
                    Raises:
         | 
| 177 | 
            -
                        ValueError: If the service name (abstract) is not a valid string.
         | 
| 201 | 
            +
                def scoped(self, concrete: Callable[..., Any]) -> str:
         | 
| 178 202 | 
             
                    """
         | 
| 179 | 
            -
                     | 
| 180 | 
            -
                     | 
| 181 | 
            -
             | 
| 182 | 
            -
             | 
| 183 | 
            -
                    # Efficient check if the service is in any of the containers
         | 
| 184 | 
            -
                    return any(abstract in container for container in [
         | 
| 185 | 
            -
                        self._bindings,
         | 
| 186 | 
            -
                        self._transients,
         | 
| 187 | 
            -
                        self._singletons,
         | 
| 188 | 
            -
                        self._scoped_services,
         | 
| 189 | 
            -
                        self._instances
         | 
| 190 | 
            -
                    ])
         | 
| 191 | 
            -
             | 
| 192 | 
            -
                def alias(self, abstract: str, alias: str) -> None:
         | 
| 193 | 
            -
                    """Creates an alias for a registered service, allowing access to the service using an alternative name.
         | 
| 194 | 
            -
             | 
| 203 | 
            +
                    Registers a callable as a scoped service.
         | 
| 204 | 
            +
                    This method ensures that the provided callable is not the main service,
         | 
| 205 | 
            +
                    is unique, and is indeed callable. It then registers the callable in the
         | 
| 206 | 
            +
                    scoped services dictionary with relevant metadata.
         | 
| 195 207 | 
             
                    Args:
         | 
| 196 | 
            -
                         | 
| 197 | 
            -
             | 
| 198 | 
            -
             | 
| 199 | 
            -
                    Raises:
         | 
| 200 | 
            -
                        OrionisContainerException: If the original service is not registered.
         | 
| 201 | 
            -
                        ValueError: If the alias is not a valid string or is already in use.
         | 
| 208 | 
            +
                        concrete (Callable[..., Any]): The callable to be registered as a scoped service.
         | 
| 209 | 
            +
                    Returns:
         | 
| 210 | 
            +
                        str: The key under which the callable is registered in the scoped services dictionary.
         | 
| 202 211 | 
             
                    """
         | 
| 212 | 
            +
                    self._ensureNotMain(concrete)
         | 
| 213 | 
            +
                    self._ensureUniqueService(concrete)
         | 
| 214 | 
            +
                    self._ensureIsCallable(concrete)
         | 
| 203 215 |  | 
| 204 | 
            -
                     | 
| 205 | 
            -
                    self. | 
| 206 | 
            -
             | 
| 207 | 
            -
             | 
| 208 | 
            -
             | 
| 209 | 
            -
                         | 
| 210 | 
            -
             | 
| 211 | 
            -
                    # Check if the original service is registered
         | 
| 212 | 
            -
                    if not self.has(abstract):
         | 
| 213 | 
            -
                        raise OrionisContainerException(f"The service '{abstract}' is not registered in the container.")
         | 
| 214 | 
            -
             | 
| 215 | 
            -
                    # Check if the alias is already in use
         | 
| 216 | 
            -
                    if alias in self._aliases:
         | 
| 217 | 
            -
                        raise ValueError(f"The alias '{alias}' is already in use.")
         | 
| 216 | 
            +
                    key = f"{concrete.__module__}.{concrete.__name__}"
         | 
| 217 | 
            +
                    self._scoped_services[key] = {
         | 
| 218 | 
            +
                        'callback': concrete,
         | 
| 219 | 
            +
                        'module': concrete.__module__,
         | 
| 220 | 
            +
                        'name': concrete.__name__,
         | 
| 221 | 
            +
                        'type': SCOPED
         | 
| 222 | 
            +
                    }
         | 
| 218 223 |  | 
| 219 | 
            -
                     | 
| 220 | 
            -
             | 
| 221 | 
            -
                def make(self, abstract: str):
         | 
| 222 | 
            -
                    """Automatically resolves a dependency, handling instances, singletons, scoped, transients, and aliases.
         | 
| 223 | 
            -
             | 
| 224 | 
            -
                    This method resolves the dependencies of a service and handles the following service types:
         | 
| 225 | 
            -
                    1. **Instances**: Returns a specific instance.
         | 
| 226 | 
            -
                    2. **Singletons**: Returns the same unique instance each time.
         | 
| 227 | 
            -
                    3. **Scoped**: Returns a shared instance within the same request.
         | 
| 228 | 
            -
                    4. **Transients**: Creates a new instance each time.
         | 
| 229 | 
            -
                    5. **Aliases**: Resolves an alias to the original service.
         | 
| 224 | 
            +
                    return key
         | 
| 230 225 |  | 
| 226 | 
            +
                def instance(self, instance: Any) -> str:
         | 
| 227 | 
            +
                    """
         | 
| 228 | 
            +
                    Registers an instance as a singleton in the container.
         | 
| 231 229 | 
             
                    Args:
         | 
| 232 | 
            -
                         | 
| 233 | 
            -
             | 
| 230 | 
            +
                        instance (Any): The instance to be registered as a singleton.
         | 
| 234 231 | 
             
                    Returns:
         | 
| 235 | 
            -
                         | 
| 236 | 
            -
             | 
| 232 | 
            +
                        str: The key under which the instance is registered in the container.
         | 
| 233 | 
            +
                    """
         | 
| 234 | 
            +
                    self._ensureNotMain(instance.__class__)
         | 
| 235 | 
            +
                    self._ensureUniqueService(instance)
         | 
| 236 | 
            +
                    self._ensureIsInstance(instance)
         | 
| 237 | 
            +
             | 
| 238 | 
            +
                    concrete = instance.__class__
         | 
| 239 | 
            +
                    key = f"{concrete.__module__}.{concrete.__name__}"
         | 
| 240 | 
            +
                    self._instances[key] = {
         | 
| 241 | 
            +
                        'instance': instance,
         | 
| 242 | 
            +
                        'module': concrete.__module__,
         | 
| 243 | 
            +
                        'name': concrete.__name__,
         | 
| 244 | 
            +
                        'type': INSTANCE
         | 
| 245 | 
            +
                    }
         | 
| 246 | 
            +
             | 
| 247 | 
            +
                    return key
         | 
| 248 | 
            +
             | 
| 249 | 
            +
                def alias(self, alias: str, concrete: Any) -> None:
         | 
| 250 | 
            +
                    """
         | 
| 251 | 
            +
                    Creates an alias for a registered service.
         | 
| 252 | 
            +
                    Args:
         | 
| 253 | 
            +
                        alias (str): The alias name to be used for the service.
         | 
| 254 | 
            +
                        concrete (Any): The actual service instance or callable to be aliased.
         | 
| 237 255 | 
             
                    Raises:
         | 
| 238 | 
            -
                        OrionisContainerException: If the  | 
| 256 | 
            +
                        OrionisContainerException: If the concrete instance is not a valid object or if the alias is a primitive type.
         | 
| 239 257 | 
             
                    """
         | 
| 240 | 
            -
                     | 
| 241 | 
            -
             | 
| 242 | 
            -
                        return self._instances[abstract]
         | 
| 258 | 
            +
                    if not callable(concrete) and not isinstance(concrete, object):
         | 
| 259 | 
            +
                        raise OrionisContainerException(f"The instance '{str(concrete)}' must be a valid object.")
         | 
| 243 260 |  | 
| 244 | 
            -
                     | 
| 245 | 
            -
             | 
| 246 | 
            -
                        if abstract not in self._instances:
         | 
| 247 | 
            -
                            self._instances[abstract] = self._resolve(self._singletons[abstract])
         | 
| 248 | 
            -
                        return self._instances[abstract]
         | 
| 261 | 
            +
                    if self._instance._validate_types.isPrimitive(alias):
         | 
| 262 | 
            +
                        raise OrionisContainerException(f"Cannot use primitive type '{alias}' as an alias.")
         | 
| 249 263 |  | 
| 250 | 
            -
                     | 
| 251 | 
            -
             | 
| 252 | 
            -
                         | 
| 253 | 
            -
             | 
| 254 | 
            -
                         | 
| 264 | 
            +
                    if isinstance(concrete, object) and concrete.__class__.__module__ not in ['builtins', 'abc']:
         | 
| 265 | 
            +
                        cls_concrete = concrete.__class__
         | 
| 266 | 
            +
                        current_key = f"{cls_concrete.__module__}.{cls_concrete.__name__}"
         | 
| 267 | 
            +
                    elif callable(concrete):
         | 
| 268 | 
            +
                        current_key = f"{concrete.__module__}.{concrete.__name__}"
         | 
| 255 269 |  | 
| 256 | 
            -
                     | 
| 257 | 
            -
                    if abstract in self._transients:
         | 
| 258 | 
            -
                        return self._resolve(self._transients[abstract])
         | 
| 270 | 
            +
                    self._aliases[alias] = current_key
         | 
| 259 271 |  | 
| 260 | 
            -
             | 
| 261 | 
            -
                     | 
| 262 | 
            -
             | 
| 272 | 
            +
                def has(self, obj: Any) -> bool:
         | 
| 273 | 
            +
                    """
         | 
| 274 | 
            +
                    Checks if a service is registered in the container.
         | 
| 263 275 |  | 
| 264 | 
            -
                     | 
| 265 | 
            -
                     | 
| 266 | 
            -
             | 
| 276 | 
            +
                    Parameters
         | 
| 277 | 
            +
                    ----------
         | 
| 278 | 
            +
                    obj : Any
         | 
| 279 | 
            +
                        The service class, instance, or alias to check.
         | 
| 267 280 |  | 
| 268 | 
            -
                     | 
| 281 | 
            +
                    Returns
         | 
| 282 | 
            +
                    -------
         | 
| 283 | 
            +
                    bool
         | 
| 284 | 
            +
                        True if the service is registered, False otherwise.
         | 
| 285 | 
            +
                    """
         | 
| 286 | 
            +
                    if isinstance(obj, str):
         | 
| 287 | 
            +
                        return obj in self._aliases or obj in (
         | 
| 288 | 
            +
                            self._bindings | self._transients | self._singletons | self._scoped_services | self._instances
         | 
| 289 | 
            +
                        )
         | 
| 269 290 |  | 
| 270 | 
            -
             | 
| 271 | 
            -
             | 
| 291 | 
            +
                    if isinstance(obj, object) and obj.__class__.__module__ not in {'builtins', 'abc'}:
         | 
| 292 | 
            +
                        key = f"{obj.__class__.__module__}.{obj.__class__.__name__}"
         | 
| 293 | 
            +
                        return key in self._instances
         | 
| 272 294 |  | 
| 273 | 
            -
                     | 
| 274 | 
            -
                         | 
| 275 | 
            -
                         | 
| 276 | 
            -
             | 
| 295 | 
            +
                    if callable(obj):
         | 
| 296 | 
            +
                        key = f"{obj.__module__}.{obj.__name__}"
         | 
| 297 | 
            +
                        return key in (
         | 
| 298 | 
            +
                            self._bindings | self._transients | self._singletons | self._scoped_services | self._aliases
         | 
| 299 | 
            +
                        )
         | 
| 277 300 |  | 
| 278 | 
            -
                     | 
| 279 | 
            -
                        Any: El resultado de ejecutar el método con las dependencias resueltas.
         | 
| 301 | 
            +
                    return False
         | 
| 280 302 |  | 
| 281 | 
            -
             | 
| 282 | 
            -
                        AttributeError: Si el método no existe en la instancia.
         | 
| 303 | 
            +
                def make(self, abstract: Any) -> Any:
         | 
| 283 304 | 
             
                    """
         | 
| 284 | 
            -
                     | 
| 285 | 
            -
             | 
| 286 | 
            -
             | 
| 287 | 
            -
                     | 
| 288 | 
            -
                     | 
| 289 | 
            -
             | 
| 290 | 
            -
             | 
| 291 | 
            -
                     | 
| 292 | 
            -
             | 
| 293 | 
            -
             | 
| 294 | 
            -
                         | 
| 295 | 
            -
             | 
| 296 | 
            -
             | 
| 297 | 
            -
             | 
| 298 | 
            -
             | 
| 299 | 
            -
             | 
| 300 | 
            -
             | 
| 301 | 
            -
             | 
| 302 | 
            -
                            dependencies[name] = param.default
         | 
| 303 | 
            -
                        else:
         | 
| 304 | 
            -
                            raise OrionisContainerValueError(f"Cannot resolve parameter '{name}' in method '{method_name}'")
         | 
| 305 | 
            -
             | 
| 306 | 
            -
                    return method(**dependencies)
         | 
| 307 | 
            -
             | 
| 305 | 
            +
                    Create and return an instance of a registered service.
         | 
| 306 | 
            +
             | 
| 307 | 
            +
                    Parameters
         | 
| 308 | 
            +
                    ----------
         | 
| 309 | 
            +
                    abstract : Any
         | 
| 310 | 
            +
                        The service class or alias to instantiate.
         | 
| 311 | 
            +
             | 
| 312 | 
            +
                    Returns
         | 
| 313 | 
            +
                    -------
         | 
| 314 | 
            +
                    Any
         | 
| 315 | 
            +
                        An instance of the requested service.
         | 
| 316 | 
            +
             | 
| 317 | 
            +
                    Raises
         | 
| 318 | 
            +
                    ------
         | 
| 319 | 
            +
                    OrionisContainerException
         | 
| 320 | 
            +
                        If the service is not found in the container.
         | 
| 321 | 
            +
                    """
         | 
| 322 | 
            +
                    key = self._aliases.get(abstract, abstract)
         | 
| 308 323 |  | 
| 309 | 
            -
             | 
| 310 | 
            -
             | 
| 324 | 
            +
                    if key in self._instances:
         | 
| 325 | 
            +
                        return self._instances[key]['instance']
         | 
| 311 326 |  | 
| 312 | 
            -
                     | 
| 313 | 
            -
                         | 
| 327 | 
            +
                    if key in self._singletons:
         | 
| 328 | 
            +
                        self._instances[key] = {'instance': self._resolve(self._singletons[key]['callback'])}
         | 
| 329 | 
            +
                        return self._instances[key]['instance']
         | 
| 314 330 |  | 
| 315 | 
            -
                     | 
| 316 | 
            -
                         | 
| 317 | 
            -
             | 
| 318 | 
            -
             | 
| 319 | 
            -
                        raise OrionisContainerException(f"Cannot register a service with a name equal to a primitive type: '{abstract}'.")
         | 
| 331 | 
            +
                    if key in self._scoped_services:
         | 
| 332 | 
            +
                        if key not in self._scoped_instances:
         | 
| 333 | 
            +
                            self._scoped_instances[key] = self._resolve(self._scoped_services[key]['callback'])
         | 
| 334 | 
            +
                        return self._scoped_instances[key]
         | 
| 320 335 |  | 
| 321 | 
            -
             | 
| 322 | 
            -
             | 
| 336 | 
            +
                    if key in self._transients:
         | 
| 337 | 
            +
                        return self._resolve(self._transients[key]['callback'])
         | 
| 323 338 |  | 
| 324 | 
            -
                     | 
| 339 | 
            +
                    if key in self._bindings:
         | 
| 340 | 
            +
                        return self._resolve(self._bindings[key]['callback'])
         | 
| 325 341 |  | 
| 326 | 
            -
                     | 
| 327 | 
            -
                        concrete (Callable[..., Any]): Concrete implementation of the service.
         | 
| 342 | 
            +
                    raise OrionisContainerException(f"Service '{abstract}' is not registered in the container.")
         | 
| 328 343 |  | 
| 329 | 
            -
             | 
| 330 | 
            -
                        Any: The resolved service instance.
         | 
| 331 | 
            -
             | 
| 332 | 
            -
                    Raises:
         | 
| 333 | 
            -
                        ValueError: If there is a constructor parameter whose type cannot be resolved.
         | 
| 344 | 
            +
                def _resolve(self, concrete: Callable[..., Any]) -> Any:
         | 
| 334 345 | 
             
                    """
         | 
| 335 | 
            -
                     | 
| 336 | 
            -
                        constructor = inspect.signature(concrete.__init__)
         | 
| 337 | 
            -
                        parameters = constructor.parameters
         | 
| 338 | 
            -
             | 
| 339 | 
            -
                        # If the class has no parameters in its constructor, instantiate it directly
         | 
| 340 | 
            -
                        if len(parameters) == 0 or (len(parameters) == 1 and "self" in parameters):
         | 
| 341 | 
            -
                            return concrete()
         | 
| 346 | 
            +
                    Resolve and instantiate a given service class or function.
         | 
| 342 347 |  | 
| 343 | 
            -
             | 
| 344 | 
            -
             | 
| 345 | 
            -
             | 
| 346 | 
            -
             | 
| 347 | 
            -
                                continue
         | 
| 348 | 
            +
                    This method analyzes the constructor of the given class (or callable),
         | 
| 349 | 
            +
                    retrieves its dependencies, and resolves them recursively, while respecting
         | 
| 350 | 
            +
                    the service lifecycle.
         | 
| 351 | 
            +
                    """
         | 
| 348 352 |  | 
| 353 | 
            +
                    # Step 1: Retrieve the constructor signature of the class or callable.
         | 
| 354 | 
            +
                    try:
         | 
| 355 | 
            +
                        signature = inspect.signature(concrete)
         | 
| 356 | 
            +
                    except ValueError as e:
         | 
| 357 | 
            +
                        raise OrionisContainerException(f"Unable to inspect signature of {concrete}: {str(e)}")
         | 
| 358 | 
            +
             | 
| 359 | 
            +
                    # Step 2: Prepare a dictionary for resolved dependencies and a queue for unresolved ones.
         | 
| 360 | 
            +
                    resolved_dependencies: Dict[str, Any] = {}
         | 
| 361 | 
            +
                    unresolved_dependencies = deque()
         | 
| 362 | 
            +
             | 
| 363 | 
            +
                    # Step 3: Iterate through the parameters of the constructor.
         | 
| 364 | 
            +
                    for param_name, param in signature.parameters.items():
         | 
| 365 | 
            +
                        if param_name == 'self':
         | 
| 366 | 
            +
                            # Skip 'self' in methods
         | 
| 367 | 
            +
                            continue
         | 
| 368 | 
            +
             | 
| 369 | 
            +
                        # If parameter has no annotation and no default value, it's unresolved
         | 
| 370 | 
            +
                        if param.annotation is param.empty and param.default is param.empty:
         | 
| 371 | 
            +
                            unresolved_dependencies.append(param_name)
         | 
| 372 | 
            +
                            continue
         | 
| 373 | 
            +
             | 
| 374 | 
            +
                        # Resolve dependencies based on annotations (excluding primitive types)
         | 
| 375 | 
            +
                        if param.annotation is not param.empty:
         | 
| 349 376 | 
             
                            param_type = param.annotation
         | 
| 350 | 
            -
             | 
| 351 | 
            -
                             | 
| 352 | 
            -
             | 
| 353 | 
            -
                                if  | 
| 354 | 
            -
                                     | 
| 355 | 
            -
                                    dependencies[name] = param.default
         | 
| 356 | 
            -
                                    continue
         | 
| 377 | 
            +
                            # Check if it's a registered service, if so, resolve it through the container
         | 
| 378 | 
            +
                            if isinstance(param_type, type) and not isinstance(param_type, (int, str, bool, float)) and not issubclass(param_type, (int, str, bool, float)):
         | 
| 379 | 
            +
                                # Check if the service is registered in the container
         | 
| 380 | 
            +
                                if self.has(param_type):
         | 
| 381 | 
            +
                                    resolved_dependencies[param_name] = self.make(f"{param_type.__module__}.{param_type.__name__}")
         | 
| 357 382 | 
             
                                else:
         | 
| 358 | 
            -
                                     | 
| 359 | 
            -
             | 
| 360 | 
            -
                            # If the parameter type is a primitive (str, int, etc.), pass it as is
         | 
| 361 | 
            -
                            if isinstance(param_type, type):
         | 
| 362 | 
            -
                                if param.default != param.empty:
         | 
| 363 | 
            -
                                    dependencies[name] = param.default if param.default != param.empty else param_type()
         | 
| 364 | 
            -
                                else:
         | 
| 365 | 
            -
                                    dependencies[name] = param_type()  # Provide default value for primitive types if not specified
         | 
| 383 | 
            +
                                    resolved_dependencies[param_name] = self._resolve_dependency(param_type)
         | 
| 366 384 | 
             
                            else:
         | 
| 367 | 
            -
                                 | 
| 385 | 
            +
                                resolved_dependencies[param_name] = param_type  # It's a primitive, use as-is
         | 
| 368 386 |  | 
| 369 | 
            -
             | 
| 370 | 
            -
             | 
| 371 | 
            -
             | 
| 372 | 
            -
                                else:
         | 
| 373 | 
            -
                                    dependencies[name] = self.make(dep_name)
         | 
| 387 | 
            +
                        # Resolve parameters with default values (without annotations)
         | 
| 388 | 
            +
                        elif param.default is not param.empty:
         | 
| 389 | 
            +
                            resolved_dependencies[param_name] = param.default
         | 
| 374 390 |  | 
| 375 | 
            -
             | 
| 391 | 
            +
                    # Step 4: Resolve any remaining unresolved dependencies.
         | 
| 392 | 
            +
                    while unresolved_dependencies:
         | 
| 393 | 
            +
                        dep_name = unresolved_dependencies.popleft()
         | 
| 394 | 
            +
                        if dep_name not in resolved_dependencies:
         | 
| 395 | 
            +
                            resolved_dependencies[dep_name] = self._resolve_dependency(dep_name)
         | 
| 376 396 |  | 
| 377 | 
            -
                     | 
| 397 | 
            +
                    # Step 5: Instantiate the class with resolved dependencies.
         | 
| 398 | 
            +
                    try:
         | 
| 399 | 
            +
                        return concrete(**resolved_dependencies)
         | 
| 400 | 
            +
                    except Exception as e:
         | 
| 401 | 
            +
                        raise OrionisContainerException(f"Failed to instantiate {concrete}: {str(e)}")
         | 
| 378 402 |  | 
| 379 | 
            -
                def  | 
| 380 | 
            -
                    """ | 
| 403 | 
            +
                def _resolve_dependency(self, dep_type: Any) -> Any:
         | 
| 404 | 
            +
                    """
         | 
| 405 | 
            +
                    Resolves a dependency based on the provided type.
         | 
| 381 406 |  | 
| 382 | 
            -
                    This method  | 
| 383 | 
            -
                     | 
| 407 | 
            +
                    This method looks for the type in the container and returns the instance,
         | 
| 408 | 
            +
                    respecting the lifecycle of the service (transient, singleton, etc.).
         | 
| 384 409 | 
             
                    """
         | 
| 385 | 
            -
                     | 
| 410 | 
            +
                    # Check if the dependency exists in the container or create it if necessary
         | 
| 411 | 
            +
                    # If it's a class type
         | 
| 412 | 
            +
                    if isinstance(dep_type, type):
         | 
| 413 | 
            +
                        if self.has(dep_type):
         | 
| 414 | 
            +
                            # Resolves the service through the container
         | 
| 415 | 
            +
                            return self.make(f"{dep_type.__module__}.{dep_type.__name__}")
         | 
| 416 | 
            +
                        else:
         | 
| 417 | 
            +
                            # Instantiate the class if not found in the container
         | 
| 418 | 
            +
                            return self._resolve(dep_type)
         | 
| 419 | 
            +
             | 
| 420 | 
            +
                    raise OrionisContainerException(f"Cannot resolve dependency of type {dep_type}")
         | 
| @@ -34,3 +34,21 @@ class OrionisContainerValueError(ValueError): | |
| 34 34 | 
             
                def __str__(self) -> str:
         | 
| 35 35 | 
             
                    """Retorna una representación en cadena de la excepción."""
         | 
| 36 36 | 
             
                    return f"[OrionisContainerValueError] {self.args[0]}"
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            class OrionisContainerTypeError(TypeError):
         | 
| 39 | 
            +
                """
         | 
| 40 | 
            +
                Custom exception for TypeError related to the Orionis container.
         | 
| 41 | 
            +
                """
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                def __init__(self, message: str) -> None:
         | 
| 44 | 
            +
                    """
         | 
| 45 | 
            +
                    Initializes the exception with an error message.
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                    Args:
         | 
| 48 | 
            +
                        message (str): Descriptive error message.
         | 
| 49 | 
            +
                    """
         | 
| 50 | 
            +
                    super().__init__(message)
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                def __str__(self) -> str:
         | 
| 53 | 
            +
                    """Returns a string representation of the exception."""
         | 
| 54 | 
            +
                    return f"[OrionisContainerTypeError] {self.args[0]}"
         | 
| @@ -14,12 +14,12 @@ class IRegister(ABC): | |
| 14 14 |  | 
| 15 15 | 
             
                Methods
         | 
| 16 16 | 
             
                -------
         | 
| 17 | 
            -
                config(config_class: type) ->  | 
| 17 | 
            +
                config(config_class: type) -> None
         | 
| 18 18 | 
             
                    Registers a configuration class and ensures it meets the necessary criteria.
         | 
| 19 19 | 
             
                """
         | 
| 20 20 |  | 
| 21 21 | 
             
                @abstractmethod
         | 
| 22 | 
            -
                def config(self, config_class: type) ->  | 
| 22 | 
            +
                def config(self, config_class: type) -> None:
         | 
| 23 23 | 
             
                    """
         | 
| 24 24 | 
             
                    Registers a configuration class and ensures it meets the required structure.
         | 
| 25 25 |  | 
| @@ -2,151 +2,221 @@ from abc import ABC, abstractmethod | |
| 2 2 | 
             
            from typing import Any, Callable
         | 
| 3 3 |  | 
| 4 4 | 
             
            class IContainer(ABC):
         | 
| 5 | 
            -
                """Service container and dependency injection."""
         | 
| 6 5 |  | 
| 7 6 | 
             
                @abstractmethod
         | 
| 8 | 
            -
                def  | 
| 9 | 
            -
                    """ | 
| 10 | 
            -
             | 
| 11 | 
            -
                     | 
| 12 | 
            -
             | 
| 13 | 
            -
                        concrete (Callable[..., Any]): Concrete implementation of the service.
         | 
| 7 | 
            +
                def _newRequest(self) -> None:
         | 
| 8 | 
            +
                    """
         | 
| 9 | 
            +
                    Reset scoped instances at the beginning of a new request.
         | 
| 10 | 
            +
                    """
         | 
| 11 | 
            +
                    pass
         | 
| 14 12 |  | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 13 | 
            +
                @abstractmethod
         | 
| 14 | 
            +
                def _ensureNotMain(self, concrete: Callable[..., Any]) -> str:
         | 
| 15 | 
            +
                    """
         | 
| 16 | 
            +
                    Ensure that a class is not defined in the main script.
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    Parameters
         | 
| 19 | 
            +
                    ----------
         | 
| 20 | 
            +
                    concrete : Callable[..., Any]
         | 
| 21 | 
            +
                        The class or function to check.
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    Returns
         | 
| 24 | 
            +
                    -------
         | 
| 25 | 
            +
                    str
         | 
| 26 | 
            +
                        The fully qualified name of the class.
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    Raises
         | 
| 29 | 
            +
                    ------
         | 
| 30 | 
            +
                    OrionisContainerValueError
         | 
| 31 | 
            +
                        If the class is defined in the main module.
         | 
| 18 32 | 
             
                    """
         | 
| 19 33 | 
             
                    pass
         | 
| 20 34 |  | 
| 21 35 | 
             
                @abstractmethod
         | 
| 22 | 
            -
                def  | 
| 23 | 
            -
                    """ | 
| 36 | 
            +
                def _ensureUniqueService(self, obj: Any) -> None:
         | 
| 37 | 
            +
                    """
         | 
| 38 | 
            +
                    Ensure that a service is not already registered.
         | 
| 24 39 |  | 
| 25 | 
            -
                     | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 40 | 
            +
                    Parameters
         | 
| 41 | 
            +
                    ----------
         | 
| 42 | 
            +
                    obj : Any
         | 
| 43 | 
            +
                        The service to check.
         | 
| 28 44 |  | 
| 29 | 
            -
                    Raises | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 45 | 
            +
                    Raises
         | 
| 46 | 
            +
                    ------
         | 
| 47 | 
            +
                    OrionisContainerValueError
         | 
| 48 | 
            +
                        If the service is already registered.
         | 
| 32 49 | 
             
                    """
         | 
| 33 50 | 
             
                    pass
         | 
| 34 51 |  | 
| 35 52 | 
             
                @abstractmethod
         | 
| 36 | 
            -
                def  | 
| 37 | 
            -
                    """ | 
| 53 | 
            +
                def _ensureIsCallable(self, concrete: Callable[..., Any]) -> None:
         | 
| 54 | 
            +
                    """
         | 
| 55 | 
            +
                    Ensure that the given implementation is callable or instantiable.
         | 
| 38 56 |  | 
| 39 | 
            -
                     | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 57 | 
            +
                    Parameters
         | 
| 58 | 
            +
                    ----------
         | 
| 59 | 
            +
                    concrete : Callable[..., Any]
         | 
| 60 | 
            +
                        The implementation to check.
         | 
| 42 61 |  | 
| 43 | 
            -
                    Raises | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 62 | 
            +
                    Raises
         | 
| 63 | 
            +
                    ------
         | 
| 64 | 
            +
                    OrionisContainerTypeError
         | 
| 65 | 
            +
                        If the implementation is not callable.
         | 
| 46 66 | 
             
                    """
         | 
| 47 67 | 
             
                    pass
         | 
| 48 68 |  | 
| 49 69 | 
             
                @abstractmethod
         | 
| 50 | 
            -
                def  | 
| 51 | 
            -
                    """ | 
| 70 | 
            +
                def _ensureIsInstance(self, instance: Any) -> None:
         | 
| 71 | 
            +
                    """
         | 
| 72 | 
            +
                    Ensure that the given instance is a valid object.
         | 
| 52 73 |  | 
| 53 | 
            -
                     | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 74 | 
            +
                    Parameters
         | 
| 75 | 
            +
                    ----------
         | 
| 76 | 
            +
                    instance : Any
         | 
| 77 | 
            +
                        The instance to check.
         | 
| 56 78 |  | 
| 57 | 
            -
                    Raises | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 79 | 
            +
                    Raises
         | 
| 80 | 
            +
                    ------
         | 
| 81 | 
            +
                    OrionisContainerValueError
         | 
| 82 | 
            +
                        If the instance is not a valid object.
         | 
| 60 83 | 
             
                    """
         | 
| 61 84 | 
             
                    pass
         | 
| 62 85 |  | 
| 63 86 | 
             
                @abstractmethod
         | 
| 64 | 
            -
                def  | 
| 65 | 
            -
                    """ | 
| 66 | 
            -
             | 
| 87 | 
            +
                def bind(self, concrete: Callable[..., Any]) -> str:
         | 
| 88 | 
            +
                    """
         | 
| 89 | 
            +
                    Bind a callable to the container.
         | 
| 90 | 
            +
                    This method ensures that the provided callable is not the main function,
         | 
| 91 | 
            +
                    is unique within the container, and is indeed callable. It then creates
         | 
| 92 | 
            +
                    a unique key for the callable based on its module and name, and stores
         | 
| 93 | 
            +
                    the callable in the container's bindings.
         | 
| 67 94 | 
             
                    Args:
         | 
| 68 | 
            -
                         | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
                    Raises:
         | 
| 72 | 
            -
                        OrionisContainerException: If the instance is already registered.
         | 
| 73 | 
            -
                        ValueError: If the provided instance is of an unexpected or invalid type.
         | 
| 95 | 
            +
                        concrete (Callable[..., Any]): The callable to be bound to the container.
         | 
| 96 | 
            +
                    Returns:
         | 
| 97 | 
            +
                        str: The unique key generated for the callable.
         | 
| 74 98 | 
             
                    """
         | 
| 75 99 | 
             
                    pass
         | 
| 76 100 |  | 
| 77 101 | 
             
                @abstractmethod
         | 
| 78 | 
            -
                def  | 
| 79 | 
            -
                    """ | 
| 80 | 
            -
             | 
| 102 | 
            +
                def transient(self, concrete: Callable[..., Any]) -> str:
         | 
| 103 | 
            +
                    """
         | 
| 104 | 
            +
                    Registers a transient service in the container.
         | 
| 105 | 
            +
                    A transient service is created each time it is requested.
         | 
| 81 106 | 
             
                    Args:
         | 
| 82 | 
            -
                         | 
| 83 | 
            -
             | 
| 107 | 
            +
                        concrete (Callable[..., Any]): The callable that defines the service.
         | 
| 84 108 | 
             
                    Returns:
         | 
| 85 | 
            -
                         | 
| 86 | 
            -
             | 
| 87 | 
            -
                    Raises:
         | 
| 88 | 
            -
                        ValueError: If the service name (abstract) is not a valid string.
         | 
| 109 | 
            +
                        str: The unique key generated for the callable.
         | 
| 89 110 | 
             
                    """
         | 
| 90 111 | 
             
                    pass
         | 
| 91 112 |  | 
| 92 113 | 
             
                @abstractmethod
         | 
| 93 | 
            -
                def  | 
| 94 | 
            -
                    """ | 
| 95 | 
            -
             | 
| 114 | 
            +
                def singleton(self, concrete: Callable[..., Any]) -> str:
         | 
| 115 | 
            +
                    """
         | 
| 116 | 
            +
                    Registers a callable as a singleton in the container.
         | 
| 117 | 
            +
                    This method ensures that the provided callable is not the main module,
         | 
| 118 | 
            +
                    is unique within the container, and is indeed callable. It then registers
         | 
| 119 | 
            +
                    the callable as a singleton, storing it in the container's singleton registry.
         | 
| 96 120 | 
             
                    Args:
         | 
| 97 | 
            -
                         | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
                    Raises:
         | 
| 101 | 
            -
                        OrionisContainerException: If the original service is not registered.
         | 
| 102 | 
            -
                        ValueError: If the alias is not a valid string or is already in use.
         | 
| 121 | 
            +
                        concrete (Callable[..., Any]): The callable to be registered as a singleton.
         | 
| 122 | 
            +
                    Returns:
         | 
| 123 | 
            +
                        str: The key under which the singleton is registered in the container.
         | 
| 103 124 | 
             
                    """
         | 
| 104 125 | 
             
                    pass
         | 
| 105 126 |  | 
| 106 127 | 
             
                @abstractmethod
         | 
| 107 | 
            -
                def  | 
| 108 | 
            -
                    """ | 
| 109 | 
            -
             | 
| 110 | 
            -
                    This method  | 
| 111 | 
            -
                     | 
| 112 | 
            -
                     | 
| 113 | 
            -
                    3. **Scoped**: Returns a shared instance within the same request.
         | 
| 114 | 
            -
                    4. **Transients**: Creates a new instance each time.
         | 
| 115 | 
            -
                    5. **Aliases**: Resolves an alias to the original service.
         | 
| 116 | 
            -
             | 
| 128 | 
            +
                def scoped(self, concrete: Callable[..., Any]) -> str:
         | 
| 129 | 
            +
                    """
         | 
| 130 | 
            +
                    Registers a callable as a scoped service.
         | 
| 131 | 
            +
                    This method ensures that the provided callable is not the main service,
         | 
| 132 | 
            +
                    is unique, and is indeed callable. It then registers the callable in the
         | 
| 133 | 
            +
                    scoped services dictionary with relevant metadata.
         | 
| 117 134 | 
             
                    Args:
         | 
| 118 | 
            -
                         | 
| 135 | 
            +
                        concrete (Callable[..., Any]): The callable to be registered as a scoped service.
         | 
| 136 | 
            +
                    Returns:
         | 
| 137 | 
            +
                        str: The key under which the callable is registered in the scoped services dictionary.
         | 
| 138 | 
            +
                    """
         | 
| 139 | 
            +
                    pass
         | 
| 119 140 |  | 
| 141 | 
            +
                @abstractmethod
         | 
| 142 | 
            +
                def instance(self, instance: Any) -> str:
         | 
| 143 | 
            +
                    """
         | 
| 144 | 
            +
                    Registers an instance as a singleton in the container.
         | 
| 145 | 
            +
                    Args:
         | 
| 146 | 
            +
                        instance (Any): The instance to be registered as a singleton.
         | 
| 120 147 | 
             
                    Returns:
         | 
| 121 | 
            -
                         | 
| 148 | 
            +
                        str: The key under which the instance is registered in the container.
         | 
| 149 | 
            +
                    """
         | 
| 150 | 
            +
                    pass
         | 
| 122 151 |  | 
| 152 | 
            +
                @abstractmethod
         | 
| 153 | 
            +
                def alias(self, alias: str, concrete: Any) -> None:
         | 
| 154 | 
            +
                    """
         | 
| 155 | 
            +
                    Creates an alias for a registered service.
         | 
| 156 | 
            +
                    Args:
         | 
| 157 | 
            +
                        alias (str): The alias name to be used for the service.
         | 
| 158 | 
            +
                        concrete (Any): The actual service instance or callable to be aliased.
         | 
| 123 159 | 
             
                    Raises:
         | 
| 124 | 
            -
                        OrionisContainerException: If the  | 
| 160 | 
            +
                        OrionisContainerException: If the concrete instance is not a valid object or if the alias is a primitive type.
         | 
| 125 161 | 
             
                    """
         | 
| 126 162 | 
             
                    pass
         | 
| 127 163 |  | 
| 128 164 | 
             
                @abstractmethod
         | 
| 129 | 
            -
                def  | 
| 130 | 
            -
                    """ | 
| 165 | 
            +
                def has(self, obj: Any) -> bool:
         | 
| 166 | 
            +
                    """
         | 
| 167 | 
            +
                    Checks if a service is registered in the container.
         | 
| 131 168 |  | 
| 132 | 
            -
                     | 
| 133 | 
            -
             | 
| 134 | 
            -
             | 
| 135 | 
            -
                         | 
| 169 | 
            +
                    Parameters
         | 
| 170 | 
            +
                    ----------
         | 
| 171 | 
            +
                    obj : Any
         | 
| 172 | 
            +
                        The service class, instance, or alias to check.
         | 
| 136 173 |  | 
| 137 | 
            -
                    Returns | 
| 138 | 
            -
             | 
| 174 | 
            +
                    Returns
         | 
| 175 | 
            +
                    -------
         | 
| 176 | 
            +
                    bool
         | 
| 177 | 
            +
                        True if the service is registered, False otherwise.
         | 
| 178 | 
            +
                    """
         | 
| 179 | 
            +
                    pass
         | 
| 139 180 |  | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 181 | 
            +
                @abstractmethod
         | 
| 182 | 
            +
                def make(self, abstract: Any) -> Any:
         | 
| 183 | 
            +
                    """
         | 
| 184 | 
            +
                    Create and return an instance of a registered service.
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                    Parameters
         | 
| 187 | 
            +
                    ----------
         | 
| 188 | 
            +
                    abstract : Any
         | 
| 189 | 
            +
                        The service class or alias to instantiate.
         | 
| 190 | 
            +
             | 
| 191 | 
            +
                    Returns
         | 
| 192 | 
            +
                    -------
         | 
| 193 | 
            +
                    Any
         | 
| 194 | 
            +
                        An instance of the requested service.
         | 
| 195 | 
            +
             | 
| 196 | 
            +
                    Raises
         | 
| 197 | 
            +
                    ------
         | 
| 198 | 
            +
                    OrionisContainerException
         | 
| 199 | 
            +
                        If the service is not found in the container.
         | 
| 142 200 | 
             
                    """
         | 
| 143 201 | 
             
                    pass
         | 
| 144 202 |  | 
| 145 203 | 
             
                @abstractmethod
         | 
| 146 | 
            -
                def  | 
| 147 | 
            -
                    """ | 
| 204 | 
            +
                def _resolve(self, concrete: Callable[..., Any]) -> Any:
         | 
| 205 | 
            +
                    """
         | 
| 206 | 
            +
                    Resolve and instantiate a given service class or function.
         | 
| 207 | 
            +
             | 
| 208 | 
            +
                    This method analyzes the constructor of the given class (or callable),
         | 
| 209 | 
            +
                    retrieves its dependencies, and resolves them recursively, while respecting
         | 
| 210 | 
            +
                    the service lifecycle.
         | 
| 211 | 
            +
                    """
         | 
| 212 | 
            +
                    pass
         | 
| 213 | 
            +
             | 
| 214 | 
            +
                @abstractmethod
         | 
| 215 | 
            +
                def _resolve_dependency(self, dep_type: Any) -> Any:
         | 
| 216 | 
            +
                    """
         | 
| 217 | 
            +
                    Resolves a dependency based on the provided type.
         | 
| 148 218 |  | 
| 149 | 
            -
                    This method  | 
| 150 | 
            -
                     | 
| 219 | 
            +
                    This method looks for the type in the container and returns the instance,
         | 
| 220 | 
            +
                    respecting the lifecycle of the service (transient, singleton, etc.).
         | 
| 151 221 | 
             
                    """
         | 
| 152 222 | 
             
                    pass
         | 
| @@ -1,13 +1,13 @@ | |
| 1 1 | 
             
            orionis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 2 2 | 
             
            orionis/cli_manager.py,sha256=9wNVJxB0HyqUbNesUvkwlsqTyUbZwK6R46iVLE5WVBQ,1715
         | 
| 3 | 
            -
            orionis/framework.py,sha256= | 
| 3 | 
            +
            orionis/framework.py,sha256=erUuf0Lfq0_tWOuxBX6r_arQFnqBRgk7te6RPxymQRI,1386
         | 
| 4 4 | 
             
            orionis/luminate/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 5 5 | 
             
            orionis/luminate/app.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 6 6 | 
             
            orionis/luminate/bootstrap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 7 7 | 
             
            orionis/luminate/bootstrap/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 8 8 | 
             
            orionis/luminate/bootstrap/config/bootstrapper.py,sha256=R1ixec362o-Td-kNSvi-0ylVqspFWJq6L6IHYzWHPmg,4227
         | 
| 9 9 | 
             
            orionis/luminate/bootstrap/config/parser.py,sha256=Ay8dh3aax9xhVgeLSHT71ubtZJiKAJAP85dLFF7djyA,1950
         | 
| 10 | 
            -
            orionis/luminate/bootstrap/config/register.py,sha256= | 
| 10 | 
            +
            orionis/luminate/bootstrap/config/register.py,sha256=uX0XGEWdo3iJou5B96vxvhZEjliTGC1HBaT8w9enMmk,2760
         | 
| 11 11 | 
             
            orionis/luminate/cache/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 12 12 | 
             
            orionis/luminate/cache/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 13 13 | 
             
            orionis/luminate/cache/app/config.py,sha256=tSHZ7sL_nYSz0aQOo_WkhYYchV1Q9ZdHOWUeHx7uwxE,2242
         | 
| @@ -53,13 +53,13 @@ orionis/luminate/console/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRk | |
| 53 53 | 
             
            orionis/luminate/console/scripts/management.py,sha256=KT6Bg8kyuUw63SNAtZo6tLH6syOEkxM9J70tCpKgrUw,2860
         | 
| 54 54 | 
             
            orionis/luminate/console/tasks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 55 55 | 
             
            orionis/luminate/console/tasks/scheduler.py,sha256=h3fRVTx6TuZVcY7zZ6oOzGDnlDAWaRwkj92pFTGUm6E,22686
         | 
| 56 | 
            -
            orionis/luminate/container/container.py,sha256= | 
| 57 | 
            -
            orionis/luminate/container/exception.py,sha256= | 
| 56 | 
            +
            orionis/luminate/container/container.py,sha256=O4AKaRQK2XfN0es70lIxUGkP0mxxemSsHOOuvtJVcUU,16212
         | 
| 57 | 
            +
            orionis/luminate/container/exception.py,sha256=ap1SqYEjQEEHXJJTNmL7V1jrmRjgT5_7geZ95MYkhMA,1691
         | 
| 58 58 | 
             
            orionis/luminate/container/types.py,sha256=PbPNOJ8e4SGzCmu-zOmCQmDzt1b9I73v3fw_xzLq9RU,932
         | 
| 59 59 | 
             
            orionis/luminate/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 60 60 | 
             
            orionis/luminate/contracts/bootstrap/config/bootstrapper_interface.py,sha256=De6nKQcZpN1dWsubXWUO229ZH4IbCoUaGtP5HOUw2Ps,2251
         | 
| 61 61 | 
             
            orionis/luminate/contracts/bootstrap/config/parser_interface.py,sha256=7DLnp7yB7edayVkSm-piTi8JSf0QKaYYI82qDZudgM0,1641
         | 
| 62 | 
            -
            orionis/luminate/contracts/bootstrap/config/register_interface.py,sha256= | 
| 62 | 
            +
            orionis/luminate/contracts/bootstrap/config/register_interface.py,sha256=7kMW04ptvQ51PnprtCIR-iLHljVSGiH58GN493igeuw,1506
         | 
| 63 63 | 
             
            orionis/luminate/contracts/cache/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 64 64 | 
             
            orionis/luminate/contracts/cache/cache_commands_interface.py,sha256=NhJAh2OZHXKMwbJ8nOU4IFJRZpuJNmfN9rtnpbCnuOo,1936
         | 
| 65 65 | 
             
            orionis/luminate/contracts/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| @@ -80,7 +80,7 @@ orionis/luminate/contracts/console/register_interface.py,sha256=rhHI_as_3yNWtdgQ | |
| 80 80 | 
             
            orionis/luminate/contracts/console/runner_interface.py,sha256=vWLtMhl0m1T6rfCUHZbxGQJl9ZWTXlp3HjcTfCAztGk,1644
         | 
| 81 81 | 
             
            orionis/luminate/contracts/console/schedule_interface.py,sha256=_dsR0gCvJ7_67lwPUAzBwQFHNvWM6jVjcg1EdPqDIIo,10117
         | 
| 82 82 | 
             
            orionis/luminate/contracts/console/task_manager_interface.py,sha256=sOmeifoncpWCG2WYh4q3QZ7M7w7P9Onb3Jxw9X2lpXE,1197
         | 
| 83 | 
            -
            orionis/luminate/contracts/container/container_interface.py,sha256= | 
| 83 | 
            +
            orionis/luminate/contracts/container/container_interface.py,sha256=c_QRQHXGIujiDnYXyt--3J2LKXngVtoB3O-qchPmFDQ,6899
         | 
| 84 84 | 
             
            orionis/luminate/contracts/container/types_interface.py,sha256=GCH7x3PjpXKPET3l84GcXbcM8cpne8AGrmTw-uFaT24,526
         | 
| 85 85 | 
             
            orionis/luminate/contracts/facades/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 86 86 | 
             
            orionis/luminate/contracts/facades/env_interface.py,sha256=aN9dZdsuCpy3meZqMxyxLCYlKEIF7XkRNXmP7aS7eCw,1664
         | 
| @@ -140,9 +140,9 @@ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 | |
| 140 140 | 
             
            tests/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
         | 
| 141 141 | 
             
            tests/tools/class_example.py,sha256=dIPD997Y15n6WmKhWoOFSwEldRm9MdOHTZZ49eF1p3c,1056
         | 
| 142 142 | 
             
            tests/tools/test_reflection.py,sha256=dNN5p_xAosyEf0ddAElmmmTfhcTtBd4zBNl7qzgnsc0,5242
         | 
| 143 | 
            -
            orionis-0. | 
| 144 | 
            -
            orionis-0. | 
| 145 | 
            -
            orionis-0. | 
| 146 | 
            -
            orionis-0. | 
| 147 | 
            -
            orionis-0. | 
| 148 | 
            -
            orionis-0. | 
| 143 | 
            +
            orionis-0.23.0.dist-info/LICENCE,sha256=-_4cF2EBKuYVS_SQpy1uapq0oJPUU1vl_RUWSy2jJTo,1111
         | 
| 144 | 
            +
            orionis-0.23.0.dist-info/METADATA,sha256=IBV6Pic2odjpNmHFEEZUIDIGrkjVPg48VsrQApR669c,2978
         | 
| 145 | 
            +
            orionis-0.23.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
         | 
| 146 | 
            +
            orionis-0.23.0.dist-info/entry_points.txt,sha256=eef1_CVewfokKjrGBynXa06KabSJYo7LlDKKIKvs1cM,53
         | 
| 147 | 
            +
            orionis-0.23.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
         | 
| 148 | 
            +
            orionis-0.23.0.dist-info/RECORD,,
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         |