orionis 0.245.0__py3-none-any.whl → 0.247.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.
Files changed (108) hide show
  1. orionis/framework.py +1 -1
  2. orionis/luminate/config/app/__init__.py +10 -0
  3. orionis/luminate/config/app/entities/app.py +205 -0
  4. orionis/luminate/config/app/enums/ciphers.py +34 -0
  5. orionis/luminate/config/app/enums/environments.py +15 -0
  6. orionis/luminate/config/auth/__init__.py +7 -0
  7. orionis/luminate/config/auth/entities/auth.py +11 -0
  8. orionis/luminate/config/cache/__init__.py +9 -0
  9. orionis/luminate/config/cache/entities/cache.py +58 -0
  10. orionis/luminate/config/cache/entities/file.py +29 -0
  11. orionis/luminate/config/cache/entities/stores.py +35 -0
  12. orionis/luminate/config/cache/enums/drivers.py +12 -0
  13. orionis/luminate/config/contracts/config.py +27 -0
  14. orionis/luminate/config/entities/testing.py +215 -0
  15. orionis/luminate/config/exceptions/integrity_exception.py +30 -0
  16. orionis/luminate/console/dumper/dump_die.py +418 -0
  17. orionis/luminate/contracts/facades/commands/scheduler_facade.py +1 -1
  18. orionis/luminate/facades/files/path_facade.py +1 -1
  19. orionis/luminate/patterns/__init__.py +4 -0
  20. orionis/luminate/patterns/singleton/__init__.py +10 -0
  21. orionis/luminate/patterns/singleton/meta_class.py +56 -0
  22. orionis/luminate/providers/commands/reactor_commands_service_provider.py +3 -3
  23. orionis/luminate/providers/commands/scheduler_provider.py +1 -1
  24. orionis/luminate/providers/config/config_service_provider.py +1 -1
  25. orionis/luminate/providers/environment/environment__service_provider.py +2 -2
  26. orionis/luminate/providers/files/paths_provider.py +1 -1
  27. orionis/luminate/providers/log/log_service_provider.py +2 -2
  28. orionis/luminate/services/environment/__init__.py +10 -0
  29. orionis/luminate/services/environment/contracts/__init__.py +5 -0
  30. orionis/luminate/services/environment/contracts/env.py +93 -0
  31. orionis/luminate/services/environment/dot_env.py +293 -0
  32. orionis/luminate/services/environment/env.py +77 -0
  33. orionis/luminate/services/paths/__init__.py +9 -0
  34. orionis/luminate/services/paths/contracts/__init__.py +0 -0
  35. orionis/luminate/services/paths/contracts/resolver.py +67 -0
  36. orionis/luminate/services/paths/resolver.py +83 -0
  37. orionis/luminate/services/workers/__init__.py +10 -0
  38. orionis/luminate/services/workers/maximum_workers.py +36 -0
  39. orionis/luminate/services_/__init__.py +0 -0
  40. orionis/luminate/services_/commands/__init__.py +0 -0
  41. orionis/luminate/services_/config/__init__.py +0 -0
  42. orionis/luminate/services_/log/__init__.py +0 -0
  43. orionis/luminate/support/introspection/abstracts/entities/__init__.py +0 -0
  44. orionis/luminate/support/introspection/abstracts/entities/abstract_class_attributes.py +11 -0
  45. orionis/luminate/support/introspection/abstracts/reflect_abstract.py +154 -16
  46. orionis/luminate/support/introspection/instances/reflection_instance.py +2 -2
  47. orionis/luminate/test/__init__.py +11 -1
  48. orionis/luminate/test/cases/test_async.py +1 -10
  49. orionis/luminate/test/cases/test_case.py +8 -3
  50. orionis/luminate/test/cases/test_sync.py +1 -0
  51. orionis/luminate/test/core/contracts/test_suite.py +19 -31
  52. orionis/luminate/test/core/contracts/test_unit.py +103 -59
  53. orionis/luminate/test/core/test_suite.py +50 -42
  54. orionis/luminate/test/core/test_unit.py +756 -196
  55. orionis/luminate/test/entities/test_result.py +19 -18
  56. orionis/luminate/test/enums/test_mode.py +16 -0
  57. orionis/luminate/test/exceptions/test_config_exception.py +28 -0
  58. orionis/luminate/test/exceptions/test_exception.py +41 -34
  59. orionis/luminate/test/output/contracts/test_std_out.py +22 -11
  60. orionis/luminate/test/output/test_std_out.py +79 -48
  61. {orionis-0.245.0.dist-info → orionis-0.247.0.dist-info}/METADATA +4 -1
  62. {orionis-0.245.0.dist-info → orionis-0.247.0.dist-info}/RECORD +98 -61
  63. tests/config/__init__.py +0 -0
  64. tests/config/test_app.py +122 -0
  65. tests/config/test_auth.py +21 -0
  66. tests/config/test_cache.py +20 -0
  67. tests/patterns/__init__.py +0 -0
  68. tests/patterns/singleton/__init__.py +0 -0
  69. tests/patterns/singleton/test_singleton.py +18 -0
  70. tests/services/__init__.py +0 -0
  71. tests/services/environment/__init__.py +0 -0
  72. tests/services/environment/test_env.py +33 -0
  73. tests/support/inspection/fakes/fake_reflect_abstract.py +61 -5
  74. tests/support/inspection/test_reflect_abstract.py +62 -1
  75. tests/support/inspection/test_reflect_instance.py +0 -1
  76. orionis/luminate/config/app.py +0 -47
  77. orionis/luminate/config/auth.py +0 -15
  78. orionis/luminate/config/cache.py +0 -51
  79. orionis/luminate/support/environment/contracts/env.py +0 -68
  80. orionis/luminate/support/environment/env.py +0 -138
  81. orionis/luminate/support/environment/functions.py +0 -49
  82. orionis/luminate/support/environment/helper.py +0 -26
  83. orionis/luminate/support/patterns/singleton.py +0 -44
  84. tests/support/environment/test_env.py +0 -91
  85. tests/support/patterns/test_singleton.py +0 -18
  86. /orionis/luminate/{services/commands → config/app/entities}/__init__.py +0 -0
  87. /orionis/luminate/{services/config → config/app/enums}/__init__.py +0 -0
  88. /orionis/luminate/{services/log → config/auth/entities}/__init__.py +0 -0
  89. /orionis/luminate/{support/environment → config/cache/entities}/__init__.py +0 -0
  90. /orionis/luminate/{support/environment/contracts → config/cache/enums}/__init__.py +0 -0
  91. /orionis/luminate/{support/patterns → config/contracts}/__init__.py +0 -0
  92. /orionis/luminate/config/{cors.py → entities/cors.py} +0 -0
  93. /orionis/luminate/config/{database.py → entities/database.py} +0 -0
  94. /orionis/luminate/config/{filesystems.py → entities/filesystems.py} +0 -0
  95. /orionis/luminate/config/{logging.py → entities/logging.py} +0 -0
  96. /orionis/luminate/config/{mail.py → entities/mail.py} +0 -0
  97. /orionis/luminate/config/{queue.py → entities/queue.py} +0 -0
  98. /orionis/luminate/config/{session.py → entities/session.py} +0 -0
  99. {tests/support/environment → orionis/luminate/config/exceptions}/__init__.py +0 -0
  100. {tests/support/patterns → orionis/luminate/console/dumper}/__init__.py +0 -0
  101. /orionis/luminate/{services → services_}/commands/reactor_commands_service.py +0 -0
  102. /orionis/luminate/{services → services_}/commands/scheduler_service.py +0 -0
  103. /orionis/luminate/{services → services_}/config/config_service.py +0 -0
  104. /orionis/luminate/{services → services_}/log/log_service.py +0 -0
  105. {orionis-0.245.0.dist-info → orionis-0.247.0.dist-info}/LICENCE +0 -0
  106. {orionis-0.245.0.dist-info → orionis-0.247.0.dist-info}/WHEEL +0 -0
  107. {orionis-0.245.0.dist-info → orionis-0.247.0.dist-info}/entry_points.txt +0 -0
  108. {orionis-0.245.0.dist-info → orionis-0.247.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,67 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Optional
3
+
4
+ class IResolver(ABC):
5
+ """
6
+ Interface for a utility class that resolves file and directory paths relative to a base path.
7
+ """
8
+
9
+ @abstractmethod
10
+ def __init__(self, root_path: Optional[str] = None):
11
+ """
12
+ Initializes the resolver with an optional root path.
13
+
14
+ Parameters
15
+ ----------
16
+ root_path : str, optional
17
+ The root directory to resolve relative paths from.
18
+ """
19
+ pass
20
+
21
+ @abstractmethod
22
+ def relativePath(self, relative_path: str):
23
+ """
24
+ Resolves a relative path into an absolute one and validates its existence.
25
+
26
+ Parameters
27
+ ----------
28
+ relative_path : str
29
+ The relative path to resolve.
30
+
31
+ Returns
32
+ -------
33
+ ResolverInterface
34
+ The instance itself for method chaining.
35
+
36
+ Raises
37
+ ------
38
+ FileNotFoundError
39
+ If the resolved path does not exist.
40
+ ValueError
41
+ If the resolved path is neither a file nor a directory.
42
+ """
43
+ pass
44
+
45
+ @abstractmethod
46
+ def toString(self) -> str:
47
+ """
48
+ Returns the resolved path as a string.
49
+
50
+ Returns
51
+ -------
52
+ str
53
+ The resolved path.
54
+ """
55
+ pass
56
+
57
+ @abstractmethod
58
+ def __str__(self) -> str:
59
+ """
60
+ Returns the resolved path as a string (for print or str()).
61
+
62
+ Returns
63
+ -------
64
+ str
65
+ The resolved path.
66
+ """
67
+ pass
@@ -0,0 +1,83 @@
1
+ import os
2
+ from pathlib import Path
3
+ from orionis.luminate.support.paths.contracts.resolver import IResolver
4
+
5
+ class Resolver(IResolver):
6
+ """
7
+ A utility class for resolving file and directory paths relative to the project's root directory.
8
+ """
9
+
10
+ def __init__(self, root_path: str = None):
11
+ """
12
+ Initializes the Resolver instance with the project's root directory.
13
+
14
+ Parameters
15
+ ----------
16
+ root_path : str, optional
17
+ The root directory of the project. If not provided, it defaults to the current working directory.
18
+ """
19
+ self.base_path = Path(root_path).resolve() if root_path else Path(os.getcwd()).resolve()
20
+ self.resolved_path = None
21
+
22
+ def relativePath(self, relative_path: str) -> 'Resolver':
23
+ """
24
+ Resolves a given relative path to an absolute path and validates its existence.
25
+
26
+ This method combines the project's root directory with the provided relative path,
27
+ resolves it to an absolute path, and ensures it exists as either a directory or a file.
28
+
29
+ Parameters
30
+ ----------
31
+ relative_path : str
32
+ The relative path to a directory or file to be resolved.
33
+
34
+ Returns
35
+ -------
36
+ Resolver
37
+ The current instance of the Resolver class with the resolved path.
38
+
39
+ Raises
40
+ ------
41
+ FileNotFoundError
42
+ If the resolved path does not exist.
43
+ ValueError
44
+ If the resolved path is neither a valid directory nor a file.
45
+ """
46
+ # Combine the base path with the relative path and resolve it
47
+ resolved_path = (self.base_path / relative_path).resolve()
48
+
49
+ # Validate that the path exists
50
+ if not resolved_path.exists():
51
+ raise FileNotFoundError(f"The requested path does not exist: {resolved_path}")
52
+
53
+ # Validate that the path is either a directory or a file
54
+ if not (resolved_path.is_dir() or resolved_path.is_file()):
55
+ raise ValueError(f"The requested path is neither a valid directory nor a file: {resolved_path}")
56
+
57
+ # Store the resolved path in the instance variable
58
+ self.resolved_path = resolved_path
59
+
60
+ # Return the current instance
61
+ return self
62
+
63
+ def toString(self) -> str:
64
+ """
65
+ Returns the string representation of the resolved path.
66
+
67
+ Returns
68
+ -------
69
+ str
70
+ The resolved path as a string.
71
+ """
72
+ return str(self.resolved_path)
73
+
74
+ def __str__(self) -> str:
75
+ """
76
+ Returns the string representation of the resolved path.
77
+
78
+ Returns
79
+ -------
80
+ str
81
+ The resolved path as a string.
82
+ """
83
+ return str(self.resolved_path)
@@ -0,0 +1,10 @@
1
+ from orionis.luminate.services.workers.maximum_workers import MaximumWorkers
2
+
3
+ __all__ = [
4
+ "MaximumWorkers",
5
+ ]
6
+ __author__ = "Raúl Mauricio Uñate Castro"
7
+ __description__ = (
8
+ "This module provides a class to calculate the maximum number of workers "
9
+ "that can be run on a machine based on its CPU and memory resources. "
10
+ )
@@ -0,0 +1,36 @@
1
+ import multiprocessing
2
+ import math
3
+ import psutil
4
+
5
+ class MaximumWorkers:
6
+ """
7
+ Calculates the optimal number of workers a machine can handle based on CPU and memory resources.
8
+
9
+ This class estimates the maximum number of Uvicorn (or similar) workers by considering:
10
+ - The number of available CPU cores.
11
+ - The total system memory (RAM).
12
+ - The estimated memory usage per worker (configurable).
13
+
14
+ Parameters
15
+ ----------
16
+ ram_per_worker : float, optional
17
+ Estimated amount of RAM (in GB) that each worker will consume. Default is 0.5 GB.
18
+ """
19
+
20
+ def __init__(self, ram_per_worker: float = 0.5):
21
+ self._cpu_count = multiprocessing.cpu_count()
22
+ self._ram_total_gb = psutil.virtual_memory().total / (1024 ** 3)
23
+ self._ram_per_worker = ram_per_worker
24
+
25
+ def calculate(self) -> int:
26
+ """
27
+ Computes the maximum number of workers supported by the current machine.
28
+
29
+ Returns
30
+ -------
31
+ int
32
+ The recommended number of worker processes based on CPU and memory limits.
33
+ """
34
+ max_workers_by_cpu = self._cpu_count
35
+ max_workers_by_ram = math.floor(self._ram_total_gb / self._ram_per_worker)
36
+ return min(max_workers_by_cpu, max_workers_by_ram)
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,11 @@
1
+ from dataclasses import dataclass
2
+ from typing import Any, Dict
3
+
4
+ @dataclass(frozen=True, kw_only=True)
5
+ class AbstractClassAttributes:
6
+ """
7
+ A class to represent the attributes of an entity.
8
+ """
9
+ public: Dict[str, Any]
10
+ private: Dict[str, Any]
11
+ protected: Dict[str, Any]
@@ -3,11 +3,11 @@ import ast
3
3
  import inspect
4
4
  import types
5
5
  from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type, TypeVar
6
- from orionis.luminate.support.introspection.contracts.reflexion_abstract import IReflexionAbstract
6
+ from orionis.luminate.support.introspection.abstracts.entities.abstract_class_attributes import AbstractClassAttributes
7
7
 
8
8
  ABC = TypeVar('ABC', bound=abc.ABC)
9
9
 
10
- class ReflexionAbstract(IReflexionAbstract):
10
+ class ReflexionAbstract:
11
11
  """A reflection object encapsulating an abstract class.
12
12
 
13
13
  Parameters
@@ -64,7 +64,7 @@ class ReflexionAbstract(IReflexionAbstract):
64
64
  """
65
65
  return self._abstract.__module__
66
66
 
67
- def getAllAttributes(self) -> Dict[str, Any]:
67
+ def getAllAttributes(self) -> AbstractClassAttributes:
68
68
  """
69
69
  Get all attributes of the abstract class.
70
70
 
@@ -93,11 +93,161 @@ class ReflexionAbstract(IReflexionAbstract):
93
93
  else:
94
94
  public[attr] = value
95
95
 
96
- return {"public": public, "protected": protected, "private": private}
96
+ return AbstractClassAttributes(
97
+ public=public,
98
+ private=private,
99
+ protected=protected
100
+ )
97
101
 
102
+ def getAttributes(self) -> Dict[str, Any]:
103
+ """
104
+ Get all attributes of the instance.
98
105
 
106
+ Returns
107
+ -------
108
+ Dict[str, Any]
109
+ Dictionary of attribute names and their values
110
+ """
111
+ attr = self.getAllAttributes()
112
+ return {**attr.public, **attr.private, **attr.protected}
99
113
 
114
+ def getPublicAttributes(self) -> Dict[str, Any]:
115
+ """
116
+ Get all public attributes of the instance.
100
117
 
118
+ Returns
119
+ -------
120
+ Dict[str, Any]
121
+ Dictionary of public attribute names and their values
122
+ """
123
+ attr = self.getAllAttributes()
124
+ return attr.public
125
+
126
+ def getPrivateAttributes(self) -> Dict[str, Any]:
127
+ """
128
+ Get all private attributes of the instance.
129
+
130
+ Returns
131
+ -------
132
+ Dict[str, Any]
133
+ Dictionary of private attribute names and their values
134
+ """
135
+ attr = self.getAllAttributes()
136
+ return attr.private
137
+
138
+ def getProtectedAttributes(self) -> Dict[str, Any]:
139
+ """
140
+ Get all Protected attributes of the instance.
141
+
142
+ Returns
143
+ -------
144
+ Dict[str, Any]
145
+ Dictionary of Protected attribute names and their values
146
+ """
147
+ attr = self.getAllAttributes()
148
+ return attr.protected
149
+
150
+ def getAllMethods(self) -> Dict[str, List[str]]:
151
+ """
152
+ Categorize all methods and relevant members of the abstract class into public, private, protected,
153
+ static, asynchronous, synchronous, class methods, magic methods, abstract methods, and properties.
154
+
155
+ Returns
156
+ -------
157
+ Dict[str, List[str]]
158
+ A dictionary categorizing methods and attributes into various types.
159
+ """
160
+ class_name = self.getClassName()
161
+ private_prefix = f"_{class_name}"
162
+ attributes = set(self.getAttributes().keys()) | {attr for attr in dir(self._abstract) if attr.startswith('_abc_')}
163
+
164
+ result = {
165
+ "public": [],
166
+ "private": [],
167
+ "protected": [],
168
+ "static": [],
169
+ "asynchronous": [],
170
+ "synchronous": [],
171
+ "class_methods": [],
172
+ "asynchronous_static": [],
173
+ "synchronous_static": [],
174
+ "magic": [],
175
+ "abstract": [],
176
+ "abstract_class_methods": [],
177
+ "abstract_static_methods": []
178
+ }
179
+
180
+ # Precompute all members once
181
+ members = inspect.getmembers(self._abstract)
182
+ static_attrs = {}
183
+
184
+ # First pass to collect all relevant information
185
+ for name, attr in members:
186
+ if name in attributes:
187
+ continue
188
+
189
+ # Get static attribute once
190
+ static_attr = inspect.getattr_static(self._abstract, name)
191
+ static_attrs[name] = static_attr
192
+
193
+ # Magic methods
194
+ if name.startswith("__") and name.endswith("__"):
195
+ result["magic"].append(name)
196
+ continue
197
+
198
+ # Static and class methods
199
+ if isinstance(static_attr, staticmethod):
200
+ result["static"].append(name)
201
+ elif isinstance(static_attr, classmethod):
202
+ result["class_methods"].append(name)
203
+
204
+ # Private, protected, public
205
+ if name.startswith(private_prefix):
206
+ clean_name = name.replace(private_prefix, "")
207
+ result["private"].append(clean_name)
208
+ elif name.startswith("_"):
209
+ result["protected"].append(name)
210
+ else:
211
+ result["public"].append(name)
212
+
213
+ # Async methods
214
+ if inspect.iscoroutinefunction(attr):
215
+ clean_name = name.replace(private_prefix, "")
216
+ if name in result["static"]:
217
+ result["asynchronous_static"].append(clean_name)
218
+ else:
219
+ result["asynchronous"].append(clean_name)
220
+
221
+ # Second pass for synchronous methods (needs info from first pass)
222
+ for name, attr in members:
223
+ if name in attributes or name in result["magic"] or name in result["class_methods"] or name in result["static"]:
224
+ continue
225
+
226
+ if inspect.isfunction(attr):
227
+ clean_name = name.replace(private_prefix, "")
228
+ if clean_name not in result["asynchronous"]:
229
+ result["synchronous"].append(clean_name)
230
+
231
+ # Synchronous static methods
232
+ for name in result["static"]:
233
+ if name not in attributes and name not in result["asynchronous_static"] and name not in result["class_methods"]:
234
+ result["synchronous_static"].append(name)
235
+
236
+ # Abstract methods
237
+ abstract_methods = getattr(self._abstract, "__abstractmethods__", set())
238
+ for name in abstract_methods:
239
+ if name in attributes:
240
+ continue
241
+
242
+ static_attr = static_attrs.get(name, inspect.getattr_static(self._abstract, name))
243
+ if isinstance(static_attr, staticmethod):
244
+ result["abstract_static_methods"].append(name)
245
+ elif isinstance(static_attr, classmethod):
246
+ result["abstract_class_methods"].append(name)
247
+ elif not isinstance(static_attr, property):
248
+ result["abstract"].append(name)
249
+
250
+ return result
101
251
 
102
252
 
103
253
 
@@ -109,19 +259,7 @@ class ReflexionAbstract(IReflexionAbstract):
109
259
 
110
260
 
111
261
 
112
- def getAbstractMethods(self) -> Set[str]:
113
- """Get all abstract method names required by the class.
114
262
 
115
- Returns
116
- -------
117
- Set[str]
118
- Set of abstract method names
119
- """
120
- methods = []
121
- for method in self._abstract.__abstractmethods__:
122
- if not isinstance(getattr(self._abstract, method), property):
123
- methods.append(method)
124
- return set(methods)
125
263
 
126
264
  def getAbstractProperties(self) -> Set[str]:
127
265
  """Get all abstract property names required by the class.
@@ -171,8 +171,8 @@ class ReflectionInstance(IReflectionInstance):
171
171
  def getAllMethods(self):
172
172
  """
173
173
  Retrieves and categorizes all methods of the instance's class into various classifications.
174
- This method inspects the instance's class and its methods, categorizing them into public, private,
175
- protected, static, asynchronous, synchronous, class methods, asynchronous static, synchronous static,
174
+ This method inspects the instance's class and its methods, categorizing them into public, private,
175
+ protected, static, asynchronous, synchronous, class methods, asynchronous static, synchronous static,
176
176
  and magic methods.
177
177
  Returns
178
178
  -------
@@ -10,4 +10,14 @@ __all__ = [
10
10
  "AsyncTestCase",
11
11
  "TestCase",
12
12
  "SyncTestCase",
13
- ]
13
+ ]
14
+ __author__ = "Raúl Mauricio Uñate Castro"
15
+ __description__ = (
16
+ "Orionis Framework - Component Test Suites is a microframework "
17
+ "for creating unit and integration tests. "
18
+ "It allows you to write tests quickly and easily, "
19
+ "using a clear and concise syntax. "
20
+ "Supports both asynchronous and synchronous tests, "
21
+ "as well as the creation of test suites and parallel test execution. "
22
+ "It uses Python's native unittest module for test creation."
23
+ )
@@ -6,17 +6,8 @@ class AsyncTestCase(unittest.IsolatedAsyncioTestCase, TestStdOut):
6
6
  AsyncTestCase is a test case class designed for asynchronous unit testing.
7
7
  It inherits from `unittest.IsolatedAsyncioTestCase` to provide support for
8
8
  async test methods and `TestStdOut` for additional functionality.
9
- Methods
10
- -------
11
- asyncSetUp()
12
- Asynchronous setup method called before each test. It ensures that the
13
- parent class's asyncSetUp method is invoked to initialize any required
14
- resources.
15
- asyncTearDown()
16
- Asynchronous teardown method called after each test. It ensures that the
17
- parent class's asyncTearDown method is invoked to clean up any resources
18
- used during the test.
19
9
  """
10
+
20
11
  async def asyncSetUp(self):
21
12
  """
22
13
  Asynchronous setup method called before each test.
@@ -3,9 +3,14 @@ from orionis.luminate.test.output.test_std_out import TestStdOut
3
3
 
4
4
  class TestCase(unittest.IsolatedAsyncioTestCase, TestStdOut):
5
5
  """
6
- TestCase is a base class for unit tests that provides support for asynchronous
7
- testing using `unittest.IsolatedAsyncioTestCase` and additional functionality
8
- from `TestStdOut`."""
6
+ A base test case class for asynchronous unit tests.
7
+ Inherits from:
8
+ unittest.IsolatedAsyncioTestCase: Provides support for asynchronous test methods and setup/teardown.
9
+ TestStdOut: Mixin for capturing or testing standard output during tests.
10
+ This class defines asynchronous setup and teardown methods to ensure proper initialization and cleanup
11
+ of resources before and after each test case.
12
+ """
13
+
9
14
  async def asyncSetUp(self):
10
15
  """
11
16
  Asynchronous setup method called before each test.
@@ -7,4 +7,5 @@ class SyncTestCase(unittest.TestCase, TestStdOut):
7
7
  It inherits from `unittest.TestCase` to provide support for standard test methods
8
8
  and `TestStdOut` for additional functionality.
9
9
  """
10
+
10
11
  pass
@@ -1,42 +1,30 @@
1
1
  from abc import ABC, abstractmethod
2
+ from orionis.luminate.config.entities.testing import Testing
3
+ from orionis.luminate.test.core.test_unit import UnitTest
2
4
 
3
5
  class ITestSuite(ABC):
4
6
  """
5
- Provides utility methods to configure and execute unit tests from specified folders.
7
+ Interface for configuring and initializing a UnitTest suite using a provided Testing configuration.
8
+ Methods:
9
+ config(config: Testing) -> UnitTest:
6
10
  """
7
11
 
8
12
  @staticmethod
9
13
  @abstractmethod
10
- def load(
11
- base_path: str = 'tests',
12
- folder_path: list | str = '*',
13
- pattern: str = 'test_*.py'
14
- ):
14
+ def config(config:Testing) -> UnitTest:
15
15
  """
16
- Discover and initialize a test suite from the specified folder(s).
17
-
18
- This method scans the provided folder(s) for test files matching the given pattern
19
- and initializes a test suite with the discovered files.
20
-
21
- Parameters
22
- ----------
23
- base_path : str, optional
24
- The base path for the tests. Defaults to 'tests'.
25
- folder_path : str or list of str, optional
26
- Path(s) to the folder(s) containing test files. Use '*' to scan all folders
27
- under the base path. Defaults to '*'.
28
- pattern : str, optional
29
- File pattern to match test files. Defaults to 'test_*.py'.
30
-
31
- Returns
32
- -------
33
- UnitTestClass
34
- An initialized test suite containing the discovered test files.
35
-
36
- Raises
37
- ------
38
- TypeError
39
- If `base_path` is not a string, `folder_path` is not a string or list, or
40
- `pattern` is not a string.
16
+ Configures and initializes a UnitTest suite based on the provided Testing configuration.
17
+ Args:
18
+ config (Testing): An instance of the Testing class containing configuration options for the test suite.
19
+ Returns:
20
+ UnitTest: An initialized UnitTest suite configured according to the provided settings.
21
+ Raises:
22
+ OrionisTestConfigException: If the config parameter is not an instance of the Testing class.
23
+ The function performs the following steps:
24
+ - Validates the type of the config parameter.
25
+ - Initializes a UnitTest suite and applies configuration values from the Testing instance.
26
+ - Discovers folders containing test files based on the specified base path, folder path(s), and filename pattern.
27
+ - Adds discovered test folders to the UnitTest suite, applying optional test name patterns and tags.
28
+ - Returns the configured UnitTest suite ready for execution.
41
29
  """
42
30
  pass