orionis 0.321.0__py3-none-any.whl → 0.323.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/container/container.py +25 -2
- orionis/container/context/manager.py +94 -0
- orionis/container/context/scope.py +40 -0
- orionis/container/contracts/container.py +1 -1
- orionis/container/facades/__init__.py +0 -0
- orionis/container/facades/facade.py +60 -0
- orionis/container/resolver.py +54 -5
- orionis/metadata/framework.py +1 -1
- {orionis-0.321.0.dist-info → orionis-0.323.0.dist-info}/METADATA +1 -1
- {orionis-0.321.0.dist-info → orionis-0.323.0.dist-info}/RECORD +15 -16
- orionis/_container/container.py +0 -543
- orionis/_container/container_integrity.py +0 -292
- orionis/_container/exception.py +0 -54
- orionis/_container/lifetimes.py +0 -13
- orionis/_container/resolve.py +0 -64
- /orionis/{_container → container/context}/__init__.py +0 -0
- {orionis-0.321.0.dist-info → orionis-0.323.0.dist-info}/WHEEL +0 -0
- {orionis-0.321.0.dist-info → orionis-0.323.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.321.0.dist-info → orionis-0.323.0.dist-info}/top_level.txt +0 -0
- {orionis-0.321.0.dist-info → orionis-0.323.0.dist-info}/zip-safe +0 -0
orionis/container/container.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import threading
|
2
2
|
from typing import Any, Callable
|
3
|
+
from orionis.container.context.manager import ScopeManager
|
3
4
|
from orionis.container.contracts.container import IContainer
|
4
5
|
from orionis.container.entities.binding import Binding
|
5
6
|
from orionis.container.enums.lifetimes import Lifetime
|
@@ -430,7 +431,7 @@ class Container(IContainer):
|
|
430
431
|
# Return True to indicate successful registration
|
431
432
|
return True
|
432
433
|
|
433
|
-
def
|
434
|
+
def callable(
|
434
435
|
self,
|
435
436
|
alias: str,
|
436
437
|
fn: Callable[..., Any],
|
@@ -633,4 +634,26 @@ class Container(IContainer):
|
|
633
634
|
binding,
|
634
635
|
*args,
|
635
636
|
**kwargs
|
636
|
-
)
|
637
|
+
)
|
638
|
+
|
639
|
+
def createContext(self) -> ScopeManager:
|
640
|
+
"""
|
641
|
+
Creates a new context for managing scoped services.
|
642
|
+
|
643
|
+
This method returns a context manager that can be used with a 'with' statement
|
644
|
+
to control the lifecycle of scoped services.
|
645
|
+
|
646
|
+
Returns
|
647
|
+
-------
|
648
|
+
ScopeManager
|
649
|
+
A context manager for scoped services.
|
650
|
+
|
651
|
+
Usage
|
652
|
+
-------
|
653
|
+
with container.createContext():
|
654
|
+
# Scoped services created here will be disposed when exiting this block
|
655
|
+
service = container.make(IScopedService)
|
656
|
+
...
|
657
|
+
# Scoped services are automatically disposed here
|
658
|
+
"""
|
659
|
+
return ScopeManager()
|
@@ -0,0 +1,94 @@
|
|
1
|
+
from orionis.container.context.scope import ScopedContext
|
2
|
+
|
3
|
+
class ScopeManager:
|
4
|
+
"""
|
5
|
+
A context manager to manage scoped lifetimes in the container.
|
6
|
+
"""
|
7
|
+
def __init__(self):
|
8
|
+
"""
|
9
|
+
Initialize a new ScopeManager with an empty instances dictionary.
|
10
|
+
"""
|
11
|
+
self._instances = {}
|
12
|
+
|
13
|
+
def __getitem__(self, key):
|
14
|
+
"""
|
15
|
+
Get an instance by key.
|
16
|
+
|
17
|
+
Parameters
|
18
|
+
----------
|
19
|
+
key : hashable
|
20
|
+
The key of the instance to retrieve.
|
21
|
+
|
22
|
+
Returns
|
23
|
+
-------
|
24
|
+
object or None
|
25
|
+
The instance associated with the key or None if not found.
|
26
|
+
"""
|
27
|
+
return self._instances.get(key)
|
28
|
+
|
29
|
+
def __setitem__(self, key, value):
|
30
|
+
"""
|
31
|
+
Store an instance by key.
|
32
|
+
|
33
|
+
Parameters
|
34
|
+
----------
|
35
|
+
key : hashable
|
36
|
+
The key to associate with the instance.
|
37
|
+
value : object
|
38
|
+
The instance to store.
|
39
|
+
"""
|
40
|
+
self._instances[key] = value
|
41
|
+
|
42
|
+
def __contains__(self, key):
|
43
|
+
"""
|
44
|
+
Check if a key exists in this scope.
|
45
|
+
|
46
|
+
Parameters
|
47
|
+
----------
|
48
|
+
key : hashable
|
49
|
+
The key to check.
|
50
|
+
|
51
|
+
Returns
|
52
|
+
-------
|
53
|
+
bool
|
54
|
+
True if the key exists in the scope, False otherwise.
|
55
|
+
"""
|
56
|
+
return key in self._instances
|
57
|
+
|
58
|
+
def clear(self):
|
59
|
+
"""
|
60
|
+
Clear all instances from this scope.
|
61
|
+
"""
|
62
|
+
self._instances.clear()
|
63
|
+
|
64
|
+
def __enter__(self):
|
65
|
+
"""
|
66
|
+
Enter the scope context.
|
67
|
+
|
68
|
+
Sets this scope as the current active scope.
|
69
|
+
|
70
|
+
Returns
|
71
|
+
-------
|
72
|
+
ScopeManager
|
73
|
+
This scope manager instance.
|
74
|
+
"""
|
75
|
+
ScopedContext.setCurrentScope(self)
|
76
|
+
return self
|
77
|
+
|
78
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
79
|
+
"""
|
80
|
+
Exit the scope context.
|
81
|
+
|
82
|
+
Clears this scope and the active scope reference.
|
83
|
+
|
84
|
+
Parameters
|
85
|
+
----------
|
86
|
+
exc_type : type or None
|
87
|
+
The exception type if an exception was raised, None otherwise.
|
88
|
+
exc_val : Exception or None
|
89
|
+
The exception instance if an exception was raised, None otherwise.
|
90
|
+
exc_tb : traceback or None
|
91
|
+
The exception traceback if an exception was raised, None otherwise.
|
92
|
+
"""
|
93
|
+
self.clear()
|
94
|
+
ScopedContext.clear()
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import contextvars
|
2
|
+
|
3
|
+
class ScopedContext:
|
4
|
+
"""
|
5
|
+
Holds scoped instances for the current context.
|
6
|
+
"""
|
7
|
+
_active_scope = contextvars.ContextVar("orionis_scope", default=None)
|
8
|
+
|
9
|
+
@classmethod
|
10
|
+
def getCurrentScope(cls):
|
11
|
+
"""
|
12
|
+
Get the currently active scope.
|
13
|
+
|
14
|
+
Returns
|
15
|
+
-------
|
16
|
+
object or None
|
17
|
+
The current active scope or None if no scope is active.
|
18
|
+
"""
|
19
|
+
return cls._active_scope.get()
|
20
|
+
|
21
|
+
@classmethod
|
22
|
+
def setCurrentScope(cls, scope):
|
23
|
+
"""
|
24
|
+
Set the current active scope.
|
25
|
+
|
26
|
+
Parameters
|
27
|
+
----------
|
28
|
+
scope : object
|
29
|
+
The scope object to set as active.
|
30
|
+
"""
|
31
|
+
cls._active_scope.set(scope)
|
32
|
+
|
33
|
+
@classmethod
|
34
|
+
def clear(cls):
|
35
|
+
"""
|
36
|
+
Clear the current active scope.
|
37
|
+
|
38
|
+
Sets the active scope to None.
|
39
|
+
"""
|
40
|
+
cls._active_scope.set(None)
|
File without changes
|
@@ -0,0 +1,60 @@
|
|
1
|
+
from typing import Any
|
2
|
+
from orionis.container.container import Container
|
3
|
+
|
4
|
+
class FacadeMeta(type):
|
5
|
+
|
6
|
+
def __getattr__(cls, name: str) -> Any:
|
7
|
+
"""
|
8
|
+
When an undefined attribute is accessed, this method resolves the service and delegates the call.
|
9
|
+
It's like having a genie in a bottle, but for services.
|
10
|
+
|
11
|
+
Args:
|
12
|
+
name: The name of the attribute to access
|
13
|
+
|
14
|
+
Returns:
|
15
|
+
The requested attribute from the underlying service
|
16
|
+
"""
|
17
|
+
service = cls.resolve()
|
18
|
+
if not hasattr(service, name):
|
19
|
+
raise AttributeError(f"'{cls.__name__}' facade's service has no attribute '{name}'")
|
20
|
+
return getattr(service, name)
|
21
|
+
|
22
|
+
|
23
|
+
class Facade(metaclass=FacadeMeta):
|
24
|
+
|
25
|
+
_container = Container()
|
26
|
+
|
27
|
+
@classmethod
|
28
|
+
def getFacadeAccessor(cls) -> str:
|
29
|
+
"""
|
30
|
+
This method must be overridden by subclasses to return the name of the service to be resolved.
|
31
|
+
If not, it throws a tantrum (NotImplementedError).
|
32
|
+
|
33
|
+
Returns:
|
34
|
+
The service name to be resolved from the container
|
35
|
+
"""
|
36
|
+
raise NotImplementedError(f"Class {cls.__name__} must define the getFacadeAccessor method")
|
37
|
+
|
38
|
+
@classmethod
|
39
|
+
def resolve(cls) -> Any:
|
40
|
+
"""
|
41
|
+
Resolves the service from the Container with caching for improved performance.
|
42
|
+
It's like calling the butler to fetch something from the pantry.
|
43
|
+
|
44
|
+
Returns:
|
45
|
+
The resolved service instance
|
46
|
+
"""
|
47
|
+
|
48
|
+
# Get the service name from the facade accessor
|
49
|
+
service_name = cls.getFacadeAccessor()
|
50
|
+
|
51
|
+
# Check if the service is bound in the container
|
52
|
+
if not cls._container.bound(service_name):
|
53
|
+
raise RuntimeError(
|
54
|
+
f"The service '{service_name}' is not bound in the container. "
|
55
|
+
"Did you forget to register it?"
|
56
|
+
)
|
57
|
+
|
58
|
+
# Resolve the service instance from the container
|
59
|
+
service_instance = cls._container.make(service_name)
|
60
|
+
return service_instance
|
orionis/container/resolver.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
from typing import Any, Callable
|
2
|
+
from orionis.container.context.scope import ScopedContext
|
2
3
|
from orionis.container.contracts.container import IContainer
|
3
4
|
from orionis.container.entities.binding import Binding
|
4
5
|
from orionis.container.enums.lifetimes import Lifetime
|
@@ -61,10 +62,7 @@ class Resolver:
|
|
61
62
|
elif binding.lifetime == Lifetime.SINGLETON:
|
62
63
|
return self.__resolveSingleton(binding, *args, **kwargs)
|
63
64
|
elif binding.lifetime == Lifetime.SCOPED:
|
64
|
-
|
65
|
-
raise OrionisContainerException(
|
66
|
-
"Scoped lifetime resolution is not yet implemented."
|
67
|
-
)
|
65
|
+
return self.__resolveScoped(binding, *args, **kwargs)
|
68
66
|
|
69
67
|
def __resolveTransient(self, binding: Binding, *args, **kwargs) -> Any:
|
70
68
|
"""
|
@@ -153,6 +151,58 @@ class Resolver:
|
|
153
151
|
"Cannot resolve singleton binding: neither a concrete class, instance, nor function is defined."
|
154
152
|
)
|
155
153
|
|
154
|
+
def __resolveScoped(self, binding: Binding, *args, **kwargs) -> Any:
|
155
|
+
"""
|
156
|
+
Resolves a service with scoped lifetime.
|
157
|
+
|
158
|
+
Parameters
|
159
|
+
----------
|
160
|
+
binding : Binding
|
161
|
+
The binding to resolve.
|
162
|
+
*args : tuple
|
163
|
+
Positional arguments to pass to the constructor.
|
164
|
+
**kwargs : dict
|
165
|
+
Keyword arguments to pass to the constructor.
|
166
|
+
|
167
|
+
Returns
|
168
|
+
-------
|
169
|
+
Any
|
170
|
+
The scoped instance of the requested service.
|
171
|
+
|
172
|
+
Raises
|
173
|
+
------
|
174
|
+
OrionisContainerException
|
175
|
+
If no scope is active or service can't be resolved.
|
176
|
+
"""
|
177
|
+
scope = ScopedContext.getCurrentScope()
|
178
|
+
if scope is None:
|
179
|
+
raise OrionisContainerException(
|
180
|
+
f"No active scope found while resolving scoped service '{binding.alias}'. "
|
181
|
+
f"Use 'with container.createContext():' to create a scope context."
|
182
|
+
)
|
183
|
+
|
184
|
+
if binding.alias in scope:
|
185
|
+
return scope[binding.alias]
|
186
|
+
|
187
|
+
# Create a new instance
|
188
|
+
if binding.concrete:
|
189
|
+
if args or kwargs:
|
190
|
+
instance = self.__instantiateConcreteWithArgs(binding.concrete, *args, **kwargs)
|
191
|
+
else:
|
192
|
+
instance = self.__instantiateConcreteReflective(binding.concrete)
|
193
|
+
elif binding.function:
|
194
|
+
if args or kwargs:
|
195
|
+
instance = self.__instantiateCallableWithArgs(binding.function, *args, **kwargs)
|
196
|
+
else:
|
197
|
+
instance = self.__instantiateCallableReflective(binding.function)
|
198
|
+
else:
|
199
|
+
raise OrionisContainerException(
|
200
|
+
"Cannot resolve scoped binding: neither a concrete class nor a function is defined."
|
201
|
+
)
|
202
|
+
|
203
|
+
scope[binding.alias] = instance
|
204
|
+
return instance
|
205
|
+
|
156
206
|
def __instantiateConcreteWithArgs(self, concrete: Callable[..., Any], *args, **kwargs) -> Any:
|
157
207
|
"""
|
158
208
|
Instantiates a concrete class with the provided arguments.
|
@@ -401,4 +451,3 @@ class Resolver:
|
|
401
451
|
|
402
452
|
# Raise a more informative exception
|
403
453
|
raise OrionisContainerException(error_msg) from e
|
404
|
-
|
orionis/metadata/framework.py
CHANGED
@@ -2,12 +2,6 @@ orionis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
orionis/_application.py,sha256=dMjJ0nFcIIOBGb5zr-tHNzcgTOZ1vJ7iMdFAlqSQph0,9405
|
3
3
|
orionis/application.py,sha256=Off5uOUj-IYvvR8DcqLUoBW_98opWa7MQrtqTr0SZGc,292
|
4
4
|
orionis/unittesting.py,sha256=_NU3_sm3R6bUUH_Y-KSPgNVBajUGCtKo_CGgjB1YD5k,2094
|
5
|
-
orionis/_container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
-
orionis/_container/container.py,sha256=0AOqTNwpN_OtWbq9mBI99qfJ7LMkN71y0lP0JWKzut0,18289
|
7
|
-
orionis/_container/container_integrity.py,sha256=vrqZrkJaP6ghbiAzr-nEul9f_lEWVa2nMUSugQXDfWk,10095
|
8
|
-
orionis/_container/exception.py,sha256=ap1SqYEjQEEHXJJTNmL7V1jrmRjgT5_7geZ95MYkhMA,1691
|
9
|
-
orionis/_container/lifetimes.py,sha256=2lbdiV7R2WlJf1cLD6eBxLnJud_lZvX1IhQH2Djy3Ww,375
|
10
|
-
orionis/_container/resolve.py,sha256=5qVE--fBpbVFiTYM_jXKbjHNssm28aM4cwd49AhiLkY,2231
|
11
5
|
orionis/_contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
6
|
orionis/_contracts/application.py,sha256=ltuDA1mN5P73l89jJto_A96ePJWE02OZ_B2NOPpfeWs,1061
|
13
7
|
orionis/_contracts/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -135,14 +129,19 @@ orionis/console/output/console.py,sha256=TE_Hl720ADd82dbERFSWhkoQRukDQZmETSw4nkw
|
|
135
129
|
orionis/console/output/executor.py,sha256=bdvkzW2-buy0BPpy2r5qUGrRFW2Ay6k-5rSeHb0gQ3o,3352
|
136
130
|
orionis/console/output/progress_bar.py,sha256=vFy582z6VJS46LV6tuyrmr9qvdVeTEtw3hyNcEHezeg,3088
|
137
131
|
orionis/console/output/styles.py,sha256=6a4oQCOBOKMh2ARdeq5GlIskJ3wjiylYmh66tUKKmpQ,4053
|
138
|
-
orionis/container/container.py,sha256=
|
139
|
-
orionis/container/resolver.py,sha256=
|
140
|
-
orionis/container/
|
132
|
+
orionis/container/container.py,sha256=dIfHPCC28_Eho7kgp0AUFS1S5iaCD4ws7udCy_jQ6sE,23112
|
133
|
+
orionis/container/resolver.py,sha256=bR26v1bAtg9FgDtfs6zP30-g75aWrSO43UJPweJ7jfo,18014
|
134
|
+
orionis/container/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
135
|
+
orionis/container/context/manager.py,sha256=9yODWkHBoJ2kgJZ5ONLqcEcex50vaWuMcxsvmDgnQo4,2437
|
136
|
+
orionis/container/context/scope.py,sha256=CWFiLLTAC_IdmeFKWX-jrphdxB0_TMEVBlz6lQVMPC8,937
|
137
|
+
orionis/container/contracts/container.py,sha256=hOO3w2yqVhp2nPTeS1uJEYgXSTbM3xwezDCOSNMC_a0,7603
|
141
138
|
orionis/container/entities/binding.py,sha256=Qp6Lf4XUDp2NjqXDAC2lzvhOFQWiBDKiGFcKfwb4axw,4342
|
142
139
|
orionis/container/enums/lifetimes.py,sha256=RqQmugMIB1Ev_j_vFLcWorndm-to7xg4stQ7yKFDdDw,190
|
143
140
|
orionis/container/exceptions/container_exception.py,sha256=goTDEwC70xTMD2qppN8KV-xyR0Nps218OD4D1LZ2-3s,470
|
144
141
|
orionis/container/exceptions/type_error_exception.py,sha256=cYuvoXVOgRYj3tZPfK341aUERkf33-buOiI2eXxcrAw,470
|
145
142
|
orionis/container/exceptions/value_exception.py,sha256=hjY0YEusoL3DurME1ornxvIv1wyGaf6tBggLFlGHblo,472
|
143
|
+
orionis/container/facades/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
144
|
+
orionis/container/facades/facade.py,sha256=8YMuZp9Mc--OfGzcyDbSke8Xi5V1kpRglHvMWftr1DQ,2075
|
146
145
|
orionis/container/validators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
147
146
|
orionis/container/validators/implements.py,sha256=iSoDxxTalQKhyKjvsojFlkROhBFvAjvJxRvPJlmGrSg,2843
|
148
147
|
orionis/container/validators/is_abstract_class.py,sha256=Q-Lqyrrps6oj2XWI0KFRp-hDZf4_sgbZlEbfBXj5XT4,1169
|
@@ -244,7 +243,7 @@ orionis/foundation/contracts/config.py,sha256=Rpz6U6t8OXHO9JJKSTnCimytXE-tfCB-1i
|
|
244
243
|
orionis/foundation/exceptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
245
244
|
orionis/foundation/exceptions/integrity.py,sha256=mc4pL1UMoYRHEmphnpW2oGk5URhu7DJRREyzHaV-cs8,472
|
246
245
|
orionis/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
247
|
-
orionis/metadata/framework.py,sha256=
|
246
|
+
orionis/metadata/framework.py,sha256=Oj4bwfkR8QW41Dfg0E01NAG-hIkgTRZiDT9rY93ZFqM,4960
|
248
247
|
orionis/metadata/package.py,sha256=tqLfBRo-w1j_GN4xvzUNFyweWYFS-qhSgAEc-AmCH1M,5452
|
249
248
|
orionis/patterns/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
250
249
|
orionis/patterns/singleton/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -356,7 +355,7 @@ orionis/test/suite/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuF
|
|
356
355
|
orionis/test/suite/test_unit.py,sha256=MWgW8dRCRyT1XZ5LsbXQ7-KVPReasoXwzEEL1EWWfE4,52190
|
357
356
|
orionis/test/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
358
357
|
orionis/test/view/render.py,sha256=jXZkbITBknbUwm_mD8bcTiwLDvsFkrO9qrf0ZgPwqxc,4903
|
359
|
-
orionis-0.
|
358
|
+
orionis-0.323.0.dist-info/licenses/LICENCE,sha256=-_4cF2EBKuYVS_SQpy1uapq0oJPUU1vl_RUWSy2jJTo,1111
|
360
359
|
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
361
360
|
tests/example/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
362
361
|
tests/example/test_example.py,sha256=kvWgiW3ADEZf718dGsMPtDh_rmOSx1ypEInKm7_6ZPQ,601
|
@@ -457,8 +456,8 @@ tests/support/wrapper/test_services_wrapper_docdict.py,sha256=yeVwl-VcwkWSQYyxZu
|
|
457
456
|
tests/testing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
458
457
|
tests/testing/test_testing_result.py,sha256=MrGK3ZimedL0b5Ydu69Dg8Iul017AzLTm7VPxpXlpfU,4315
|
459
458
|
tests/testing/test_testing_unit.py,sha256=DjLBtvVn8B1KlVJNNkstBT8_csA1yeaMqnGrbanN_J4,7438
|
460
|
-
orionis-0.
|
461
|
-
orionis-0.
|
462
|
-
orionis-0.
|
463
|
-
orionis-0.
|
464
|
-
orionis-0.
|
459
|
+
orionis-0.323.0.dist-info/METADATA,sha256=9ItAv8CGa3j5dBYJeOZyBivus_9cy2pl5mjtNvMCIwY,4772
|
460
|
+
orionis-0.323.0.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
|
461
|
+
orionis-0.323.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
|
462
|
+
orionis-0.323.0.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
463
|
+
orionis-0.323.0.dist-info/RECORD,,
|