mapFolding 0.3.12__py3-none-any.whl → 0.4.1__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.
- mapFolding/__init__.py +40 -38
- mapFolding/basecamp.py +50 -50
- mapFolding/beDRY.py +336 -336
- mapFolding/oeis.py +262 -262
- mapFolding/reference/flattened.py +294 -293
- mapFolding/reference/hunterNumba.py +126 -126
- mapFolding/reference/irvineJavaPort.py +99 -99
- mapFolding/reference/jax.py +153 -153
- mapFolding/reference/lunnan.py +148 -148
- mapFolding/reference/lunnanNumpy.py +115 -115
- mapFolding/reference/lunnanWhile.py +114 -114
- mapFolding/reference/rotatedEntryPoint.py +183 -183
- mapFolding/reference/total_countPlus1vsPlusN.py +203 -203
- mapFolding/someAssemblyRequired/__init__.py +5 -1
- mapFolding/someAssemblyRequired/getLLVMforNoReason.py +12 -12
- mapFolding/someAssemblyRequired/makeJob.py +46 -52
- mapFolding/someAssemblyRequired/synthesizeModuleJAX.py +17 -17
- mapFolding/someAssemblyRequired/synthesizeNumba.py +343 -633
- mapFolding/someAssemblyRequired/synthesizeNumbaGeneralized.py +325 -0
- mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +173 -0
- mapFolding/someAssemblyRequired/synthesizeNumbaModules.py +77 -0
- mapFolding/syntheticModules/__init__.py +0 -0
- mapFolding/syntheticModules/numba_countInitialize.py +4 -4
- mapFolding/syntheticModules/numba_countParallel.py +4 -4
- mapFolding/syntheticModules/numba_countSequential.py +4 -4
- mapFolding/syntheticModules/numba_doTheNeedful.py +7 -7
- mapFolding/theDao.py +165 -165
- mapFolding/theSSOT.py +177 -173
- mapFolding/theSSOTnumba.py +90 -74
- mapFolding-0.4.1.dist-info/METADATA +154 -0
- mapFolding-0.4.1.dist-info/RECORD +42 -0
- tests/conftest.py +253 -129
- tests/test_computations.py +79 -0
- tests/test_oeis.py +76 -85
- tests/test_other.py +136 -224
- tests/test_tasks.py +19 -23
- tests/test_types.py +2 -2
- mapFolding/someAssemblyRequired/synthesizeNumbaHardcoding.py +0 -188
- mapFolding-0.3.12.dist-info/METADATA +0 -155
- mapFolding-0.3.12.dist-info/RECORD +0 -40
- tests/conftest_tmpRegistry.py +0 -62
- tests/conftest_uniformTests.py +0 -53
- {mapFolding-0.3.12.dist-info → mapFolding-0.4.1.dist-info}/LICENSE +0 -0
- {mapFolding-0.3.12.dist-info → mapFolding-0.4.1.dist-info}/WHEEL +0 -0
- {mapFolding-0.3.12.dist-info → mapFolding-0.4.1.dist-info}/entry_points.txt +0 -0
- {mapFolding-0.3.12.dist-info → mapFolding-0.4.1.dist-info}/top_level.txt +0 -0
tests/test_other.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from contextlib import redirect_stdout
|
|
2
2
|
from tests.conftest import *
|
|
3
|
-
from typing import Dict, List, Optional, Any, Tuple, Literal, Callable, Generator
|
|
4
3
|
from Z0Z_tools import intInnit
|
|
5
4
|
import io
|
|
6
5
|
import itertools
|
|
@@ -12,248 +11,161 @@ import random
|
|
|
12
11
|
import sys
|
|
13
12
|
|
|
14
13
|
@pytest.mark.parametrize("listDimensions,expected_intInnit,expected_parseListDimensions,expected_validateListDimensions,expected_getLeavesTotal", [
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
14
|
+
(None, ValueError, ValueError, ValueError, ValueError), # None instead of list
|
|
15
|
+
(['a'], ValueError, ValueError, ValueError, ValueError), # string
|
|
16
|
+
([-4, 2], [-4, 2], ValueError, ValueError, ValueError), # negative
|
|
17
|
+
([-3], [-3], ValueError, ValueError, ValueError), # negative
|
|
18
|
+
([0, 0], [0, 0], [0, 0], NotImplementedError, 0), # no positive dimensions
|
|
19
|
+
([0, 5, 6], [0, 5, 6], [0, 5, 6], [5, 6], 30), # zeros ignored
|
|
20
|
+
([0], [0], [0], NotImplementedError, 0), # edge case
|
|
21
|
+
([1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], 120), # sequential
|
|
22
|
+
([1, sys.maxsize], [1, sys.maxsize], [1, sys.maxsize], [1, sys.maxsize], sys.maxsize), # maxint
|
|
23
|
+
([7.5], ValueError, ValueError, ValueError, ValueError), # float
|
|
24
|
+
([1] * 1000, [1] * 1000, [1] * 1000, [1] * 1000, 1), # long list
|
|
25
|
+
([11], [11], [11], NotImplementedError, 11), # single dimension
|
|
26
|
+
([13, 0, 17], [13, 0, 17], [13, 0, 17], [13, 17], 221), # zeros handled
|
|
27
|
+
([2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2], 16), # repeated dimensions
|
|
28
|
+
([2, 3, 4], [2, 3, 4], [2, 3, 4], [2, 3, 4], 24),
|
|
29
|
+
([2, 3], [2, 3], [2, 3], [2, 3], 6),
|
|
30
|
+
([2] * 11, [2] * 11, [2] * 11, [2] * 11, 2048), # power of 2
|
|
31
|
+
([3, 2], [3, 2], [3, 2], [2, 3], 6), # return value is the input when valid
|
|
32
|
+
([3] * 5, [3] * 5, [3] * 5, [3, 3, 3, 3, 3], 243), # power of 3
|
|
33
|
+
([None], TypeError, TypeError, TypeError, TypeError), # None
|
|
34
|
+
([True], TypeError, TypeError, TypeError, TypeError), # bool
|
|
35
|
+
([[17, 39]], TypeError, TypeError, TypeError, TypeError), # nested
|
|
36
|
+
([], ValueError, ValueError, ValueError, ValueError), # empty
|
|
37
|
+
([complex(1,1)], ValueError, ValueError, ValueError, ValueError), # complex number
|
|
38
|
+
([float('inf')], ValueError, ValueError, ValueError, ValueError), # infinity
|
|
39
|
+
([float('nan')], ValueError, ValueError, ValueError, ValueError), # NaN
|
|
40
|
+
([sys.maxsize - 1, 1], [sys.maxsize - 1, 1], [sys.maxsize - 1, 1], [1, sys.maxsize - 1], sys.maxsize - 1), # near maxint
|
|
41
|
+
([sys.maxsize // 2, sys.maxsize // 2, 2], [sys.maxsize // 2, sys.maxsize // 2, 2], [sys.maxsize // 2, sys.maxsize // 2, 2], [2, sys.maxsize // 2, sys.maxsize // 2], OverflowError), # overflow protection
|
|
42
|
+
([sys.maxsize, sys.maxsize], [sys.maxsize, sys.maxsize], [sys.maxsize, sys.maxsize], [sys.maxsize, sys.maxsize], OverflowError), # overflow protection
|
|
43
|
+
(range(3, 7), [3, 4, 5, 6], [3, 4, 5, 6], [3, 4, 5, 6], 360), # range sequence type
|
|
44
|
+
(tuple([3, 5, 7]), [3, 5, 7], [3, 5, 7], [3, 5, 7], 105), # tuple sequence type
|
|
46
45
|
])
|
|
47
46
|
def test_listDimensionsAsParameter(listDimensions: None | List[str] | List[int] | List[float] | List[None] | List[bool] | List[List[int]] | List[complex] | range | tuple[int, ...], expected_intInnit: type[ValueError] | List[int] | type[TypeError], expected_parseListDimensions: type[ValueError] | List[int] | type[TypeError], expected_validateListDimensions: type[ValueError] | type[NotImplementedError] | List[int] | type[TypeError], expected_getLeavesTotal: type[ValueError] | int | type[TypeError] | type[OverflowError]) -> None:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
"""Test both validateListDimensions and getLeavesTotal with the same inputs."""
|
|
48
|
+
standardizedEqualTo(expected_intInnit, intInnit, listDimensions)
|
|
49
|
+
standardizedEqualTo(expected_parseListDimensions, parseDimensions, listDimensions)
|
|
50
|
+
standardizedEqualTo(expected_validateListDimensions, validateListDimensions, listDimensions)
|
|
51
|
+
standardizedEqualTo(expected_getLeavesTotal, getLeavesTotal, listDimensions)
|
|
53
52
|
|
|
54
53
|
def test_getLeavesTotal_edge_cases() -> None:
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
"""Test edge cases for getLeavesTotal."""
|
|
55
|
+
# Order independence
|
|
56
|
+
standardizedEqualTo(getLeavesTotal([2, 3, 4]), getLeavesTotal, [4, 2, 3])
|
|
58
57
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
# TODO fix this mock
|
|
65
|
-
# @pytest.mark.parametrize("foldsValue,writeFoldsTarget", [
|
|
66
|
-
# (756839, "foldsTotalTest.txt"), # Direct file
|
|
67
|
-
# (2640919, "foldsTotalTest.txt"), # Direct file
|
|
68
|
-
# (7715177, None), # Directory, will use default filename
|
|
69
|
-
# ])
|
|
70
|
-
# def test_countFolds_writeFoldsTotal(
|
|
71
|
-
# listDimensionsTestFunctionality: List[int],
|
|
72
|
-
# pathTempTesting: pathlib.Path,
|
|
73
|
-
# mockFoldingFunction: Callable[..., Callable[..., None]],
|
|
74
|
-
# mockDispatcher: Callable[[Callable[..., None]], Any],
|
|
75
|
-
# foldsValue: int,
|
|
76
|
-
# writeFoldsTarget: Optional[str]
|
|
77
|
-
# ) -> None:
|
|
78
|
-
# """Test writing folds total to either a file or directory."""
|
|
79
|
-
# # For directory case, use the directory path directly
|
|
80
|
-
# if writeFoldsTarget is None:
|
|
81
|
-
# pathWriteTarget = pathTempTesting
|
|
82
|
-
# filenameFoldsTotalExpected = getFilenameFoldsTotal(listDimensionsTestFunctionality)
|
|
83
|
-
# else:
|
|
84
|
-
# pathWriteTarget = pathTempTesting / writeFoldsTarget
|
|
85
|
-
# filenameFoldsTotalExpected = writeFoldsTarget
|
|
86
|
-
|
|
87
|
-
# foldsTotalExpected = foldsValue * getLeavesTotal(listDimensionsTestFunctionality)
|
|
88
|
-
# mock_countFolds = mockFoldingFunction(foldsValue, listDimensionsTestFunctionality)
|
|
89
|
-
|
|
90
|
-
# with mockDispatcher(mock_countFolds):
|
|
91
|
-
# returned = countFolds(listDimensionsTestFunctionality, pathLikeWriteFoldsTotal=pathWriteTarget)
|
|
92
|
-
|
|
93
|
-
# standardizedEqualTo(str(foldsTotalExpected), lambda: (pathTempTesting / filenameFoldsTotalExpected).read_text())
|
|
58
|
+
# Immutability
|
|
59
|
+
listOriginal = [2, 3]
|
|
60
|
+
standardizedEqualTo(6, getLeavesTotal, listOriginal)
|
|
61
|
+
standardizedEqualTo([2, 3], lambda x: x, listOriginal) # Check that the list wasn't modified
|
|
94
62
|
|
|
95
63
|
@pytest.mark.parametrize("nameOfTest,callablePytest", PytestFor_intInnit())
|
|
96
64
|
def testIntInnit(nameOfTest: str, callablePytest: Callable[[], None]) -> None:
|
|
97
|
-
|
|
65
|
+
callablePytest()
|
|
98
66
|
|
|
99
67
|
@pytest.mark.parametrize("nameOfTest,callablePytest", PytestFor_oopsieKwargsie())
|
|
100
68
|
def testOopsieKwargsie(nameOfTest: str, callablePytest: Callable[[], None]) -> None:
|
|
101
|
-
|
|
69
|
+
callablePytest()
|
|
102
70
|
|
|
103
71
|
@pytest.mark.parametrize("CPUlimit, expectedLimit", [
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
72
|
+
(None, numba.get_num_threads()),
|
|
73
|
+
(False, numba.get_num_threads()),
|
|
74
|
+
(True, 1),
|
|
75
|
+
(4, 4),
|
|
76
|
+
(0.5, max(1, numba.get_num_threads() // 2)),
|
|
77
|
+
(-0.5, max(1, numba.get_num_threads() // 2)),
|
|
78
|
+
(-2, max(1, numba.get_num_threads() - 2)),
|
|
79
|
+
(0, numba.get_num_threads()),
|
|
80
|
+
(1, 1),
|
|
113
81
|
])
|
|
114
82
|
def test_setCPUlimit(CPUlimit: None | float | bool | Literal[4] | Literal[-2] | Literal[0] | Literal[1], expectedLimit: Any | int) -> None:
|
|
115
|
-
|
|
83
|
+
standardizedEqualTo(expectedLimit, setCPUlimit, CPUlimit)
|
|
116
84
|
|
|
117
85
|
def test_makeConnectionGraph_nonNegative(listDimensionsTestFunctionality: List[int]) -> None:
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
# @pytest.mark.parametrize("datatype", ['int16', 'uint64'])
|
|
122
|
-
# def test_makeConnectionGraph_datatype(listDimensionsTestFunctionality: List[int], datatype) -> None:
|
|
123
|
-
# connectionGraph = makeConnectionGraph(listDimensionsTestFunctionality, datatype=datatype)
|
|
124
|
-
# assert connectionGraph.dtype == datatype, f"Expected datatype {datatype}, but got {connectionGraph.dtype}."
|
|
125
|
-
|
|
126
|
-
"""5 parameters
|
|
127
|
-
listDimensionsTestFunctionality
|
|
128
|
-
|
|
129
|
-
computationDivisions
|
|
130
|
-
None
|
|
131
|
-
random: int, first included: 2, first excluded: leavesTotal
|
|
132
|
-
maximum
|
|
133
|
-
cpu
|
|
134
|
-
|
|
135
|
-
CPUlimit
|
|
136
|
-
None
|
|
137
|
-
True
|
|
138
|
-
False
|
|
139
|
-
0
|
|
140
|
-
1
|
|
141
|
-
-1
|
|
142
|
-
random: 0 < float < 1
|
|
143
|
-
random: -1 < float < 0
|
|
144
|
-
random: int, first included: 2, first excluded: (min(leavesTotal, 16) - 1)
|
|
145
|
-
random: int, first included: -1 * (min(leavesTotal, 16) - 1), first excluded: -1
|
|
146
|
-
|
|
147
|
-
datatypeMedium
|
|
148
|
-
None
|
|
149
|
-
numpy.int64
|
|
150
|
-
numpy.intc
|
|
151
|
-
numpy.uint16
|
|
152
|
-
|
|
153
|
-
datatypeLarge
|
|
154
|
-
None
|
|
155
|
-
numpy.int64
|
|
156
|
-
numpy.intp
|
|
157
|
-
numpy.uint32
|
|
158
|
-
|
|
159
|
-
"""
|
|
86
|
+
connectionGraph = makeConnectionGraph(listDimensionsTestFunctionality)
|
|
87
|
+
assert numpy.all(connectionGraph >= 0), "All values in the connection graph should be non-negative."
|
|
160
88
|
|
|
161
89
|
@pytest.fixture
|
|
162
90
|
def parameterIterator() -> Callable[[List[int]], Generator[Dict[str, Any], None, None]]:
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
# # Check that path was set to Colab-specific value
|
|
238
|
-
# assert mapFolding.theSSOT.pathJobDEFAULT == pathlib.Path("/content/drive/MyDrive") / "jobs"
|
|
239
|
-
|
|
240
|
-
# # Reload one more time to restore original state
|
|
241
|
-
# importlib.reload(mapFolding.theSSOT)
|
|
242
|
-
|
|
243
|
-
def test_saveFoldsTotal_fallback(pathTempTesting: pathlib.Path) -> None:
|
|
244
|
-
foldsTotal = 123
|
|
245
|
-
pathFilename = pathTempTesting / "foldsTotal.txt"
|
|
246
|
-
with unittest.mock.patch("pathlib.Path.write_text", side_effect=OSError("Simulated write failure")):
|
|
247
|
-
with unittest.mock.patch("os.getcwd", return_value=str(pathTempTesting)):
|
|
248
|
-
capturedOutput = io.StringIO()
|
|
249
|
-
with redirect_stdout(capturedOutput):
|
|
250
|
-
saveFoldsTotal(pathFilename, foldsTotal)
|
|
251
|
-
fallbackFiles = list(pathTempTesting.glob("foldsTotalYO_*.txt"))
|
|
252
|
-
assert len(fallbackFiles) == 1, "Fallback file was not created upon write failure."
|
|
91
|
+
"""Generate random combinations of parameters for outfitCountFolds testing."""
|
|
92
|
+
parameterSets: Dict[str, List[Any]] = {
|
|
93
|
+
'computationDivisions': [
|
|
94
|
+
None,
|
|
95
|
+
'maximum',
|
|
96
|
+
'cpu',
|
|
97
|
+
],
|
|
98
|
+
'CPUlimit': [
|
|
99
|
+
None, True, False, 0, 1, -1,
|
|
100
|
+
],
|
|
101
|
+
'datatypeMedium': [
|
|
102
|
+
None,
|
|
103
|
+
numpy.int64,
|
|
104
|
+
numpy.intc,
|
|
105
|
+
numpy.uint16
|
|
106
|
+
],
|
|
107
|
+
'datatypeLarge': [
|
|
108
|
+
None,
|
|
109
|
+
numpy.int64,
|
|
110
|
+
numpy.intp,
|
|
111
|
+
numpy.uint32
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
def makeParametersDynamic(listDimensions: List[int]) -> Dict[str, List[Any]]:
|
|
116
|
+
"""Add context-dependent parameter values."""
|
|
117
|
+
parametersDynamic = parameterSets.copy()
|
|
118
|
+
leavesTotal = getLeavesTotal(listDimensions)
|
|
119
|
+
concurrencyLimit = min(leavesTotal, 16)
|
|
120
|
+
|
|
121
|
+
# Add dynamic computationDivisions values
|
|
122
|
+
dynamicDivisions = [random.randint(2, leavesTotal-1) for iterator in range(3)]
|
|
123
|
+
parametersDynamic['computationDivisions'] = parametersDynamic['computationDivisions'] + dynamicDivisions
|
|
124
|
+
|
|
125
|
+
# Add dynamic CPUlimit values
|
|
126
|
+
parameterDynamicCPU = [
|
|
127
|
+
random.random(), # 0 to 1
|
|
128
|
+
-random.random(), # -1 to 0
|
|
129
|
+
]
|
|
130
|
+
parameterDynamicCPU.extend(
|
|
131
|
+
[random.randint(2, concurrencyLimit-1) for iterator in range(2)]
|
|
132
|
+
)
|
|
133
|
+
parameterDynamicCPU.extend(
|
|
134
|
+
[random.randint(-concurrencyLimit+1, -2) for iterator in range(2)]
|
|
135
|
+
)
|
|
136
|
+
parametersDynamic['CPUlimit'] = parametersDynamic['CPUlimit'] + parameterDynamicCPU
|
|
137
|
+
|
|
138
|
+
return parametersDynamic
|
|
139
|
+
|
|
140
|
+
def generateCombinations(listDimensions: List[int]) -> Generator[Dict[str, Any], None, None]:
|
|
141
|
+
parametersDynamic = makeParametersDynamic(listDimensions)
|
|
142
|
+
parameterKeys = list(parametersDynamic.keys())
|
|
143
|
+
parameterValues = [parametersDynamic[key] for key in parameterKeys]
|
|
144
|
+
|
|
145
|
+
# Shuffle each parameter list
|
|
146
|
+
for valueList in parameterValues:
|
|
147
|
+
random.shuffle(valueList)
|
|
148
|
+
|
|
149
|
+
# Use zip_longest to iterate, filling with None when shorter lists are exhausted
|
|
150
|
+
for combination in itertools.zip_longest(*parameterValues, fillvalue=None):
|
|
151
|
+
yield dict(zip(parameterKeys, combination))
|
|
152
|
+
|
|
153
|
+
return generateCombinations
|
|
154
|
+
|
|
155
|
+
def test_saveFoldsTotal_fallback(pathTmpTesting: pathlib.Path) -> None:
|
|
156
|
+
foldsTotal = 123
|
|
157
|
+
pathFilename = pathTmpTesting / "foldsTotal.txt"
|
|
158
|
+
with unittest.mock.patch("pathlib.Path.write_text", side_effect=OSError("Simulated write failure")):
|
|
159
|
+
with unittest.mock.patch("os.getcwd", return_value=str(pathTmpTesting)):
|
|
160
|
+
capturedOutput = io.StringIO()
|
|
161
|
+
with redirect_stdout(capturedOutput):
|
|
162
|
+
saveFoldsTotal(pathFilename, foldsTotal)
|
|
163
|
+
fallbackFiles = list(pathTmpTesting.glob("foldsTotalYO_*.txt"))
|
|
164
|
+
assert len(fallbackFiles) == 1, "Fallback file was not created upon write failure."
|
|
253
165
|
|
|
254
166
|
def test_makeDataContainer_default_datatype() -> None:
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
167
|
+
"""Test that makeDataContainer uses dtypeLargeDEFAULT when no datatype is specified."""
|
|
168
|
+
testShape = (3, 4)
|
|
169
|
+
container = makeDataContainer(testShape)
|
|
170
|
+
assert container.dtype == hackSSOTdtype('dtypeFoldsTotal'), f"Expected datatype but got {container.dtype}"
|
|
171
|
+
assert container.shape == testShape, f"Expected shape {testShape}, but got {container.shape}"
|
tests/test_tasks.py
CHANGED
|
@@ -1,44 +1,40 @@
|
|
|
1
1
|
from tests.conftest import *
|
|
2
2
|
import pytest
|
|
3
|
-
from typing import List, Dict, Literal, Tuple, Any
|
|
4
3
|
|
|
5
4
|
# TODO add a test. `C` = number of logical cores available. `n = C + 1`. Ensure that `[2,n]` is computed correctly.
|
|
6
5
|
# Or, probably smarter: limit the number of cores, then run a test with C+1.
|
|
7
6
|
|
|
8
|
-
def test_algorithmSourceParallel(listDimensionsTestParallelization: List[int], foldsTotalKnown: Dict[Tuple[int, ...], int], useAlgorithmDirectly: None) -> None:
|
|
9
|
-
standardizedEqualTo(foldsTotalKnown[tuple(listDimensionsTestParallelization)], countFolds, listDimensionsTestParallelization, None, 'maximum')
|
|
10
|
-
|
|
11
7
|
def test_countFoldsComputationDivisionsInvalid(listDimensionsTestFunctionality: List[int]) -> None:
|
|
12
|
-
|
|
8
|
+
standardizedEqualTo(ValueError, countFolds, listDimensionsTestFunctionality, None, {"wrong": "value"})
|
|
13
9
|
|
|
14
10
|
def test_countFoldsComputationDivisionsMaximum(listDimensionsTestParallelization: List[int], foldsTotalKnown: Dict[Tuple[int, ...], int]) -> None:
|
|
15
|
-
|
|
11
|
+
standardizedEqualTo(foldsTotalKnown[tuple(listDimensionsTestParallelization)], countFolds, listDimensionsTestParallelization, None, 'maximum')
|
|
16
12
|
|
|
17
13
|
@pytest.mark.parametrize("nameOfTest,callablePytest", PytestFor_defineConcurrencyLimit())
|
|
18
14
|
def test_defineConcurrencyLimit(nameOfTest: str, callablePytest: Callable[[], None]) -> None:
|
|
19
|
-
|
|
15
|
+
callablePytest()
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
@pytest.mark.parametrize("CPUlimitParameter", [{"invalid": True}, ["weird"]])
|
|
18
|
+
def test_countFolds_cpuLimitOopsie(listDimensionsTestFunctionality: List[int], CPUlimitParameter: Dict[str, bool] | List[str]) -> None:
|
|
19
|
+
standardizedEqualTo(ValueError, countFolds, listDimensionsTestFunctionality, None, 'cpu', CPUlimitParameter)
|
|
24
20
|
|
|
25
21
|
@pytest.mark.parametrize("computationDivisions, concurrencyLimit, listDimensions, expectedTaskDivisions", [
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
(None, 4, [9, 11], 0),
|
|
23
|
+
("maximum", 4, [7, 11], 77),
|
|
24
|
+
("cpu", 4, [3, 7], 4),
|
|
25
|
+
(["invalid"], 4, [19, 23], ValueError),
|
|
26
|
+
(20, 4, [3,5], ValueError)
|
|
31
27
|
])
|
|
32
28
|
def test_getTaskDivisions(computationDivisions: None | List[str] | Literal['maximum'] | Literal['cpu'] | Literal[20], concurrencyLimit: Literal[4], listDimensions: List[int], expectedTaskDivisions: type[ValueError] | Literal[0] | Literal[77] | Literal[4]) -> None:
|
|
33
|
-
|
|
29
|
+
standardizedEqualTo(expectedTaskDivisions, getTaskDivisions, computationDivisions, concurrencyLimit, None, listDimensions)
|
|
34
30
|
|
|
35
31
|
@pytest.mark.parametrize("expected,parameter", [
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
(2, "2"), # string
|
|
33
|
+
(ValueError, [4]), # list
|
|
34
|
+
(ValueError, (2,)), # tuple
|
|
35
|
+
(ValueError, {2}), # set
|
|
36
|
+
(ValueError, {"cores": 2}), # dict
|
|
41
37
|
])
|
|
42
38
|
def test_setCPUlimitMalformedParameter(expected: type[ValueError] | Literal[2], parameter: List[int] | Tuple[int] | set[int] | Dict[str, int] | Literal['2']) -> None:
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
"""Test that invalid CPUlimit types are properly handled."""
|
|
40
|
+
standardizedEqualTo(expected, setCPUlimit, parameter)
|
tests/test_types.py
CHANGED