orionis 0.405.0__py3-none-any.whl → 0.407.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 (175) hide show
  1. orionis/console/base/command.py +57 -50
  2. orionis/console/base/contracts/command.py +68 -0
  3. orionis/console/dynamic/contracts/progress_bar.py +3 -3
  4. orionis/console/dynamic/progress_bar.py +8 -8
  5. orionis/console/output/console.py +8 -2
  6. orionis/console/output/contracts/console.py +1 -1
  7. orionis/container/container.py +2 -2
  8. orionis/container/context/scope.py +4 -1
  9. orionis/container/contracts/service_provider.py +2 -2
  10. orionis/container/entities/binding.py +31 -44
  11. orionis/container/enums/lifetimes.py +22 -1
  12. orionis/container/facades/facade.py +1 -2
  13. orionis/container/providers/service_provider.py +2 -2
  14. orionis/foundation/application.py +542 -248
  15. orionis/foundation/config/app/entities/app.py +107 -90
  16. orionis/foundation/config/auth/entities/auth.py +4 -33
  17. orionis/foundation/config/cache/entities/cache.py +18 -41
  18. orionis/foundation/config/cache/entities/file.py +8 -35
  19. orionis/foundation/config/cache/entities/stores.py +17 -38
  20. orionis/foundation/config/cors/entities/cors.py +41 -54
  21. orionis/foundation/config/database/entities/connections.py +40 -56
  22. orionis/foundation/config/database/entities/database.py +11 -38
  23. orionis/foundation/config/database/entities/mysql.py +48 -76
  24. orionis/foundation/config/database/entities/oracle.py +30 -57
  25. orionis/foundation/config/database/entities/pgsql.py +45 -61
  26. orionis/foundation/config/database/entities/sqlite.py +26 -53
  27. orionis/foundation/config/filesystems/entitites/aws.py +28 -49
  28. orionis/foundation/config/filesystems/entitites/disks.py +27 -47
  29. orionis/foundation/config/filesystems/entitites/filesystems.py +15 -37
  30. orionis/foundation/config/filesystems/entitites/local.py +9 -35
  31. orionis/foundation/config/filesystems/entitites/public.py +14 -41
  32. orionis/foundation/config/logging/entities/channels.py +56 -86
  33. orionis/foundation/config/logging/entities/chunked.py +9 -9
  34. orionis/foundation/config/logging/entities/daily.py +8 -8
  35. orionis/foundation/config/logging/entities/hourly.py +6 -6
  36. orionis/foundation/config/logging/entities/logging.py +12 -18
  37. orionis/foundation/config/logging/entities/monthly.py +7 -7
  38. orionis/foundation/config/logging/entities/stack.py +5 -5
  39. orionis/foundation/config/logging/entities/weekly.py +6 -6
  40. orionis/foundation/config/mail/entities/file.py +9 -36
  41. orionis/foundation/config/mail/entities/mail.py +22 -40
  42. orionis/foundation/config/mail/entities/mailers.py +29 -44
  43. orionis/foundation/config/mail/entities/smtp.py +47 -48
  44. orionis/foundation/config/queue/entities/brokers.py +19 -41
  45. orionis/foundation/config/queue/entities/database.py +24 -46
  46. orionis/foundation/config/queue/entities/queue.py +28 -40
  47. orionis/foundation/config/roots/paths.py +272 -468
  48. orionis/foundation/config/session/entities/session.py +23 -53
  49. orionis/foundation/config/startup.py +165 -135
  50. orionis/foundation/config/testing/entities/testing.py +137 -122
  51. orionis/foundation/config/testing/enums/__init__.py +6 -2
  52. orionis/foundation/config/testing/enums/drivers.py +16 -0
  53. orionis/foundation/config/testing/enums/verbosity.py +18 -0
  54. orionis/foundation/contracts/application.py +152 -362
  55. orionis/foundation/providers/console_provider.py +24 -2
  56. orionis/foundation/providers/dumper_provider.py +24 -2
  57. orionis/foundation/providers/logger_provider.py +24 -2
  58. orionis/foundation/providers/path_resolver_provider.py +25 -2
  59. orionis/foundation/providers/progress_bar_provider.py +24 -2
  60. orionis/foundation/providers/testing_provider.py +39 -0
  61. orionis/foundation/providers/workers_provider.py +24 -2
  62. orionis/metadata/framework.py +1 -1
  63. orionis/services/asynchrony/contracts/coroutines.py +13 -5
  64. orionis/services/asynchrony/coroutines.py +33 -29
  65. orionis/services/asynchrony/exceptions/exception.py +9 -1
  66. orionis/services/environment/core/dot_env.py +46 -34
  67. orionis/services/environment/enums/__init__.py +0 -0
  68. orionis/services/environment/enums/cast_type.py +42 -0
  69. orionis/services/environment/helpers/functions.py +1 -2
  70. orionis/services/environment/key/__init__.py +0 -0
  71. orionis/services/environment/key/key_generator.py +37 -0
  72. orionis/services/environment/serializer/__init__.py +0 -0
  73. orionis/services/environment/serializer/values.py +21 -0
  74. orionis/services/environment/validators/__init__.py +0 -0
  75. orionis/services/environment/validators/key_name.py +46 -0
  76. orionis/services/environment/validators/types.py +45 -0
  77. orionis/services/system/contracts/imports.py +38 -18
  78. orionis/services/system/contracts/workers.py +29 -12
  79. orionis/services/system/imports.py +65 -25
  80. orionis/services/system/runtime/imports.py +18 -9
  81. orionis/services/system/workers.py +49 -16
  82. orionis/support/entities/__init__.py +0 -0
  83. orionis/support/entities/base.py +104 -0
  84. orionis/support/facades/testing.py +15 -0
  85. orionis/support/facades/workers.py +1 -1
  86. orionis/test/cases/asynchronous.py +0 -11
  87. orionis/test/cases/synchronous.py +0 -9
  88. orionis/test/contracts/dumper.py +11 -4
  89. orionis/test/contracts/kernel.py +5 -110
  90. orionis/test/contracts/logs.py +27 -65
  91. orionis/test/contracts/printer.py +16 -128
  92. orionis/test/contracts/test_result.py +100 -0
  93. orionis/test/contracts/unit_test.py +87 -150
  94. orionis/test/core/unit_test.py +608 -554
  95. orionis/test/entities/result.py +22 -2
  96. orionis/test/enums/__init__.py +0 -2
  97. orionis/test/enums/status.py +14 -9
  98. orionis/test/exceptions/config.py +9 -1
  99. orionis/test/exceptions/failure.py +34 -11
  100. orionis/test/exceptions/persistence.py +10 -2
  101. orionis/test/exceptions/runtime.py +9 -1
  102. orionis/test/exceptions/value.py +13 -1
  103. orionis/test/kernel.py +87 -289
  104. orionis/test/output/dumper.py +83 -18
  105. orionis/test/output/printer.py +399 -156
  106. orionis/test/records/logs.py +203 -82
  107. orionis/test/validators/__init__.py +33 -0
  108. orionis/test/validators/base_path.py +45 -0
  109. orionis/test/validators/execution_mode.py +45 -0
  110. orionis/test/validators/fail_fast.py +37 -0
  111. orionis/test/validators/folder_path.py +34 -0
  112. orionis/test/validators/module_name.py +31 -0
  113. orionis/test/validators/name_pattern.py +40 -0
  114. orionis/test/validators/pattern.py +36 -0
  115. orionis/test/validators/persistent.py +42 -0
  116. orionis/test/validators/persistent_driver.py +43 -0
  117. orionis/test/validators/print_result.py +37 -0
  118. orionis/test/validators/tags.py +37 -0
  119. orionis/test/validators/throw_exception.py +39 -0
  120. orionis/test/validators/verbosity.py +37 -0
  121. orionis/test/validators/web_report.py +35 -0
  122. orionis/test/validators/workers.py +31 -0
  123. orionis/test/view/render.py +48 -54
  124. {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/METADATA +1 -1
  125. {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/RECORD +170 -112
  126. tests/container/__init__.py +0 -0
  127. tests/container/context/__init__.py +0 -0
  128. tests/container/context/test_manager.py +27 -0
  129. tests/container/context/test_scope.py +23 -0
  130. tests/container/entities/__init__.py +0 -0
  131. tests/container/entities/test_binding.py +133 -0
  132. tests/container/enums/__init__.py +0 -0
  133. tests/container/enums/test_lifetimes.py +63 -0
  134. tests/container/facades/__init__.py +0 -0
  135. tests/container/facades/test_facade.py +61 -0
  136. tests/container/mocks/__init__.py +0 -0
  137. tests/container/mocks/mock_complex_classes.py +482 -0
  138. tests/container/mocks/mock_simple_classes.py +32 -0
  139. tests/container/providers/__init__.py +0 -0
  140. tests/container/providers/test_providers.py +48 -0
  141. tests/container/resolver/__init__.py +0 -0
  142. tests/container/resolver/test_resolver.py +55 -0
  143. tests/container/test_container.py +254 -0
  144. tests/container/test_singleton.py +98 -0
  145. tests/container/test_thread_safety.py +217 -0
  146. tests/container/validators/__init__.py +0 -0
  147. tests/container/validators/test_implements.py +140 -0
  148. tests/container/validators/test_is_abstract_class.py +99 -0
  149. tests/container/validators/test_is_callable.py +73 -0
  150. tests/container/validators/test_is_concrete_class.py +97 -0
  151. tests/container/validators/test_is_instance.py +105 -0
  152. tests/container/validators/test_is_not_subclass.py +117 -0
  153. tests/container/validators/test_is_subclass.py +115 -0
  154. tests/container/validators/test_is_valid_alias.py +113 -0
  155. tests/container/validators/test_lifetime.py +75 -0
  156. tests/example/test_example.py +2 -2
  157. tests/foundation/config/testing/test_foundation_config_testing.py +1 -1
  158. tests/metadata/test_metadata_framework.py +89 -24
  159. tests/metadata/test_metadata_package.py +55 -10
  160. tests/services/asynchrony/test_services_asynchrony_coroutine.py +52 -7
  161. tests/services/system/test_services_system_imports.py +119 -16
  162. tests/services/system/test_services_system_workers.py +71 -30
  163. tests/testing/test_testing_result.py +117 -117
  164. tests/testing/test_testing_unit.py +209 -209
  165. orionis/foundation/config/base.py +0 -112
  166. orionis/test/arguments/parser.py +0 -187
  167. orionis/test/contracts/parser.py +0 -43
  168. orionis/test/entities/arguments.py +0 -38
  169. orionis/test/enums/execution_mode.py +0 -16
  170. /orionis/{test/arguments → console/base/contracts}/__init__.py +0 -0
  171. /orionis/foundation/config/testing/enums/{test_mode.py → mode.py} +0 -0
  172. {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/WHEEL +0 -0
  173. {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/licenses/LICENCE +0 -0
  174. {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/top_level.txt +0 -0
  175. {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/zip-safe +0 -0
@@ -1,4 +1,5 @@
1
1
 
2
+ import asyncio
2
3
  from orionis.services.asynchrony.coroutines import Coroutine
3
4
  from orionis.services.asynchrony.exceptions import OrionisCoroutineException
4
5
  from orionis.test.cases.asynchronous import AsyncTestCase
@@ -7,34 +8,78 @@ class TestServicesAsynchronyCoroutine(AsyncTestCase):
7
8
 
8
9
  async def testExecuteWithActiveEventLoop(self):
9
10
  """
10
- Test the execution of a coroutine within an active event loop.
11
- This test simulates a scenario where the coroutine is executed in an environment with an active event loop,
12
- such as a Jupyter notebook or a Starlette application.
11
+ Tests coroutine execution within an active event loop.
12
+
13
+ This method verifies that a coroutine can be executed successfully when an event loop is already running,
14
+ such as in asynchronous environments (e.g., Jupyter notebooks or ASGI applications). It ensures that the
15
+ Coroutine wrapper correctly awaits and returns the result of the coroutine.
16
+
17
+ Returns
18
+ -------
19
+ None
20
+ This is a test method and does not return a value. It asserts that the coroutine result matches the expected output.
13
21
  """
22
+
23
+ # Simple coroutine that returns a string
14
24
  async def sample_coroutine():
25
+ asyncio.sleep(0.1)
15
26
  return "Hello, World!"
16
27
 
28
+ # Await the result of running the coroutine using the Coroutine wrapper
17
29
  result = await Coroutine(sample_coroutine()).run()
30
+
31
+ # Assert that the result matches the expected output
18
32
  self.assertEqual(result, "Hello, World!")
19
33
 
20
34
  def testExecuteWithoutActiveEventLoop(self):
21
35
  """
22
- Test the execution of a coroutine without an active event loop.
23
- This test simulates a scenario where the coroutine is executed in a synchronous context without an active event loop.
36
+ Tests coroutine execution without an active event loop.
37
+
38
+ This method simulates the scenario where a coroutine is executed in a synchronous context,
39
+ such as a standard Python script, where no event loop is running. It verifies that the
40
+ Coroutine wrapper can correctly create and manage an event loop internally, execute the
41
+ coroutine, and return the expected result.
42
+
43
+ Returns
44
+ -------
45
+ None
46
+ This test method does not return a value. It asserts that the coroutine result matches the expected output.
24
47
  """
48
+
49
+ # Define a simple coroutine that returns a string
25
50
  async def sample_coroutine():
51
+ asyncio.sleep(0.1)
26
52
  return "Hello, World!"
27
53
 
54
+ # Run the coroutine using the Coroutine wrapper, which should handle event loop creation
28
55
  result = Coroutine(sample_coroutine()).run()
56
+
57
+ # Assert that the result matches the expected output
29
58
  self.assertEqual(result, "Hello, World!")
30
59
 
31
60
  def testExecuteWithNonCoroutine(self):
32
61
  """
33
- Test the execution of a non-coroutine object.
34
- This test checks that a TypeError is raised when a non-coroutine object is passed to the execute method.
62
+ Tests execution of a non-coroutine object.
63
+
64
+ This method verifies that passing a non-coroutine object to the Coroutine wrapper
65
+ raises an OrionisCoroutineException. It ensures that the Coroutine class enforces
66
+ the requirement for coroutine objects and does not accept regular functions or other types.
67
+
68
+ Parameters
69
+ ----------
70
+ self : TestServicesAsynchronyCoroutine
71
+ The test case instance.
72
+
73
+ Returns
74
+ -------
75
+ None
76
+ This test method does not return a value. It asserts that the appropriate exception is raised.
35
77
  """
78
+
79
+ # Define a regular function (not a coroutine)
36
80
  def sample_no_coroutine():
37
81
  return "Hello, World!"
38
82
 
83
+ # Assert that passing a non-coroutine raises OrionisCoroutineException
39
84
  with self.assertRaises(OrionisCoroutineException):
40
85
  Coroutine(sample_no_coroutine())
@@ -1,101 +1,204 @@
1
- from orionis.services.system.imports import Imports
2
- from orionis.test.cases.asynchronous import AsyncTestCase
3
1
  import sys
4
2
  import types
3
+ from orionis.services.system.imports import Imports
4
+ from orionis.test.cases.asynchronous import AsyncTestCase
5
5
 
6
6
  class TestServicesSystemImports(AsyncTestCase):
7
7
 
8
- def testImportModule(self) -> None:
8
+ async def testImportModule(self) -> None:
9
9
  """
10
- Test that Imports can be instantiated and collected.
10
+ Tests that an Imports instance can be created and that the collect() method
11
+ successfully populates its imports list.
12
+
13
+ This test verifies the basic instantiation of the Imports class and ensures
14
+ that the collect() method executes without errors.
11
15
 
12
16
  Returns
13
17
  -------
14
18
  None
19
+ This method does not return any value.
15
20
  """
21
+
22
+ # Create an instance of Imports
16
23
  imports = Imports()
24
+
25
+ # Populate the imports list
17
26
  imports.collect()
27
+
28
+ # Assert that the instance is of type Imports
18
29
  self.assertIsInstance(imports, Imports)
19
30
 
20
- def testCollectPopulatesImports(self):
31
+ async def testCollectPopulatesImports(self):
21
32
  """
22
- Test that collect() populates the imports list with modules.
33
+ Tests that the `collect()` method of the Imports class populates the imports list with modules.
34
+
35
+ This test creates a dummy module, adds it to `sys.modules`, and verifies that after calling
36
+ `collect()`, the dummy module appears in the `imports` list of the Imports instance.
37
+
38
+ Parameters
39
+ ----------
40
+ self : TestServicesSystemImports
41
+ The test case instance.
23
42
 
24
43
  Returns
25
44
  -------
26
45
  None
46
+ This method does not return any value.
27
47
  """
48
+
49
+ # Create a dummy module and set its __file__ attribute
28
50
  dummy_mod = types.ModuleType("dummy_mod")
29
51
  dummy_mod.__file__ = __file__
52
+
53
+ # Add a dummy function to the module and set its __module__ attribute
30
54
  def dummy_func(): pass
31
55
  dummy_mod.dummy_func = dummy_func
32
56
  dummy_func.__module__ = "dummy_mod"
57
+
58
+ # Register the dummy module in sys.modules
33
59
  sys.modules["dummy_mod"] = dummy_mod
34
60
 
61
+ # Create Imports instance and collect imports
35
62
  imports = Imports()
36
63
  imports.collect()
64
+
65
+ # Check if the dummy module was collected
37
66
  found = any(imp["name"] == "dummy_mod" for imp in imports.imports)
38
67
  self.assertTrue(found)
39
68
 
40
- # Cleanup
69
+ # Cleanup: remove the dummy module from sys.modules
41
70
  del sys.modules["dummy_mod"]
42
71
 
43
- def testCollectExcludesStdlibAndSpecialModules(self):
72
+ async def testCollectExcludesStdlibAndSpecialModules(self):
44
73
  """
45
- Test that collect() excludes standard library and special modules.
74
+ Tests that the `collect()` method of the Imports class excludes standard library modules and special modules.
75
+
76
+ This test verifies that after calling `collect()`, the resulting imports list does not contain entries for
77
+ standard library modules such as `__main__` or modules whose names start with `_distutils`. This ensures
78
+ that the Imports class correctly filters out modules that should not be included in the imports list.
79
+
80
+ Parameters
81
+ ----------
82
+ self : TestServicesSystemImports
83
+ The test case instance.
46
84
 
47
85
  Returns
48
86
  -------
49
87
  None
88
+ This method does not return any value.
50
89
  """
90
+
91
+ # Create Imports instance and collect imports
51
92
  imports = Imports()
52
93
  imports.collect()
94
+
95
+ # Extract the names of collected modules
53
96
  names = [imp["name"] for imp in imports.imports]
97
+
98
+ # Assert that '__main__' is not in the collected imports
54
99
  self.assertNotIn("__main__", names)
100
+
101
+ # Assert that modules starting with '_distutils' are not in the collected imports
55
102
  self.assertFalse(any(n.startswith("_distutils") for n in names))
56
103
 
57
- def testClearEmptiesImports(self):
104
+ async def testClearEmptiesImports(self):
58
105
  """
59
- Test that clear() empties the imports list.
106
+ Tests that the `clear()` method of the Imports class empties the imports list.
107
+
108
+ This test manually populates the `imports` attribute of an Imports instance,
109
+ calls the `clear()` method, and verifies that the imports list is empty afterward.
110
+
111
+ Parameters
112
+ ----------
113
+ self : TestServicesSystemImports
114
+ The test case instance.
60
115
 
61
116
  Returns
62
117
  -------
63
118
  None
119
+ This method does not return any value.
64
120
  """
121
+ # Create Imports instance and manually populate the imports list
65
122
  imports = Imports()
66
123
  imports.imports = [{"name": "test", "file": "test.py", "symbols": ["a"]}]
124
+
125
+ # Call clear() to empty the imports list
67
126
  imports.clear()
127
+
128
+ # Assert that the imports list is now empty
68
129
  self.assertEqual(imports.imports, [])
69
130
 
70
- def testCollectHandlesModulesWithoutFile(self):
131
+ async def testCollectHandlesModulesWithoutFile(self):
71
132
  """
72
- Test that collect() handles modules without a __file__ attribute.
133
+ Tests that the `collect()` method of the Imports class correctly handles modules that do not have a `__file__` attribute.
134
+
135
+ This test creates a dummy module without a `__file__` attribute, registers it in `sys.modules`, and verifies that after calling
136
+ `collect()`, the module does not appear in the `imports` list of the Imports instance. This ensures that the Imports class
137
+ properly skips modules lacking a `__file__` attribute, which are typically built-in or dynamically created modules.
138
+
139
+ Parameters
140
+ ----------
141
+ self : TestServicesSystemImports
142
+ The test case instance.
73
143
 
74
144
  Returns
75
145
  -------
76
146
  None
147
+ This method does not return any value.
77
148
  """
149
+ # Create a dummy module without a __file__ attribute
78
150
  mod = types.ModuleType("mod_without_file")
79
151
  sys.modules["mod_without_file"] = mod
152
+
153
+ # Create Imports instance and collect imports
80
154
  imports = Imports()
81
155
  imports.collect()
156
+
157
+ # Extract the names of collected modules
82
158
  names = [imp["name"] for imp in imports.imports]
159
+
160
+ # Assert that the dummy module is not in the collected imports
83
161
  self.assertNotIn("mod_without_file", names)
162
+
163
+ # Cleanup: remove the dummy module from sys.modules
84
164
  del sys.modules["mod_without_file"]
85
165
 
86
- def testCollectSkipsBinaryExtensions(self):
166
+ async def testCollectSkipsBinaryExtensions(self):
87
167
  """
88
- Test that collect() skips binary extension modules.
168
+ Tests that the `collect()` method of the Imports class skips binary extension modules.
169
+
170
+ This test creates a dummy module with a `.pyd` file extension (representing a binary extension),
171
+ registers it in `sys.modules`, and verifies that after calling `collect()`, the module does not
172
+ appear in the `imports` list of the Imports instance. This ensures that the Imports class
173
+ properly excludes binary extension modules from its collected imports.
174
+
175
+ Parameters
176
+ ----------
177
+ self : TestServicesSystemImports
178
+ The test case instance.
89
179
 
90
180
  Returns
91
181
  -------
92
182
  None
183
+ This method does not return any value.
93
184
  """
185
+
186
+ # Create a dummy module with a .pyd file extension to simulate a binary extension
94
187
  mod = types.ModuleType("bin_mod")
95
188
  mod.__file__ = "bin_mod.pyd"
189
+
190
+ # Register the dummy binary module in sys.modules
96
191
  sys.modules["bin_mod"] = mod
192
+
193
+ # Create Imports instance and collect imports
97
194
  imports = Imports()
98
195
  imports.collect()
196
+
197
+ # Extract the names of collected modules
99
198
  names = [imp["name"] for imp in imports.imports]
199
+
200
+ # Assert that the binary module is not in the collected imports
100
201
  self.assertNotIn("bin_mod", names)
101
- del sys.modules["bin_mod"]
202
+
203
+ # Cleanup: remove the dummy binary module from sys.modules
204
+ del sys.modules["bin_mod"]
@@ -3,88 +3,129 @@ from orionis.services.system.workers import Workers
3
3
  from orionis.test.cases.asynchronous import AsyncTestCase
4
4
 
5
5
  class TestServicesSystemWorkers(AsyncTestCase):
6
- """
7
- Unit tests for the Workers class.
8
-
9
- This test suite verifies the correct calculation of the number of workers
10
- based on available CPU and RAM resources.
11
-
12
- Methods
13
- -------
14
- testCalculateCpuLimited()
15
- Test when the number of workers is limited by CPU count.
16
- testCalculateRamLimited()
17
- Test when the number of workers is limited by available RAM.
18
- testCalculateExactFit()
19
- Test when CPU and RAM allow for the same number of workers.
20
- testCalculateLowRam()
21
- Test when low RAM restricts the number of workers to less than CPU count.
22
- """
23
6
 
24
7
  @patch('multiprocessing.cpu_count', return_value=8)
25
8
  @patch('psutil.virtual_memory')
26
9
  def testCalculateCpuLimited(self, mockVm, mockCpuCount):
27
10
  """
28
- Test when the number of workers is limited by CPU count.
11
+ Tests worker calculation when CPU count is the limiting factor.
29
12
 
30
- Simulates 8 CPUs and 16 GB RAM, with ram_per_worker=1.
31
- RAM allows 16 workers, but CPU only allows 8.
13
+ Simulates a system with 8 CPUs and 16 GB RAM, where each worker requires 1 GB of RAM.
14
+ Although the available RAM could support up to 16 workers, the CPU count restricts the number
15
+ of workers to 8.
16
+
17
+ Parameters
18
+ ----------
19
+ mockVm : unittest.mock.Mock
20
+ Mock object for `psutil.virtual_memory`.
21
+ mockCpuCount : unittest.mock.Mock
22
+ Mock object for `multiprocessing.cpu_count`.
32
23
 
33
24
  Returns
34
25
  -------
35
26
  None
27
+ Asserts that the calculated number of workers is limited by CPU count.
36
28
  """
29
+
30
+ # Set the mocked total RAM to 16 GB
37
31
  mockVm.return_value.total = 16 * 1024 ** 3
32
+
33
+ # Create Workers instance with 1 GB RAM required per worker
38
34
  workers = Workers(ram_per_worker=1)
35
+
36
+ # Assert that the number of workers is limited to 8 by CPU count
39
37
  self.assertEqual(workers.calculate(), 8)
40
38
 
41
39
  @patch('multiprocessing.cpu_count', return_value=32)
42
40
  @patch('psutil.virtual_memory')
43
41
  def testCalculateRamLimited(self, mockVm, mockCpuCount):
44
42
  """
45
- Test when the number of workers is limited by available RAM.
43
+ Tests worker calculation when RAM is the limiting factor.
46
44
 
47
- Simulates 32 CPUs and 4 GB RAM, with ram_per_worker=1.
48
- RAM allows only 4 workers.
45
+ Simulates a system with 32 CPUs and 4 GB RAM, where each worker requires 1 GB of RAM.
46
+ Although the CPU count could support up to 32 workers, the available RAM restricts the number
47
+ of workers to 4.
48
+
49
+ Parameters
50
+ ----------
51
+ mockVm : unittest.mock.Mock
52
+ Mock object for `psutil.virtual_memory`.
53
+ mockCpuCount : unittest.mock.Mock
54
+ Mock object for `multiprocessing.cpu_count`.
49
55
 
50
56
  Returns
51
57
  -------
52
58
  None
59
+ Asserts that the calculated number of workers is limited by available RAM.
53
60
  """
61
+
62
+ # Set the mocked total RAM to 4 GB
54
63
  mockVm.return_value.total = 4 * 1024 ** 3
64
+
65
+ # Create Workers instance with 1 GB RAM required per worker
55
66
  workers = Workers(ram_per_worker=1)
67
+
68
+ # Assert that the number of workers is limited to 4 by available RAM
56
69
  self.assertEqual(workers.calculate(), 4)
57
70
 
58
71
  @patch('multiprocessing.cpu_count', return_value=4)
59
72
  @patch('psutil.virtual_memory')
60
73
  def testCalculateExactFit(self, mockVm, mockCpuCount):
61
74
  """
62
- Test when CPU and RAM allow for the same number of workers.
75
+ Tests worker calculation when both CPU count and available RAM allow for the same number of workers.
63
76
 
64
- Simulates 4 CPUs and 2 GB RAM, with ram_per_worker=0.5.
65
- RAM allows 4 workers.
77
+ Simulates a system with 4 CPUs and 2 GB RAM, where each worker requires 0.5 GB of RAM.
78
+ Both CPU and RAM resources permit exactly 4 workers, so the calculation should return 4.
79
+
80
+ Parameters
81
+ ----------
82
+ mockVm : unittest.mock.Mock
83
+ Mock object for `psutil.virtual_memory`.
84
+ mockCpuCount : unittest.mock.Mock
85
+ Mock object for `multiprocessing.cpu_count`.
66
86
 
67
87
  Returns
68
88
  -------
69
89
  None
90
+ Asserts that the calculated number of workers is 4, matching both CPU and RAM constraints.
70
91
  """
92
+ # Set the mocked total RAM to 2 GB
71
93
  mockVm.return_value.total = 2 * 1024 ** 3
94
+
95
+ # Create Workers instance with 0.5 GB RAM required per worker
72
96
  workers = Workers(ram_per_worker=0.5)
97
+
98
+ # Assert that the number of workers is limited to 4 by both CPU and RAM
73
99
  self.assertEqual(workers.calculate(), 4)
74
100
 
75
101
  @patch('multiprocessing.cpu_count', return_value=2)
76
102
  @patch('psutil.virtual_memory')
77
103
  def testCalculateLowRam(self, mockVm, mockCpuCount):
78
104
  """
79
- Test when low RAM restricts the number of workers to less than CPU count.
105
+ Tests worker calculation when available RAM is lower than CPU count, restricting the number of workers.
106
+
107
+ Simulates a system with 2 CPUs and 0.7 GB RAM, where each worker requires 0.5 GB of RAM.
108
+ Although the CPU count could support up to 2 workers, the available RAM restricts the number
109
+ of workers to 1.
80
110
 
81
- Simulates 2 CPUs and 0.7 GB RAM, with ram_per_worker=0.5.
82
- RAM allows only 1 worker.
111
+ Parameters
112
+ ----------
113
+ mockVm : unittest.mock.Mock
114
+ Mock object for `psutil.virtual_memory`.
115
+ mockCpuCount : unittest.mock.Mock
116
+ Mock object for `multiprocessing.cpu_count`.
83
117
 
84
118
  Returns
85
119
  -------
86
120
  None
121
+ Asserts that the calculated number of workers is limited to 1 by available RAM.
87
122
  """
123
+
124
+ # Set the mocked total RAM to 0.7 GB
88
125
  mockVm.return_value.total = 0.7 * 1024 ** 3
126
+
127
+ # Create Workers instance with 0.5 GB RAM required per worker
89
128
  workers = Workers(ram_per_worker=0.5)
90
- self.assertEqual(workers.calculate(), 1)
129
+
130
+ # Assert that the number of workers is limited to 1 by available RAM
131
+ self.assertEqual(workers.calculate(), 1)