orionis 0.606.0__py3-none-any.whl → 0.608.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.
@@ -5,7 +5,7 @@
5
5
  NAME = "orionis"
6
6
 
7
7
  # Current version of the framework
8
- VERSION = "0.606.0"
8
+ VERSION = "0.608.0"
9
9
 
10
10
  # Full name of the author or maintainer of the project
11
11
  AUTHOR = "Raul Mauricio Uñate Castro"
@@ -317,27 +317,44 @@ class ReflectionConcrete(IReflectionConcrete):
317
317
  """
318
318
  return attribute in self.getAttributes()
319
319
 
320
- def getAttribute(self, attribute: str):
320
+ def getAttribute(self, name: str, default: Any = None) -> Any:
321
321
  """
322
- Get the value of a specific class attribute.
322
+ Retrieve the value of a specific class attribute.
323
+
324
+ This method attempts to fetch the value of the specified attribute from the class.
325
+ It first checks the combined attributes dictionary (including public, protected,
326
+ private, and dunder attributes). If the attribute is not found there, it falls
327
+ back to using `getattr` on the class itself. If the attribute does not exist,
328
+ the provided default value is returned.
323
329
 
324
330
  Parameters
325
331
  ----------
326
- attribute : str
332
+ name : str
327
333
  The name of the attribute to retrieve.
334
+ default : Any, optional
335
+ The value to return if the attribute is not found (default is None).
328
336
 
329
337
  Returns
330
338
  -------
331
339
  Any
332
- The value of the specified attribute, or None if not found.
340
+ The value of the specified attribute if found; otherwise, the provided default value.
333
341
 
334
342
  Raises
335
343
  ------
336
344
  ReflectionValueError
337
345
  If the attribute does not exist or is not accessible.
346
+
347
+ Notes
348
+ -----
349
+ This method does not raise an exception if the attribute is missing; it returns
350
+ the default value instead.
338
351
  """
352
+
353
+ # Get all attributes from the class (public, protected, private, dunder)
339
354
  attrs = self.getAttributes()
340
- return attrs.get(attribute, None)
355
+
356
+ # Try to get the attribute from the attributes dictionary; if not found, use getattr on the class
357
+ return attrs.get(name, getattr(self._concrete, name, default))
341
358
 
342
359
  def setAttribute(self, name: str, value) -> bool:
343
360
  """
@@ -247,27 +247,39 @@ class ReflectionInstance(IReflectionInstance):
247
247
  """
248
248
  return name in self.getAttributes()
249
249
 
250
- def getAttribute(self, name: str) -> Any:
250
+ def getAttribute(self, name: str, default: Any = None) -> Any:
251
251
  """
252
- Get an attribute value by name.
252
+ Retrieve the value of an attribute by its name from the instance.
253
253
 
254
254
  Parameters
255
255
  ----------
256
256
  name : str
257
- The attribute name
257
+ The name of the attribute to retrieve.
258
+ default : Any, optional
259
+ The value to return if the attribute does not exist (default is None).
258
260
 
259
261
  Returns
260
262
  -------
261
263
  Any
262
- The attribute value
264
+ The value of the specified attribute if it exists; otherwise, returns the provided `default` value.
263
265
 
264
266
  Raises
265
267
  ------
266
268
  AttributeError
267
- If the attribute doesn't exist
269
+ If the attribute does not exist and no default value is provided.
270
+
271
+ Notes
272
+ -----
273
+ This method first checks the instance's attributes dictionary for the given name.
274
+ If not found, it attempts to retrieve the attribute directly from the instance using `getattr`.
275
+ If the attribute is still not found, the `default` value is returned.
268
276
  """
277
+
278
+ # Get all attributes of the instance (public, protected, private, dunder)
269
279
  attrs = self.getAttributes()
270
- return attrs.get(name, None)
280
+
281
+ # Try to get the attribute from the attributes dictionary; if not found, use getattr with default
282
+ return attrs.get(name, getattr(self._instance, name, default))
271
283
 
272
284
  def setAttribute(self, name: str, value: Any) -> bool:
273
285
  """
@@ -532,33 +544,13 @@ class ReflectionInstance(IReflectionInstance):
532
544
  if not callable(method):
533
545
  raise ReflectionAttributeError(f"Cannot set attribute '{name}' to a non-callable value.")
534
546
 
535
- # Extarct the signature of the method and classtype
536
- sign = inspect.signature(method)
537
- classtype = self.getClass()
538
-
539
- # Check first parameter is 'cls'
540
- params = list(sign.parameters.values())
541
- if not params or params[0].name != "cls":
542
- raise ReflectionAttributeError(f"The first (or only) argument of the method must be named 'cls' and must be of type {classtype}.")
543
-
544
- # Get the expected type from the first parameter's annotation
545
- annotation = params[0].annotation
546
- if annotation != classtype:
547
- raise ReflectionAttributeError(
548
- f"The first argument has an incorrect annotation. Expected '{classtype}', but got '{annotation}'."
549
- )
550
-
551
547
  # Handle private method name mangling
552
548
  if name.startswith("__") and not name.endswith("__"):
553
549
  class_name = self.getClassName()
554
550
  name = f"_{class_name}{name}"
555
551
 
556
- # Check if the method already exists
557
- if hasattr(self._instance, name):
558
- raise ReflectionAttributeError(f"Attribute '{name}' already exists on '{self.getClassName()}'.")
559
-
560
552
  # Set the method on the instance
561
- setattr(self._instance.__class__, name, method)
553
+ setattr(self._instance, name, method)
562
554
 
563
555
  # Return True
564
556
  return True
@@ -17,6 +17,7 @@ from orionis.foundation.config.testing.entities.testing import Testing
17
17
  from orionis.foundation.config.testing.enums.drivers import PersistentDrivers
18
18
  from orionis.foundation.config.testing.enums.mode import ExecutionMode
19
19
  from orionis.foundation.contracts.application import IApplication
20
+ from orionis.services.introspection.concretes.reflection import ReflectionConcrete
20
21
  from orionis.services.introspection.instances.reflection import ReflectionInstance
21
22
  from orionis.support.performance.contracts.counter import IPerformanceCounter
22
23
  from orionis.test.contracts.test_result import IOrionisTestResult
@@ -27,21 +28,12 @@ from orionis.test.exceptions import OrionisTestValueError, OrionisTestFailureExc
27
28
  from orionis.test.output.printer import TestPrinter
28
29
  from orionis.test.records.logs import TestLogs
29
30
  from orionis.test.validators import (
30
- ValidBasePath,
31
- ValidExecutionMode,
32
- ValidFailFast,
33
- ValidFolderPath,
34
- ValidModuleName,
35
- ValidNamePattern,
36
- ValidPattern,
37
- ValidPersistentDriver,
38
- ValidPersistent,
39
- ValidThrowException,
40
- ValidVerbosity,
41
- ValidWebReport,
42
- ValidWorkers,
31
+ ValidBasePath, ValidExecutionMode, ValidFailFast, ValidFolderPath,
32
+ ValidModuleName, ValidNamePattern, ValidPattern, ValidPersistentDriver,
33
+ ValidPersistent, ValidThrowException, ValidVerbosity, ValidWebReport, ValidWorkers,
43
34
  )
44
35
  from orionis.test.view.render import TestingResultRender
36
+ import asyncio
45
37
 
46
38
  class UnitTest(IUnitTest):
47
39
  """
@@ -521,72 +513,6 @@ class UnitTest(IUnitTest):
521
513
  "Please ensure the test case is correctly defined and contains valid test methods."
522
514
  )
523
515
 
524
- def __isDecoratedMethod(
525
- self,
526
- test_case: unittest.TestCase
527
- ) -> bool:
528
- """
529
- Determines whether the test method of a given test case is decorated (i.e., wrapped by one or more Python decorators).
530
-
531
- This method inspects the test method associated with the provided `unittest.TestCase` instance to detect the presence of decorators.
532
- It traverses the decorator chain by following the `__wrapped__` attribute, which is set by Python's `functools.wraps` or similar mechanisms.
533
- Decorators are identified by the existence of the `__wrapped__` attribute, and their names are collected from the `__qualname__` or `__name__` attributes.
534
-
535
- Parameters
536
- ----------
537
- test_case : unittest.TestCase
538
- The test case instance whose test method will be checked for decorators.
539
-
540
- Returns
541
- -------
542
- bool
543
- True if the test method has one or more decorators applied (i.e., if any decorators are found in the chain).
544
- False if the test method is not decorated or if no test method is found.
545
-
546
- Notes
547
- -----
548
- - The method checks for decorators by traversing the `__wrapped__` attribute chain.
549
- - Decorator names are collected for informational purposes but are not returned.
550
- - If the test method is not decorated, or if no test method is found, the method returns False.
551
- - This method does not modify the test case or its method; it only inspects for decoration.
552
- """
553
-
554
- # Retrieve the test method from the test case's class using the test method name
555
- test_method = getattr(test_case.__class__, getattr(test_case, "_testMethodName"), None)
556
-
557
- # List to store decorator names found during traversal
558
- decorators = []
559
-
560
- # Check if the method has the __wrapped__ attribute, indicating it is decorated
561
- if hasattr(test_method, '__wrapped__'):
562
-
563
- # Start with the outermost decorated method
564
- original = test_method
565
-
566
- # Traverse the decorator chain by following __wrapped__ attributes
567
- while hasattr(original, '__wrapped__'):
568
-
569
- # Collect decorator name information for tracking purposes
570
- if hasattr(original, '__qualname__'):
571
-
572
- # Prefer __qualname__ for detailed naming information
573
- decorators.append(original.__qualname__)
574
-
575
- elif hasattr(original, '__name__'):
576
-
577
- # Fall back to __name__ if __qualname__ is not available
578
- decorators.append(original.__name__)
579
-
580
- # Move to the next level in the decorator chain
581
- original = original.__wrapped__
582
-
583
- # Return True if any decorators were found during the traversal
584
- if decorators:
585
- return True
586
-
587
- # Return False if no decorators are found or if the method is not decorated
588
- return False
589
-
590
516
  def __loadTests(
591
517
  self
592
518
  ) -> None:
@@ -667,10 +593,7 @@ class UnitTest(IUnitTest):
667
593
 
668
594
  # Categorize and resolve test dependencies efficiently
669
595
  target_list = debug_tests if self.__withDebugger(test) else normal_tests
670
- resolved_test = test
671
- if not self.__isDecoratedMethod(test):
672
- resolved_test = self.__resolveTestDependencies(test)
673
- target_list.append(resolved_test)
596
+ target_list.append(self.__resolveTestDependencies(test))
674
597
 
675
598
  # If no tests are found, raise an error
676
599
  if not flat_tests:
@@ -943,10 +866,10 @@ class UnitTest(IUnitTest):
943
866
  """
944
867
  Inject dependencies into a single test case if required, returning a TestSuite containing the resolved test case.
945
868
 
946
- This method uses reflection to inspect the test method's dependencies. If all dependencies are resolved,
947
- it injects them using the application's resolver. If there are unresolved dependencies, the original test case
948
- is returned as-is. Decorated methods and failed imports are also returned without modification. The returned
949
- TestSuite contains the test case with dependencies injected if applicable.
869
+ This method uses reflection to inspect the test method for dependency requirements. If dependencies are resolved,
870
+ it injects them into the test method. Supports both synchronous and asynchronous test methods: async methods are
871
+ wrapped to run in an event loop. If dependencies cannot be resolved, the original test case is returned as-is
872
+ within a TestSuite.
950
873
 
951
874
  Parameters
952
875
  ----------
@@ -956,7 +879,7 @@ class UnitTest(IUnitTest):
956
879
  Returns
957
880
  -------
958
881
  unittest.TestSuite
959
- A TestSuite containing the test case with dependencies injected if required.
882
+ A TestSuite containing the test case with injected dependencies if resolution is successful.
960
883
  If dependency injection is not possible or fails, the original test case is returned as-is within the suite.
961
884
 
962
885
  Raises
@@ -966,10 +889,10 @@ class UnitTest(IUnitTest):
966
889
 
967
890
  Notes
968
891
  -----
969
- - Uses reflection to determine method dependencies.
892
+ - Uses ReflectionInstance to determine method dependencies.
970
893
  - If dependencies are resolved, injects them into the test method.
894
+ - Supports async test methods by running them in an event loop.
971
895
  - If dependencies are unresolved or an error occurs, the original test case is returned.
972
- - The returned value is always a unittest.TestSuite containing the test case (with or without injected dependencies).
973
896
  """
974
897
 
975
898
  # Create a new TestSuite to hold the resolved test case
@@ -977,46 +900,68 @@ class UnitTest(IUnitTest):
977
900
 
978
901
  try:
979
902
 
980
- # Get the reflection instance for the test case
903
+ # Use reflection to inspect the test case for dependency requirements
981
904
  rf_instance = ReflectionInstance(test_case)
982
-
983
- # Get the test method name
984
- method_name = getattr(test_case, "_testMethodName", None)
985
-
986
- # Get method dependencies (resolved and unresolved)
905
+ method_name = rf_instance.getAttribute("_testMethodName", None)
987
906
  dependencies = rf_instance.getMethodDependencies(method_name)
988
907
 
989
- # If there are unresolved dependencies, return the original test case as-is
908
+ # If there are unresolved dependencies, return the original test case
990
909
  if dependencies.unresolved:
991
910
  return test_case
992
911
 
993
- # If there are resolved dependencies, inject them into the test method
912
+ # If dependencies are resolved, inject them into the test method
994
913
  if dependencies.resolved:
995
914
 
996
- # Get the test class and original method
997
- test_class = rf_instance.getClass()
998
- original_method = getattr(test_class, method_name)
915
+ # Get the test case class
916
+ test_cls = rf_instance.getClass()
917
+
918
+ # Create a ReflectionConcrete instance for the test case class
919
+ rf_concrete = ReflectionConcrete(test_cls)
920
+
921
+ # Get the original test method
922
+ original_method = rf_concrete.getAttribute(method_name)
923
+
924
+ # Resolve the actual arguments to inject
925
+ resolved_args = self.__app.resolveDependencyArguments(
926
+ rf_instance.getClassName(),
927
+ dependencies
928
+ )
929
+
930
+ # If the test method is asynchronous, wrap it to run in an event loop
931
+ if asyncio.iscoroutinefunction(original_method):
932
+
933
+ # Define an async wrapper to inject dependencies
934
+ async def async_wrapper(self_instance):
935
+ return await original_method(self_instance, **resolved_args)
936
+
937
+ # Wrap with a sync function for unittest compatibility
938
+ def sync_wrapper(self_instance):
939
+ return asyncio.run(async_wrapper(self_instance))
940
+
941
+ # Bind the wrapped method to the test case instance
942
+ bound_method = sync_wrapper.__get__(test_case, test_cls)
943
+
944
+ else:
999
945
 
1000
- # Resolve dependencies using the application container
1001
- resolved_args = self.__app.resolveDependencyArguments(rf_instance.getClassName(), dependencies)
946
+ # For synchronous methods, inject dependencies directly
947
+ def wrapper(self_instance):
948
+ return original_method(self_instance, **resolved_args)
1002
949
 
1003
- # Define a wrapper function to inject dependencies
1004
- def wrapper(self_instance):
1005
- return original_method(self_instance, **resolved_args)
950
+ # Bind the wrapped method to the test case instance
951
+ bound_method = wrapper.__get__(test_case, test_cls)
1006
952
 
1007
- # Bind the wrapped method to the test case instance
1008
- bound_method = wrapper.__get__(test_case, test_case.__class__)
1009
- setattr(test_case, method_name, bound_method)
953
+ # Replace the test method with the dependency-injected version
954
+ rf_instance.setMethod(method_name, bound_method)
1010
955
 
1011
- # Add the test case to the suite (with injected dependencies if applicable)
1012
- suite.addTest(test_case)
956
+ # Add the (possibly resolved) test case to the suite
957
+ suite.addTest(rf_instance.getInstance())
1013
958
 
1014
- # Return the TestSuite containing the resolved test case
959
+ # Return the suite containing the resolved test case
1015
960
  return suite
1016
961
 
1017
962
  except Exception:
1018
963
 
1019
- # On any error, return the original test case without injection
964
+ # On error, return the original test case
1020
965
  return test_case
1021
966
 
1022
967
  def __runTestsSequentially(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orionis
3
- Version: 0.606.0
3
+ Version: 0.608.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
@@ -217,7 +217,7 @@ orionis/foundation/providers/scheduler_provider.py,sha256=irwkjMiq-HpsbJxAOnhjji
217
217
  orionis/foundation/providers/testing_provider.py,sha256=2akFnabtH_cV_7z_2cCL7u8cPCGvCJAmlhMcnlCrc4c,3742
218
218
  orionis/foundation/providers/workers_provider.py,sha256=P_YtJuPNrdJAQJkAqI11KI0c6GSB9NqIuuCKpRytE0g,3937
219
219
  orionis/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
220
- orionis/metadata/framework.py,sha256=odWSJSUt5IWkgay1iLh-7SeBkjLj7pKW8VDc-bGBjz8,4109
220
+ orionis/metadata/framework.py,sha256=mHrtbv7UZURpFJdeEpp8Dnaje-qCMCpwZDVEfXFE0Fc,4109
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
@@ -267,7 +267,7 @@ orionis/services/introspection/callables/reflection.py,sha256=zzxrjExc2iIlfs3xfo
267
267
  orionis/services/introspection/callables/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
268
268
  orionis/services/introspection/callables/contracts/reflection.py,sha256=EZi9VfTf5GJBnMd47j_oJ8dENQ5-HzDbQ-4zSffrvpM,5523
269
269
  orionis/services/introspection/concretes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
270
- orionis/services/introspection/concretes/reflection.py,sha256=ZOScKOATUNA-gOJIG_8Z2Q5XXI2kAmDRCg8fg2SFklg,55872
270
+ orionis/services/introspection/concretes/reflection.py,sha256=vKgkDfIbuRYH4iTcHaYoHIAMalZfGjmJ_tYTG7mhsbQ,56823
271
271
  orionis/services/introspection/concretes/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
272
272
  orionis/services/introspection/concretes/contracts/reflection.py,sha256=LwEAgdN_WLCfS9b8pnFRVfN0PTRK4Br9qngu5km5aIk,24955
273
273
  orionis/services/introspection/dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -280,7 +280,7 @@ orionis/services/introspection/dependencies/entities/resolve_argument.py,sha256=
280
280
  orionis/services/introspection/exceptions/__init__.py,sha256=uVRbnndapr9veJps8EzFJeLItxnMEbjUDdPBy3dQbeM,221
281
281
  orionis/services/introspection/exceptions/introspection.py,sha256=Qd021psWiXyY9HQVNWIBVZ3KNfHGSgq8NL4btUTR8tg,2532
282
282
  orionis/services/introspection/instances/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
283
- orionis/services/introspection/instances/reflection.py,sha256=vn43FdZNP-tkIbKvX0TdptGRQZ1FntZ49xDJ_VAM4jM,54937
283
+ orionis/services/introspection/instances/reflection.py,sha256=WTkHHST8DIjKV_-DygzOsx2IA7yL5aqkr0Zn6EWm2Xo,54809
284
284
  orionis/services/introspection/instances/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
285
285
  orionis/services/introspection/instances/contracts/reflection.py,sha256=OBZ7vI6KsII76oqIF63v1I-msh94_xGfhPZQvqAVLgY,20834
286
286
  orionis/services/introspection/modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -371,7 +371,7 @@ orionis/test/contracts/render.py,sha256=wpDQzUtT0r8KFZ7zPcxWHXQ1EVNKxzA_rZ6ZKUcZ
371
371
  orionis/test/contracts/test_result.py,sha256=SNXJ2UerkweYn7uCT0i0HmMGP0XBrL_9KJs-0ZvIYU4,4002
372
372
  orionis/test/contracts/unit_test.py,sha256=EyidHoOPJItwgkBWGYY1TymbNklyn2EUXnghVvW4htc,4652
373
373
  orionis/test/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
374
- orionis/test/core/unit_test.py,sha256=3fj_u1fJHhnitfLfcAL3-KeEc_Zt-mQNX9Np4sPxrbY,72952
374
+ orionis/test/core/unit_test.py,sha256=_-Q50AsPNy8NYrlHn2JyKQNU3ohWG2BFZnfh_k5AdEI,70695
375
375
  orionis/test/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
376
376
  orionis/test/entities/result.py,sha256=eZ6UIqGmFW8FZ9x8PB_MZbLAc-SAuUyi4FUcMYIZzGo,4777
377
377
  orionis/test/enums/__init__.py,sha256=M3imAgMvKFTKg55FbtVoY3zxj7QRY9AfaUWxiSZVvn4,66
@@ -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.606.0.dist-info/licenses/LICENCE,sha256=JhC-z_9mbpUrCfPjcl3DhDA8trNDMzb57cvRSam1avc,1463
408
- orionis-0.606.0.dist-info/METADATA,sha256=wfgtPHMn36qRmNCqbl8zfkH5oUX3kvWnALfHtyEsRe4,4801
409
- orionis-0.606.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
410
- orionis-0.606.0.dist-info/top_level.txt,sha256=lyXi6jArpqJ-0zzNqd_uwsH-z9TCEBVBL-pC3Ekv7hU,8
411
- orionis-0.606.0.dist-info/RECORD,,
407
+ orionis-0.608.0.dist-info/licenses/LICENCE,sha256=JhC-z_9mbpUrCfPjcl3DhDA8trNDMzb57cvRSam1avc,1463
408
+ orionis-0.608.0.dist-info/METADATA,sha256=Dg4sMgNBKxL6QBvK42DbwGmwHAOJrViOuWZPnPYtLtM,4801
409
+ orionis-0.608.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
410
+ orionis-0.608.0.dist-info/top_level.txt,sha256=lyXi6jArpqJ-0zzNqd_uwsH-z9TCEBVBL-pC3Ekv7hU,8
411
+ orionis-0.608.0.dist-info/RECORD,,