orionis 0.652.0__py3-none-any.whl → 0.654.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.
@@ -88,37 +88,38 @@ class Container(IContainer):
88
88
 
89
89
  def __init__(self) -> None:
90
90
  """
91
- Initializes a new instance of the container.
91
+ Initializes the internal state of the container instance.
92
92
 
93
- This constructor sets up the internal dictionaries for bindings and aliases,
94
- ensuring that these are only initialized once per instance. The initialization
95
- is guarded by checking if the instance already has the required attributes.
93
+ This constructor sets up the internal dictionaries for service bindings, aliases,
94
+ singleton cache, and resolution cache. Initialization is performed only once per
95
+ instance, even if `__init__` is called multiple times due to inheritance or other
96
+ instantiation patterns. The container also registers itself under the `IContainer`
97
+ interface for dependency injection.
96
98
 
97
99
  Notes
98
100
  -----
99
- - The `__bindings` dictionary is used to store service bindings.
100
- - The `__aliases` dictionary is used to store service aliases.
101
- - Initialization occurs only once per instance, regardless of how many times __init__ is called.
102
- - The container registers itself under the IContainer interface to allow for dependency injection.
101
+ - The `__bindings` dictionary stores service bindings by abstract type.
102
+ - The `__aliases` dictionary maps aliases to their corresponding bindings.
103
+ - The `__singleton_cache` dictionary caches singleton instances.
104
+ - The `__resolution_cache` dictionary tracks types being resolved to prevent circular dependencies.
105
+ - Initialization is guarded to ensure it only occurs once per instance.
106
+
107
+ Returns
108
+ -------
109
+ None
110
+ This method does not return any value.
103
111
  """
104
112
 
105
- # Check if the instance has already been initialized
113
+ # Only initialize if this instance hasn't been initialized before
106
114
  if not hasattr(self, '_Container__initialized'):
107
115
 
108
- # Current Project Namespaces
109
- # Get current project namespace from the working directory
110
- current_project_namespace = Path().cwd().name
116
+ # Set up the container's internal dictionaries for service management
117
+ self.__bindings = {} # Stores service bindings by abstract type
118
+ self.__aliases = {} # Maps aliases to bindings
119
+ self.__resolution_cache = {} # Tracks types currently being resolved
120
+ self.__singleton_cache = {} # Caches singleton instances
111
121
 
112
- # Add the current project namespace to valid namespaces
113
- self.__valid_namespaces = set(('app', 'orionis', 'requests', 'rich', 'apscheduler', 'dotenv', current_project_namespace))
114
-
115
- # Initialize the container's internal state
116
- self.__bindings = {}
117
- self.__aliases = {}
118
- self.__resolution_cache = {}
119
- self.__singleton_cache = {}
120
-
121
- # Mark this instance as initialized
122
+ # Mark this instance as initialized to prevent re-initialization
122
123
  self.__initialized = True
123
124
 
124
125
  def __handleSyncAsyncResult(
@@ -487,6 +488,12 @@ class Container(IContainer):
487
488
  """
488
489
  Registers a service with a transient lifetime.
489
490
 
491
+ This method binds a concrete implementation to an abstract base type or interface
492
+ in the container, ensuring that a new instance of the concrete class is created
493
+ each time the service is requested. It validates the abstract and concrete types,
494
+ enforces decoupling rules if specified, checks that all abstract methods are implemented,
495
+ and manages service aliases.
496
+
490
497
  Parameters
491
498
  ----------
492
499
  abstract : Callable[..., Any]
@@ -497,13 +504,14 @@ class Container(IContainer):
497
504
  An alternative name to register the service under. If not provided, a default alias is generated
498
505
  using the abstract's module and class name.
499
506
  enforce_decoupling : bool, optional
500
- If True, enforces that the concrete class does NOT inherit from the abstract class. If False,
501
- requires that the concrete class is a subclass of the abstract.
507
+ If True, enforces that the concrete class does NOT inherit from the abstract class.
508
+ If False, requires that the concrete class is a subclass of the abstract.
502
509
 
503
510
  Returns
504
511
  -------
505
512
  bool or None
506
- Returns True if the service was registered successfully. Returns None if registration fails.
513
+ Returns True if the service was registered successfully.
514
+ Returns None if registration fails due to an exception.
507
515
 
508
516
  Raises
509
517
  ------
@@ -514,11 +522,12 @@ class Container(IContainer):
514
522
 
515
523
  Notes
516
524
  -----
517
- This method registers the given concrete implementation to the abstract type with a transient lifetime,
518
- meaning a new instance will be created each time the service is requested. The method validates the
519
- abstract and concrete types, checks decoupling rules, ensures all abstract methods are implemented,
520
- and manages service aliases. If a service is already registered under the same abstract or alias,
521
- it is removed before registering the new binding.
525
+ - Registers the given concrete implementation to the abstract type with a transient lifetime,
526
+ meaning a new instance will be created each time the service is requested.
527
+ - Validates the abstract and concrete types, checks decoupling rules, ensures all abstract methods
528
+ are implemented, and manages service aliases.
529
+ - If a service is already registered under the same abstract or alias, it is removed before registering
530
+ the new binding.
522
531
  """
523
532
 
524
533
  try:
@@ -529,11 +538,10 @@ class Container(IContainer):
529
538
  # Ensure that concrete is a concrete class
530
539
  ReflectionConcrete.ensureIsConcreteClass(concrete)
531
540
 
532
- # Ensure that concrete is NOT a subclass of abstract if decoupling is enforced,
533
- # otherwise ensure it is a subclass
541
+ # Enforce decoupling or subclass relationship as specified
534
542
  self.__decouplingCheck(abstract, concrete, enforce_decoupling)
535
543
 
536
- # Ensure that all abstract methods are implemented by the concrete class
544
+ # Ensure all abstract methods are implemented by the concrete class
537
545
  self.__implementsAbstractMethods(
538
546
  abstract=abstract,
539
547
  concrete=concrete
@@ -581,7 +589,8 @@ class Container(IContainer):
581
589
  This method validates the abstract type, the instance, and the alias (if provided).
582
590
  It ensures that the instance is a valid implementation of the abstract class or interface,
583
591
  optionally enforces decoupling, and registers the instance in the container under both
584
- the abstract type and the alias.
592
+ the abstract type and the alias. The registered instance will be shared across all resolutions
593
+ of the abstract type or alias.
585
594
 
586
595
  Parameters
587
596
  ----------
@@ -614,7 +623,7 @@ class Container(IContainer):
614
623
  -----
615
624
  - The instance is registered with singleton lifetime, meaning it will be shared
616
625
  across all resolutions of the abstract type or alias.
617
- - The method ensures that all abstract methods are implemented by the instance.
626
+ - All abstract methods must be implemented by the instance.
618
627
  - If a service is already registered under the same abstract or alias, it is removed
619
628
  before registering the new instance.
620
629
  """
@@ -639,7 +648,7 @@ class Container(IContainer):
639
648
  # Validate and generate the alias key (either provided or default)
640
649
  alias = self.__makeAliasKey(abstract, alias)
641
650
 
642
- # If the service is already registered, remove the existing binding
651
+ # Remove any existing binding for this abstract or alias
643
652
  self.drop(abstract, alias)
644
653
 
645
654
  # Register the instance with singleton lifetime
@@ -664,14 +673,6 @@ class Container(IContainer):
664
673
  f"Unexpected error registering instance: {e}"
665
674
  ) from e
666
675
 
667
-
668
-
669
-
670
-
671
-
672
-
673
-
674
-
675
676
  def singleton(
676
677
  self,
677
678
  abstract: Callable[..., Any],
@@ -683,76 +684,91 @@ class Container(IContainer):
683
684
  """
684
685
  Registers a service with a singleton lifetime.
685
686
 
687
+ This method binds a concrete implementation to an abstract base type or interface
688
+ in the container, ensuring that only one instance of the concrete class is created
689
+ and shared throughout the application's lifetime. It validates the abstract and
690
+ concrete types, enforces decoupling rules if specified, checks that all abstract
691
+ methods are implemented, and manages service aliases.
692
+
686
693
  Parameters
687
694
  ----------
688
695
  abstract : Callable[..., Any]
689
- The abstract base type or interface to be bound.
696
+ The abstract base type or interface to be bound. Must be an abstract class or interface.
690
697
  concrete : Callable[..., Any]
691
- The concrete implementation to associate with the abstract type.
698
+ The concrete implementation to associate with the abstract type. Must be a concrete class.
692
699
  alias : str, optional
693
- An alternative name to register the service under. If not provided, the abstract's class name is used.
700
+ An alternative name to register the service under. If not provided, a default alias is generated
701
+ using the abstract's module and class name.
702
+ enforce_decoupling : bool, optional
703
+ If True, enforces that the concrete class does NOT inherit from the abstract class.
704
+ If False, requires that the concrete class is a subclass of the abstract.
694
705
 
695
706
  Returns
696
707
  -------
697
- bool
698
- True if the service was registered successfully.
708
+ bool or None
709
+ Returns True if the service was registered successfully.
710
+ Returns None if registration fails due to an exception.
699
711
 
700
712
  Raises
701
713
  ------
702
714
  OrionisContainerTypeError
703
- If the abstract or concrete class checks fail.
715
+ If the abstract or concrete class validation fails.
704
716
  OrionisContainerException
705
- If the concrete class inherits from the abstract class.
717
+ If the decoupling check fails or if an unexpected error occurs during registration.
706
718
 
707
719
  Notes
708
720
  -----
709
- Registers the given concrete implementation to the abstract type with a singleton lifetime,
710
- meaning a single instance will be created and shared. Optionally, an alias can be provided for registration.
721
+ - Registers the given concrete implementation to the abstract type with a singleton lifetime,
722
+ meaning a single instance will be created and shared for all resolutions.
723
+ - If a service is already registered under the same abstract or alias, it is removed before registering the new binding.
724
+ - All abstract methods must be implemented by the concrete class.
725
+ - Aliases are validated and managed for lookup.
711
726
  """
712
727
 
713
- # Ensure that abstract is an abstract class
714
- IsAbstractClass(abstract, Lifetime.SINGLETON)
728
+ try:
715
729
 
716
- # Ensure that concrete is a concrete class
717
- IsConcreteClass(concrete, Lifetime.SINGLETON)
730
+ # Ensure that abstract is an abstract class
731
+ ReflectionAbstract.ensureIsAbstractClass(abstract)
718
732
 
719
- # Ensure that concrete is NOT a subclass of abstract
720
- if enforce_decoupling:
721
- IsNotSubclass(abstract, concrete)
733
+ # Ensure that concrete is a concrete class
734
+ ReflectionConcrete.ensureIsConcreteClass(concrete)
722
735
 
723
- # Validate that concrete is a subclass of abstract
724
- else:
725
- IsSubclass(abstract, concrete)
736
+ # Enforce decoupling or subclass relationship as specified
737
+ self.__decouplingCheck(abstract, concrete, enforce_decoupling)
726
738
 
727
- # Ensure implementation
728
- ImplementsAbstractMethods(
729
- abstract=abstract,
730
- concrete=concrete
731
- )
739
+ # Ensure all abstract methods are implemented by the concrete class
740
+ self.__implementsAbstractMethods(
741
+ abstract=abstract,
742
+ concrete=concrete
743
+ )
732
744
 
733
- # Ensure that the alias is a valid string if provided
734
- if alias:
735
- IsValidAlias(alias)
736
- else:
737
- alias = f"{abstract.__module__}.{abstract.__name__}"
745
+ # Validate and generate the alias key (either provided or default)
746
+ alias = self.__makeAliasKey(abstract, alias)
738
747
 
739
- # If the service is already registered, drop it
740
- self.drop(abstract, alias)
748
+ # If the service is already registered, remove the existing binding
749
+ self.drop(abstract, alias)
741
750
 
742
- # Register the service with singleton lifetime
743
- self.__bindings[abstract] = Binding(
744
- contract = abstract,
745
- concrete = concrete,
746
- lifetime = Lifetime.SINGLETON,
747
- enforce_decoupling = enforce_decoupling,
748
- alias = alias
749
- )
751
+ # Register the service with singleton lifetime
752
+ self.__bindings[abstract] = Binding(
753
+ contract = abstract,
754
+ concrete = concrete,
755
+ lifetime = Lifetime.SINGLETON,
756
+ enforce_decoupling = enforce_decoupling,
757
+ alias = alias
758
+ )
750
759
 
751
- # Register the alias
752
- self.__aliases[alias] = self.__bindings[abstract]
760
+ # Register the alias for lookup
761
+ self.__aliases[alias] = self.__bindings[abstract]
753
762
 
754
- # Return True to indicate successful registration
755
- return True
763
+ # Return True to indicate successful registration
764
+ return True
765
+
766
+ except Exception as e:
767
+
768
+ # Raise a container exception with details if registration fails
769
+ raise OrionisContainerException(
770
+ f"Unexpected error registering {Lifetime.SINGLETON} service: {e}"
771
+ ) from e
756
772
 
757
773
  def scoped(
758
774
  self,
@@ -765,76 +781,101 @@ class Container(IContainer):
765
781
  """
766
782
  Registers a service with a scoped lifetime.
767
783
 
784
+ This method binds a concrete implementation to an abstract base type or interface
785
+ in the container, ensuring that a new instance of the concrete class is created
786
+ for each scope context. It validates the abstract and concrete types, enforces
787
+ decoupling rules if specified, checks that all abstract methods are implemented,
788
+ and manages service aliases.
789
+
768
790
  Parameters
769
791
  ----------
770
792
  abstract : Callable[..., Any]
771
- The abstract base type or interface to be bound.
793
+ The abstract base type or interface to be bound. Must be an abstract class or interface.
772
794
  concrete : Callable[..., Any]
773
- The concrete implementation to associate with the abstract type.
795
+ The concrete implementation to associate with the abstract type. Must be a concrete class.
774
796
  alias : str, optional
775
- An alternative name to register the service under. If not provided, the abstract's class name is used.
797
+ An alternative name to register the service under. If not provided, a default alias is generated
798
+ using the abstract's module and class name.
799
+ enforce_decoupling : bool, optional
800
+ If True, enforces that the concrete class does NOT inherit from the abstract class.
801
+ If False, requires that the concrete class is a subclass of the abstract.
776
802
 
777
803
  Returns
778
804
  -------
779
- bool
780
- True if the service was registered successfully.
805
+ bool or None
806
+ Returns True if the service was registered successfully.
807
+ Returns None if registration fails due to an exception.
781
808
 
782
809
  Raises
783
810
  ------
784
811
  OrionisContainerTypeError
785
- If the abstract or concrete class checks fail.
812
+ If the abstract or concrete class validation fails.
786
813
  OrionisContainerException
787
- If the concrete class inherits from the abstract class.
814
+ If the decoupling check fails or if an unexpected error occurs during registration.
788
815
 
789
816
  Notes
790
817
  -----
791
- Registers the given concrete implementation to the abstract type with a scoped lifetime,
792
- meaning a new instance will be created per scope. Optionally, an alias can be provided for registration.
818
+ - Registers the given concrete implementation to the abstract type with a scoped lifetime,
819
+ meaning a new instance will be created for each scope context.
820
+ - Validates the abstract and concrete types, checks decoupling rules, ensures all abstract methods
821
+ are implemented, and manages service aliases.
822
+ - If a service is already registered under the same abstract or alias, it is removed before registering
823
+ the new binding.
793
824
  """
794
825
 
795
- # Ensure that abstract is an abstract class
796
- IsAbstractClass(abstract, Lifetime.SCOPED)
826
+ try:
827
+
828
+ # Ensure that abstract is an abstract class
829
+ ReflectionAbstract.ensureIsAbstractClass(abstract)
830
+
831
+ # Ensure that concrete is a concrete class
832
+ ReflectionConcrete.ensureIsConcreteClass(concrete)
833
+
834
+ # Enforce decoupling or subclass relationship as specified
835
+ self.__decouplingCheck(abstract, concrete, enforce_decoupling)
836
+
837
+ # Ensure all abstract methods are implemented by the concrete class
838
+ self.__implementsAbstractMethods(
839
+ abstract=abstract,
840
+ concrete=concrete
841
+ )
842
+
843
+ # Validate and generate the alias key (either provided or default)
844
+ alias = self.__makeAliasKey(abstract, alias)
845
+
846
+ # If the service is already registered, remove the existing binding
847
+ self.drop(abstract, alias)
848
+
849
+ # Register the service with scoped lifetime
850
+ self.__bindings[abstract] = Binding(
851
+ contract = abstract,
852
+ concrete = concrete,
853
+ lifetime = Lifetime.SCOPED,
854
+ enforce_decoupling = enforce_decoupling,
855
+ alias = alias
856
+ )
857
+
858
+ # Register the alias for lookup
859
+ self.__aliases[alias] = self.__bindings[abstract]
860
+
861
+ # Return True to indicate successful registration
862
+ return True
863
+
864
+ except Exception as e:
865
+
866
+ # Raise a container exception with details if registration fails
867
+ raise OrionisContainerException(
868
+ f"Unexpected error registering {Lifetime.SCOPED} service: {e}"
869
+ ) from e
797
870
 
798
- # Ensure that concrete is a concrete class
799
- IsConcreteClass(concrete, Lifetime.SCOPED)
800
871
 
801
- # Ensure that concrete is NOT a subclass of abstract
802
- if enforce_decoupling:
803
- IsNotSubclass(abstract, concrete)
804
872
 
805
- # Validate that concrete is a subclass of abstract
806
- else:
807
- IsSubclass(abstract, concrete)
808
873
 
809
- # Ensure implementation
810
- ImplementsAbstractMethods(
811
- abstract=abstract,
812
- concrete=concrete
813
- )
814
874
 
815
- # Ensure that the alias is a valid string if provided
816
- if alias:
817
- IsValidAlias(alias)
818
- else:
819
- alias = f"{abstract.__module__}.{abstract.__name__}"
820
875
 
821
- # If the service is already registered, drop it
822
- self.drop(abstract, alias)
823
876
 
824
- # Register the service with scoped lifetime
825
- self.__bindings[abstract] = Binding(
826
- contract = abstract,
827
- concrete = concrete,
828
- lifetime = Lifetime.SCOPED,
829
- enforce_decoupling = enforce_decoupling,
830
- alias = alias
831
- )
832
877
 
833
- # Register the alias
834
- self.__aliases[alias] = self.__bindings[abstract]
835
878
 
836
- # Return True to indicate successful registration
837
- return True
838
879
 
839
880
  def scopedInstance(
840
881
  self,
@@ -1635,6 +1676,7 @@ class Container(IContainer):
1635
1676
  The singleton instance to store cross-references for.
1636
1677
  """
1637
1678
 
1679
+ # Determine the primary cache key for this binding
1638
1680
  primary_key = self.__getSingletonCacheKey(binding)
1639
1681
 
1640
1682
  # Store cross-reference for contract if it's not the primary key
@@ -1997,6 +2039,7 @@ class Container(IContainer):
1997
2039
  """
1998
2040
 
1999
2041
  try:
2042
+
2000
2043
  # If there are no dependencies, return empty dict
2001
2044
  if not dependencies:
2002
2045
  return {}
@@ -2013,6 +2056,7 @@ class Container(IContainer):
2013
2056
  for param_name, dep in dependencies.resolved.items():
2014
2057
  params[param_name] = self.__resolveSingleDependency(name, param_name, dep)
2015
2058
 
2059
+ # Return the dictionary of resolved parameters
2016
2060
  return params
2017
2061
 
2018
2062
  except Exception as e:
@@ -2146,43 +2190,61 @@ class Container(IContainer):
2146
2190
  **kwargs
2147
2191
  ) -> Any:
2148
2192
  """
2149
- Forces resolution of a type whether it's registered in the container or not.
2193
+ Resolves and instantiates a type or callable regardless of its registration in the container.
2194
+
2195
+ This method attempts to instantiate or invoke the provided type or callable, even if it is not
2196
+ registered in the container. It first tries direct instantiation/invocation if arguments are provided,
2197
+ then attempts auto-resolution for eligible types, and finally falls back to reflection-based instantiation.
2198
+ If the type cannot be resolved by any means, an exception is raised.
2150
2199
 
2151
2200
  Parameters
2152
2201
  ----------
2153
2202
  type_ : Callable[..., Any]
2154
- The type or callable to resolve.
2203
+ The class or callable to resolve and instantiate.
2155
2204
  *args : tuple
2156
- Positional arguments to pass to the constructor/callable.
2205
+ Positional arguments to pass to the constructor or callable.
2157
2206
  **kwargs : dict
2158
- Keyword arguments to pass to the constructor/callable.
2207
+ Keyword arguments to pass to the constructor or callable.
2159
2208
 
2160
2209
  Returns
2161
2210
  -------
2162
2211
  Any
2163
- The resolved instance.
2212
+ The instantiated object or the result of the callable. If the type is a class, a new instance is returned.
2213
+ If the type is a callable, the result of its invocation is returned.
2164
2214
 
2165
2215
  Raises
2166
2216
  ------
2167
2217
  OrionisContainerException
2168
- If the type cannot be resolved.
2218
+ If the type cannot be resolved, is not a concrete class or callable, or if an error occurs during instantiation.
2219
+
2220
+ Notes
2221
+ -----
2222
+ - Direct instantiation/invocation is prioritized when arguments are provided.
2223
+ - Auto-resolution is attempted for types eligible for automatic dependency resolution.
2224
+ - Reflection-based instantiation is used as a fallback for concrete classes or callables.
2225
+ - If none of the resolution strategies succeed, an exception is raised.
2169
2226
  """
2227
+
2170
2228
  try:
2171
- # If args or kwargs are provided, use them directly
2229
+
2230
+ # If explicit arguments are provided, attempt direct instantiation or invocation
2172
2231
  if args or kwargs:
2173
2232
  if isinstance(type_, type):
2233
+ # Instantiate the class directly with provided arguments
2174
2234
  return type_(*args, **kwargs)
2175
2235
  elif callable(type_):
2236
+ # Invoke the callable directly with provided arguments
2176
2237
  return type_(*args, **kwargs)
2177
2238
 
2178
- # Try auto-resolution first for unregistered types
2239
+ # Attempt auto-resolution for eligible types
2179
2240
  if self.__canAutoResolve(type_):
2180
2241
  return self.__autoResolve(type_)
2181
2242
 
2182
- # Use the unified reflection-based instantiation
2243
+ # Use reflection-based instantiation for concrete classes
2183
2244
  if ReflectionConcrete.isConcreteClass(type_):
2184
2245
  return self.__instantiateWithReflection(type_, is_class=True)
2185
2246
 
2247
+ # Use reflection-based invocation for callables that are not classes
2186
2248
  if callable(type_) and not isinstance(type_, type):
2187
2249
  return self.__instantiateWithReflection(type_, is_class=False)
2188
2250
 
@@ -2192,9 +2254,12 @@ class Container(IContainer):
2192
2254
  )
2193
2255
 
2194
2256
  except Exception as e:
2257
+
2258
+ # Re-raise container exceptions directly
2195
2259
  if isinstance(e, OrionisContainerException):
2196
2260
  raise e from None
2197
2261
 
2262
+ # Wrap other exceptions in an OrionisContainerException with context
2198
2263
  raise OrionisContainerException(
2199
2264
  f"Error resolving '{getattr(type_, '__name__', str(type_))}': {str(e)}"
2200
2265
  ) from e
@@ -2259,26 +2324,34 @@ class Container(IContainer):
2259
2324
 
2260
2325
  def __isValidNamespace(self, type_: type) -> bool:
2261
2326
  """
2262
- Checks if a type belongs to a valid namespace for auto-resolution.
2327
+ Determines if a type belongs to a valid namespace for auto-resolution.
2328
+
2329
+ This method checks whether the provided type is defined within one of the namespaces
2330
+ considered valid for automatic dependency resolution by the container. Valid namespaces
2331
+ are typically application-specific modules or packages that are explicitly allowed
2332
+ for auto-resolution. Built-in types and types from external libraries are excluded.
2263
2333
 
2264
2334
  Parameters
2265
2335
  ----------
2266
2336
  type_ : type
2267
- The type to check for valid namespace.
2337
+ The type to check for valid namespace membership.
2268
2338
 
2269
2339
  Returns
2270
2340
  -------
2271
2341
  bool
2272
- True if the type belongs to a valid namespace, False otherwise.
2273
- """
2342
+ True if the type belongs to a valid namespace (i.e., its `__module__` attribute
2343
+ matches one of the namespaces in `self.__valid_namespaces`), otherwise False.
2274
2344
 
2275
- # Verify that the module name starts with any of the valid namespace prefixes
2276
- if hasattr(type_, '__module__'):
2277
- module_name = type_.__module__
2278
- return any(module_name.startswith(namespace) for namespace in self.__valid_namespaces)
2345
+ Notes
2346
+ -----
2347
+ - The method relies on the presence of the `__module__` attribute on the type.
2348
+ - If the type does not have a `__module__` attribute, it cannot be considered valid.
2349
+ - The set of valid namespaces is initialized in the container and may include
2350
+ application modules, framework modules, and the current project namespace.
2351
+ """
2279
2352
 
2280
- # If the type has no module information, it cannot be auto-resolved
2281
- return False
2353
+ # Ensure the type has a __module__ attribute before checking namespace validity
2354
+ return hasattr(type_, '__module__')
2282
2355
 
2283
2356
  def __isInstantiable(self, type_: type) -> bool:
2284
2357
  """
@@ -2330,6 +2403,7 @@ class Container(IContainer):
2330
2403
  return self.__canQuickInstantiate(type_)
2331
2404
 
2332
2405
  except Exception:
2406
+
2333
2407
  # If any check fails with an exception, consider it non-instantiable
2334
2408
  return False
2335
2409
 
@@ -2354,22 +2428,31 @@ class Container(IContainer):
2354
2428
 
2355
2429
  # Check if it inherits from ABC (safely)
2356
2430
  try:
2431
+
2432
+ # Check if it inherits from abc.ABC
2357
2433
  if issubclass(type_, abc.ABC):
2358
2434
  return True
2435
+
2436
+ # type_ is not a class, so it can't be abstract
2359
2437
  except TypeError:
2360
- # type_ is not a class, so it can't be abstract
2361
2438
  pass
2362
2439
 
2363
2440
  # Check if it has abstract methods
2364
2441
  try:
2365
2442
  # Try to get abstract methods using reflection
2366
2443
  for attr_name in dir(type_):
2444
+
2445
+ # Get the attribute
2367
2446
  attr = getattr(type_, attr_name)
2447
+
2448
+ # Check if the attribute is marked as an abstract method
2368
2449
  if hasattr(attr, '__isabstractmethod__') and attr.__isabstractmethod__:
2369
2450
  return True
2451
+
2370
2452
  except Exception:
2371
2453
  pass
2372
2454
 
2455
+ # If none of the checks matched, it's not abstract
2373
2456
  return False
2374
2457
 
2375
2458
  def __isGenericType(self, type_: type) -> bool:
@@ -2403,6 +2486,7 @@ class Container(IContainer):
2403
2486
  if hasattr(typing, 'TypeVar') and isinstance(type_, typing.TypeVar):
2404
2487
  return True
2405
2488
 
2489
+ # If none of the checks matched, it's not a generic type
2406
2490
  return False
2407
2491
 
2408
2492
  def __isProtocolOrTyping(self, type_: type) -> bool:
@@ -2435,9 +2519,12 @@ class Container(IContainer):
2435
2519
 
2436
2520
  # Check for common typing constructs that shouldn't be instantiated
2437
2521
  typing_constructs = ['Union', 'Optional', 'Any', 'Callable', 'Type']
2522
+
2523
+ # If the type's name matches a known typing construct, it's not instantiable
2438
2524
  if hasattr(type_, '__name__') and type_.__name__ in typing_constructs:
2439
2525
  return True
2440
2526
 
2527
+ # If none of the checks matched, it's not a protocol or typing construct
2441
2528
  return False
2442
2529
 
2443
2530
  def __hasRequiredConstructorParams(self, type_: type) -> bool:
@@ -2499,6 +2586,7 @@ class Container(IContainer):
2499
2586
  """
2500
2587
 
2501
2588
  try:
2589
+
2502
2590
  # For safety, first check if the constructor signature suggests it's safe to instantiate
2503
2591
  try:
2504
2592
 
@@ -2523,8 +2611,10 @@ class Container(IContainer):
2523
2611
  # Attempt to create an instance only if it seems safe
2524
2612
  instance = type_()
2525
2613
 
2526
- # If successful, clean up and return True
2614
+ # If successful, clean up
2527
2615
  del instance
2616
+
2617
+ # Return True if instantiation succeeded
2528
2618
  return True
2529
2619
 
2530
2620
  except Exception:
@@ -2569,6 +2659,7 @@ class Container(IContainer):
2569
2659
  )
2570
2660
 
2571
2661
  try:
2662
+
2572
2663
  # Mark this type as being resolved to prevent circular dependencies
2573
2664
  self.__resolution_cache[type_key] = True
2574
2665
 
@@ -2594,17 +2685,21 @@ class Container(IContainer):
2594
2685
  )
2595
2686
 
2596
2687
  except Exception as e:
2688
+
2597
2689
  # Remove the type from the resolution cache on error
2598
2690
  self.__resolution_cache.pop(type_key, None)
2599
2691
 
2692
+ # If the exception is already an OrionisContainerException, re-raise it
2600
2693
  if isinstance(e, OrionisContainerException):
2601
2694
  raise
2602
- else:
2603
- raise OrionisContainerException(
2604
- f"Failed to auto-resolve '{type_.__name__}': {str(e)}"
2605
- ) from e
2695
+
2696
+ # Otherwise, raise a new OrionisContainerException with additional context
2697
+ raise OrionisContainerException(
2698
+ f"Failed to auto-resolve '{type_.__name__}': {str(e)}"
2699
+ ) from e
2606
2700
 
2607
2701
  finally:
2702
+
2608
2703
  # Always clean up the resolution cache after resolution attempt
2609
2704
  self.__resolution_cache.pop(type_key, None)
2610
2705
 
@@ -2198,11 +2198,7 @@ class Application(Container, IApplication):
2198
2198
  if not self.__booted:
2199
2199
 
2200
2200
  # Register the application instance in the container
2201
- self.instance(
2202
- IApplication,
2203
- self,
2204
- alias="x-orionis.foundation.contracts.application.IApplication"
2205
- )
2201
+ self.instance(IApplication, self, alias="x-orionis.foundation.contracts.application.IApplication")
2206
2202
 
2207
2203
  # Load configuration if not already set
2208
2204
  self.__loadConfig()
@@ -2212,8 +2208,6 @@ class Application(Container, IApplication):
2212
2208
  self.__loadFrameworkProviders()
2213
2209
  self.__registerProviders()
2214
2210
  self.__bootProviders()
2215
-
2216
- # Mark as booted
2217
2211
  self.__booted = True
2218
2212
 
2219
2213
  # Load core framework kernels with app booted
@@ -5,7 +5,7 @@
5
5
  NAME = "orionis"
6
6
 
7
7
  # Current version of the framework
8
- VERSION = "0.652.0"
8
+ VERSION = "0.654.0"
9
9
 
10
10
  # Full name of the author or maintainer of the project
11
11
  AUTHOR = "Raul Mauricio Uñate Castro"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orionis
3
- Version: 0.652.0
3
+ Version: 0.654.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
@@ -67,7 +67,7 @@ orionis/console/stubs/listener.stub,sha256=DbX-ghx2-vb73kzQ6L20lyg5vSKn58jSLTwFu
67
67
  orionis/console/tasks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
68
  orionis/console/tasks/schedule.py,sha256=ZeeuQ9Tbu5KNowKC5oIk7yWeJXzlDQiQ278mWEgoCXc,87989
69
69
  orionis/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
70
- orionis/container/container.py,sha256=FgA-t4mTwyjvaVgnOXnPfhuVB2v288LgO3-gq6tZ0MM,106029
70
+ orionis/container/container.py,sha256=3s1ej-wGeylBzG4qAJ9JOra1Lvt5M3QJyAeu8q23rP8,112421
71
71
  orionis/container/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
72
72
  orionis/container/context/manager.py,sha256=I08K_jKXSKmrq18Pv33qYyMKIlAovVOwIgmfiVm-J7c,2971
73
73
  orionis/container/context/scope.py,sha256=p_oCzR7dDz-5ZAd16ab4vfLc3gBf34CaN0f4iR9D0bQ,1155
@@ -104,7 +104,7 @@ orionis/failure/contracts/handler.py,sha256=AeJfkJfD3hTkOIYAtADq6GnQfq-qWgDfUc7b
104
104
  orionis/failure/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
105
105
  orionis/failure/entities/throwable.py,sha256=1zD-awcuAyEtlR-L7V7ZIfPSF4GpXkf-neL5sXul7dc,1240
106
106
  orionis/foundation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
107
- orionis/foundation/application.py,sha256=hnl72VeiZm2FTsxI3UQvw6_It8cndqPZ0j0Z5T6Ut7s,94126
107
+ orionis/foundation/application.py,sha256=5A93XNiYJi1FEu8hIv2UStxZu--ac4KanhcWsSU25hU,94028
108
108
  orionis/foundation/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
109
109
  orionis/foundation/config/startup.py,sha256=btqvryeIf9lLNQ9fBff7bJMrfraEY8qrWi4y_5YAR0Q,9681
110
110
  orionis/foundation/config/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -217,7 +217,7 @@ orionis/foundation/providers/scheduler_provider.py,sha256=IrPQJwvQVLRm5Qnz0Cxon4
217
217
  orionis/foundation/providers/testing_provider.py,sha256=eI1p2lUlxl25b5Z487O4nmqLE31CTDb4c3Q21xFadkE,1615
218
218
  orionis/foundation/providers/workers_provider.py,sha256=GdHENYV_yGyqmHJHn0DCyWmWId5xWjD48e6Zq2PGCWY,1674
219
219
  orionis/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
220
- orionis/metadata/framework.py,sha256=ZscG6dPe4ughRqIi4LSOzuDGUBUvjZdP7nRI8SNIMzo,4089
220
+ orionis/metadata/framework.py,sha256=cxeQWRZy2fnzU53QvPzM6KYNMf4DDEQhu_iD33csm6E,4089
221
221
  orionis/metadata/package.py,sha256=k7Yriyp5aUcR-iR8SK2ec_lf0_Cyc-C7JczgXa-I67w,16039
222
222
  orionis/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
223
223
  orionis/services/asynchrony/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -404,8 +404,8 @@ orionis/test/validators/workers.py,sha256=rWcdRexINNEmGaO7mnc1MKUxkHKxrTsVuHgbnI
404
404
  orionis/test/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
405
405
  orionis/test/view/render.py,sha256=R55ykeRs0wDKcdTf4O1YZ8GDHTFmJ0IK6VQkbJkYUvo,5571
406
406
  orionis/test/view/report.stub,sha256=QLqqCdRoENr3ECiritRB3DO_MOjRQvgBh5jxZ3Hs1r0,28189
407
- orionis-0.652.0.dist-info/licenses/LICENCE,sha256=JhC-z_9mbpUrCfPjcl3DhDA8trNDMzb57cvRSam1avc,1463
408
- orionis-0.652.0.dist-info/METADATA,sha256=9q56hxrhQy2XQerviQtEiL_8jeg5ooK9p7Aq8ooA2vI,4772
409
- orionis-0.652.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
410
- orionis-0.652.0.dist-info/top_level.txt,sha256=lyXi6jArpqJ-0zzNqd_uwsH-z9TCEBVBL-pC3Ekv7hU,8
411
- orionis-0.652.0.dist-info/RECORD,,
407
+ orionis-0.654.0.dist-info/licenses/LICENCE,sha256=JhC-z_9mbpUrCfPjcl3DhDA8trNDMzb57cvRSam1avc,1463
408
+ orionis-0.654.0.dist-info/METADATA,sha256=MZG7617D7xqfB14CWjZdQ8sqkcMvxrkSucLHJlSTwsM,4772
409
+ orionis-0.654.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
410
+ orionis-0.654.0.dist-info/top_level.txt,sha256=lyXi6jArpqJ-0zzNqd_uwsH-z9TCEBVBL-pC3Ekv7hU,8
411
+ orionis-0.654.0.dist-info/RECORD,,