orionis 0.370.0__py3-none-any.whl → 0.371.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.
@@ -20,83 +20,82 @@ from orionis.services.introspection.callables.reflection import ReflectionCallab
20
20
 
21
21
  class Container(IContainer):
22
22
 
23
- # Singleton instance of the container.
24
- # This is a class variable that holds the single instance of the Container class.
25
- _instance = None
26
-
27
- # Lock for thread-safe singleton instantiation.
28
- # This lock ensures that only one thread can create the instance at a time,
29
- # preventing
30
- _lock = threading.Lock()
31
-
32
- # Class variable to track if the container has been initialized.
33
- # This is used to ensure that the initialization logic runs only once,
34
- # regardless of how many times the class is instantiated.
35
- _initialized = False
36
-
37
- def __new__(
38
- cls
39
- ) -> 'Container':
23
+ # Dictionary to hold singleton instances for each class
24
+ # This allows proper inheritance of the singleton pattern
25
+ _instances = {}
26
+
27
+ # Lock for thread-safe singleton instantiation and access
28
+ # This lock ensures that only one thread can create or access instances at a time
29
+ _lock = threading.RLock() # RLock allows reentrant locking
30
+
31
+ def __new__(cls) -> 'Container':
40
32
  """
41
- Creates and returns a singleton instance of the class.
33
+ Creates and returns a singleton instance for each specific class.
42
34
 
43
- This method implements the singleton pattern, ensuring that only one instance
44
- of the class exists. If an instance does not exist, it acquires a lock to
45
- ensure thread safety and creates the instance. Subsequent calls return the
46
- existing instance.
35
+ This method implements a truly thread-safe singleton pattern with proper
36
+ inheritance support, ensuring that each class in the hierarchy has its own
37
+ singleton instance. Uses double-checked locking with proper memory barriers.
47
38
 
48
39
  Returns
49
40
  -------
50
41
  Container
51
- The singleton instance of the class.
42
+ The singleton instance of the specific class.
43
+
44
+ Notes
45
+ -----
46
+ This implementation is completely thread-safe and guarantees that:
47
+ - Only one instance per class exists across all threads
48
+ - Memory visibility is properly handled
49
+ - No race conditions can occur
50
+ - Inheritance is properly supported
52
51
  """
53
52
 
54
- # Check if the class has an existing instance
55
- if cls._instance is None:
53
+ # First check without lock for performance (fast path)
54
+ if cls in cls._instances:
55
+ return cls._instances[cls]
56
56
 
57
- # Acquire the lock to ensure thread safety during instance creation
58
- with cls._lock:
57
+ # Acquire the lock for the slow path (instance creation)
58
+ with cls._lock:
59
59
 
60
- # If the instance is still None, create a new instance
61
- if cls._instance is None:
60
+ # Double-check if the instance was created by another thread
61
+ # while we were waiting for the lock
62
+ if cls in cls._instances:
63
+ return cls._instances[cls]
62
64
 
63
- # Call the superclass's __new__ method to create a new instance
64
- cls._instance = super(Container, cls).__new__(cls)
65
+ # Create a new instance for this specific class
66
+ instance = super(Container, cls).__new__(cls)
65
67
 
66
- # Return the existing instance of the class
67
- return cls._instance
68
+ # Store the instance in the class-specific dictionary
69
+ # This write is protected by the lock, ensuring memory visibility
70
+ cls._instances[cls] = instance
68
71
 
69
- def __init__(
70
- self
71
- ) -> None:
72
+ return instance
73
+
74
+ def __init__(self) -> None:
72
75
  """
73
76
  Initializes a new instance of the container.
74
77
 
75
78
  This constructor sets up the internal dictionaries for bindings and aliases,
76
- ensuring that these are only initialized once per class. The initialization
77
- is guarded by the `_initialized` class attribute to prevent redundant setup.
78
- The container also registers itself as a service to allow for injection.
79
+ ensuring that these are only initialized once per instance. The initialization
80
+ is guarded by checking if the instance already has the required attributes.
79
81
 
80
82
  Notes
81
83
  -----
82
84
  - The `__bindings` dictionary is used to store service bindings.
83
85
  - The `__aliasses` dictionary is used to store service aliases.
84
- - Initialization occurs only once per class, regardless of the number of instances.
86
+ - Initialization occurs only once per instance, regardless of how many times __init__ is called.
85
87
  - The container registers itself under the IContainer interface to allow for dependency injection.
86
88
  """
87
89
 
88
- # Check if the class has been initialized
89
- if not self.__class__._initialized:
90
+ # Check if the instance has already been initialized
91
+ if not hasattr(self, '_Container__initialized'):
90
92
 
91
93
  # Initialize the container's internal state
92
94
  self.__bindings = {}
93
95
  self.__aliasses = {}
94
96
 
95
- # Set the initialized flag to True to prevent re-initialization
96
- self.__class__._initialized = True
97
-
98
- # Register the container itself as a service
99
- self.instance(IContainer, self)
97
+ # Mark this instance as initialized
98
+ self.__initialized = True
100
99
 
101
100
  def transient(
102
101
  self,
@@ -245,4 +245,27 @@ class IContainer(ABC):
245
245
  alias : str, optional
246
246
  The alias of the service to be removed.
247
247
  """
248
+ pass
249
+
250
+ @abstractmethod
251
+ def createContext(self):
252
+ """
253
+ Creates a new context for managing scoped services.
254
+
255
+ This method returns a context manager that can be used with a 'with' statement
256
+ to control the lifecycle of scoped services.
257
+
258
+ Returns
259
+ -------
260
+ ScopeManager
261
+ A context manager for scoped services.
262
+
263
+ Usage
264
+ -------
265
+ with container.createContext():
266
+ # Scoped services created here will be disposed when exiting this block
267
+ service = container.make(IScopedService)
268
+ ...
269
+ # Scoped services are automatically disposed here
270
+ """
248
271
  pass
@@ -1,8 +1,9 @@
1
1
  from typing import Type, List
2
2
  from orionis.container.container import Container
3
3
  from orionis.container.contracts.service_provider import IServiceProvider
4
+ from orionis.foundation.contracts.application import IApplication
4
5
 
5
- class App(Container):
6
+ class Orionis(Container, IApplication):
6
7
  """
7
8
  Application container that manages service providers.
8
9
 
@@ -33,10 +34,22 @@ class App(Container):
33
34
  Initialize a new App instance.
34
35
 
35
36
  Sets up the container and initializes the provider tracking system.
37
+ This method ensures that initialization only happens once per instance,
38
+ even in a singleton context.
36
39
  """
40
+
41
+ # Call parent constructor first
37
42
  super().__init__()
38
- self.__providers: List[IServiceProvider] = []
39
- self.__booted: bool = False
43
+
44
+ # Check if this specific instance has already been initialized
45
+ if not hasattr(self, '_Orionis__initialized'):
46
+
47
+ # Initialize provider-specific attributes
48
+ self.__providers: List[IServiceProvider] = []
49
+ self.__booted: bool = False
50
+
51
+ # Mark this instance as initialized
52
+ self.__initialized = True
40
53
 
41
54
  def __registerProvider(
42
55
  self,
@@ -0,0 +1,58 @@
1
+ from abc import abstractmethod
2
+ from typing import List, Type
3
+ from orionis.container.contracts.service_provider import IServiceProvider
4
+ from orionis.container.contracts.container import IContainer
5
+
6
+ class IApplication(IContainer):
7
+ """
8
+ Abstract interface for application containers that manage service providers.
9
+
10
+ This interface extends IContainer to provide application-level functionality
11
+ including service provider management and application lifecycle operations.
12
+
13
+ By inheriting from IContainer, this interface provides access to all container
14
+ methods while adding application-specific functionality.
15
+ """
16
+
17
+ @property
18
+ @abstractmethod
19
+ def isBooted(self) -> bool:
20
+ """
21
+ Check if the application providers have been booted.
22
+
23
+ Returns
24
+ -------
25
+ bool
26
+ True if providers are booted, False otherwise
27
+ """
28
+ pass
29
+
30
+ @abstractmethod
31
+ def load(self, providers: List[Type[IServiceProvider]]) -> None:
32
+ """
33
+ Load and boot a list of service providers.
34
+
35
+ This method registers each provider and then boots all providers.
36
+
37
+ Parameters
38
+ ----------
39
+ providers : List[Type[IServiceProvider]]
40
+ List of service provider classes to register and boot
41
+
42
+ Returns
43
+ -------
44
+ None
45
+ """
46
+ pass
47
+
48
+ @abstractmethod
49
+ def getProviders(self) -> List[IServiceProvider]:
50
+ """
51
+ Get the list of registered providers.
52
+
53
+ Returns
54
+ -------
55
+ List[IServiceProvider]
56
+ The list of registered service providers
57
+ """
58
+ pass
@@ -1,4 +1,4 @@
1
- from orionis._console.dumper.dump_die import Debug
1
+ from orionis.console.dumper.dump import Debug
2
2
  from orionis.console.dumper.contracts.dump import IDebug
3
3
  from orionis.container.providers.service_provider import ServiceProvider
4
4
 
@@ -5,7 +5,7 @@
5
5
  NAME = "orionis"
6
6
 
7
7
  # Current version of the framework
8
- VERSION = "0.370.0"
8
+ VERSION = "0.371.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.370.0
3
+ Version: 0.371.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
@@ -113,12 +113,12 @@ orionis/console/output/contracts/console.py,sha256=F2c1jC_O61o7jDiXwAeZAOEodEhuC
113
113
  orionis/console/output/enums/__init__.py,sha256=LAaAxg-DpArCjf_jqZ0_9s3p8899gntDYkSU_ppTdC8,66
114
114
  orionis/console/output/enums/styles.py,sha256=6a4oQCOBOKMh2ARdeq5GlIskJ3wjiylYmh66tUKKmpQ,4053
115
115
  orionis/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
116
- orionis/container/container.py,sha256=1fGOHN_4M4YAA_6ljGHB669hY6egl_Cyb6L9EZtFK9E,23083
116
+ orionis/container/container.py,sha256=HgUoQrAz9sM2QLfiDbz2Lm_pqhZ0TRkPtGynVs7TgVU,23176
117
117
  orionis/container/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
118
118
  orionis/container/context/manager.py,sha256=9yODWkHBoJ2kgJZ5ONLqcEcex50vaWuMcxsvmDgnQo4,2437
119
119
  orionis/container/context/scope.py,sha256=CWFiLLTAC_IdmeFKWX-jrphdxB0_TMEVBlz6lQVMPC8,937
120
120
  orionis/container/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
121
- orionis/container/contracts/container.py,sha256=hOO3w2yqVhp2nPTeS1uJEYgXSTbM3xwezDCOSNMC_a0,7603
121
+ orionis/container/contracts/container.py,sha256=QV_seo8mKrZJG2Ytr2u0RSiRaTaSPw6zUxgJ_tq6oP4,8301
122
122
  orionis/container/contracts/resolver.py,sha256=mR7lztPAQDwyspoQewaTMQPxJaoOCA88euDevaZYHGo,1712
123
123
  orionis/container/contracts/service_provider.py,sha256=hXp-l4iP7q0FhsCcQAKoYcJ_zxCzIgTdfmO4F0Bbssg,896
124
124
  orionis/container/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -147,7 +147,7 @@ orionis/container/validators/is_subclass.py,sha256=4sBaGLoRs8nUhuWjlP0VJqyTwVHYq
147
147
  orionis/container/validators/is_valid_alias.py,sha256=4uAYcq8xov7jZbXnpKpjNkxcZtlTNnL5RRctVPMwJes,1424
148
148
  orionis/container/validators/lifetime.py,sha256=IQ43fDNrxYHMlZH2zlYDJnlkLO_eS4U7Fs3UJgQBidI,1844
149
149
  orionis/foundation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
150
- orionis/foundation/application.py,sha256=OiBbTI-4cGTEZppVaFxDHadvsb_jRl8aDwJEwlypVLg,4799
150
+ orionis/foundation/application.py,sha256=wYt664l8v95_B3ny0i83aq07OUTsp-uwF3sqYD-PtaY,5331
151
151
  orionis/foundation/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
152
152
  orionis/foundation/config/startup.py,sha256=zutF-34DkW68bpiTxH9xrmIe1iJdXCF9Y6wueXS6qys,8265
153
153
  orionis/foundation/config/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -236,18 +236,19 @@ orionis/foundation/config/testing/entities/testing.py,sha256=keU7dSuRv0rgaG-T4Vo
236
236
  orionis/foundation/config/testing/enums/__init__.py,sha256=tCHed6wBzqHx8o3kWBGm8tZYkYOKdSAx8TvgC-Eauv0,75
237
237
  orionis/foundation/config/testing/enums/test_mode.py,sha256=IbFpauu7J-iSAfmC8jDbmTEYl8eZr-AexL-lyOh8_74,337
238
238
  orionis/foundation/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
239
+ orionis/foundation/contracts/application.py,sha256=Zr10-f7p8QKhKwGJMscX9-euuUlN8sq2BTShjSqczX4,1688
239
240
  orionis/foundation/contracts/config.py,sha256=Rpz6U6t8OXHO9JJKSTnCimytXE-tfCB-1ithP2nG8MQ,628
240
241
  orionis/foundation/exceptions/__init__.py,sha256=XtG3MJ_MFNY_dU5mmTyz_N_4QG1jYrcv5RegBso7wuY,163
241
242
  orionis/foundation/exceptions/integrity.py,sha256=mc4pL1UMoYRHEmphnpW2oGk5URhu7DJRREyzHaV-cs8,472
242
243
  orionis/foundation/exceptions/value.py,sha256=hQhXybXEnaa59ba7JxG65jceHt3mnql9MyekF-TChpM,465
243
244
  orionis/foundation/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
244
245
  orionis/foundation/providers/console_provider.py,sha256=pAIklY1QKx2HKjTp7YyJT6KbJPlEEyzWSr79RTFkEK0,700
245
- orionis/foundation/providers/dumper_provider.py,sha256=mLJDpNNNl4PV8oM_GKBvSxBcfXRxgiBlrA9Qg5WKi0A,689
246
+ orionis/foundation/providers/dumper_provider.py,sha256=_CjIZoa1EkITkJqFFWQuLeVpagSnb6TuSwcpvqdM-Bc,684
246
247
  orionis/foundation/providers/path_resolver_provider.py,sha256=rXvaVc5sSqmDgRzWJoattAW0ikO_SF3H7WBddVxwmhw,717
247
248
  orionis/foundation/providers/progress_bar_provider.py,sha256=75Jr4iEgUOUGl8Di1DioeP5_HRQlR-1lVzPmS96sWjA,737
248
249
  orionis/foundation/providers/workers_provider.py,sha256=WWlji3C69_-Y0c42aZDbR_bmcE_qZEh2SaA_cNkCivI,702
249
250
  orionis/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
250
- orionis/metadata/framework.py,sha256=uWb-E59Z6jG1FTYOZfjfo1edZBIuB7aSMG_xOytZZlk,4960
251
+ orionis/metadata/framework.py,sha256=ELLE9bftoocsTWd1mXjuTK3xa3mgdzsQ9BRkRihfQ5g,4960
251
252
  orionis/metadata/package.py,sha256=tqLfBRo-w1j_GN4xvzUNFyweWYFS-qhSgAEc-AmCH1M,5452
252
253
  orionis/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
253
254
  orionis/services/asynchrony/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -379,7 +380,7 @@ orionis/test/output/dumper.py,sha256=3EV-G3KgEV4O0M4yl-4klPKc1etWOPZvPAcYhUQyXnI
379
380
  orionis/test/output/printer.py,sha256=WGjGW2lgu_l5wWJ6Z8qTTV7NAObhoTBcvhM1TcNvwU4,16938
380
381
  orionis/test/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
381
382
  orionis/test/view/render.py,sha256=jXZkbITBknbUwm_mD8bcTiwLDvsFkrO9qrf0ZgPwqxc,4903
382
- orionis-0.370.0.dist-info/licenses/LICENCE,sha256=-_4cF2EBKuYVS_SQpy1uapq0oJPUU1vl_RUWSy2jJTo,1111
383
+ orionis-0.371.0.dist-info/licenses/LICENCE,sha256=-_4cF2EBKuYVS_SQpy1uapq0oJPUU1vl_RUWSy2jJTo,1111
383
384
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
384
385
  tests/example/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
385
386
  tests/example/test_example.py,sha256=kvWgiW3ADEZf718dGsMPtDh_rmOSx1ypEInKm7_6ZPQ,601
@@ -480,8 +481,8 @@ tests/support/wrapper/test_services_wrapper_docdict.py,sha256=hIVqGt19vbW22xPjQS
480
481
  tests/testing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
481
482
  tests/testing/test_testing_result.py,sha256=1O_8xjsFPnzwZOpLT6ImqjO9HY5_jIgP7DTVBsgHvQA,4335
482
483
  tests/testing/test_testing_unit.py,sha256=S3anwYcF2DBWYh_UfqKcZq2FgNpQjP0SfYVRd5sD5rI,7442
483
- orionis-0.370.0.dist-info/METADATA,sha256=ThIPJvF6BMpzcZ7eG6-X8ojdk7l_Ce8Meo7rddmoVlE,4772
484
- orionis-0.370.0.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
485
- orionis-0.370.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
486
- orionis-0.370.0.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
487
- orionis-0.370.0.dist-info/RECORD,,
484
+ orionis-0.371.0.dist-info/METADATA,sha256=R3PbjmUDx3DhHzBDS9GdFoa-PHUZ45PgXWXiPB5jHh8,4772
485
+ orionis-0.371.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
486
+ orionis-0.371.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
487
+ orionis-0.371.0.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
488
+ orionis-0.371.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.7.1)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5