mapFolding 0.12.3__py3-none-any.whl → 0.13.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.
@@ -24,7 +24,7 @@ research domain.
24
24
  """
25
25
 
26
26
  from collections.abc import Callable, Generator, Sequence
27
- from mapFolding import getLeavesTotal, makeDataContainer, validateListDimensions
27
+ from mapFolding import getLeavesTotal, makeDataContainer, oeis, packageSettings, validateListDimensions
28
28
  from mapFolding.oeis import oeisIDsImplemented, settingsOEIS
29
29
  from pathlib import Path
30
30
  from typing import Any
@@ -34,50 +34,90 @@ import random
34
34
  import shutil
35
35
  import unittest.mock
36
36
  import uuid
37
+ import warnings
38
+
39
+ # ruff: noqa: S311
37
40
 
38
41
  # SSOT for test data paths and filenames
39
- pathDataSamples: Path = Path("tests/dataSamples").absolute()
40
- pathTmpRoot: Path = pathDataSamples / "tmp"
41
- pathTmpRoot.mkdir(parents=True, exist_ok=True)
42
+ pathDataSamples: Path = Path(packageSettings.pathPackage, "tests/dataSamples").absolute()
43
+ path_tmpRoot: Path = pathDataSamples / "tmp"
44
+ path_tmpRoot.mkdir(parents=True, exist_ok=True)
42
45
 
43
46
  # The registrar maintains the register of temp files
44
47
  registerOfTemporaryFilesystemObjects: set[Path] = set()
45
48
 
46
- def registrarRecordsTmpObject(path: Path) -> None:
47
- """The registrar adds a tmp file to the register."""
49
+ def registrarRecordsTemporaryFilesystemObject(path: Path) -> None:
50
+ """The registrar adds a tmp file to the register.
51
+
52
+ Parameters
53
+ ----------
54
+ path : Path
55
+ The filesystem path to register for cleanup.
56
+
57
+ """
48
58
  registerOfTemporaryFilesystemObjects.add(path)
49
59
 
50
- def registrarDeletesTmpObjects() -> None:
60
+ def registrarDeletesTemporaryFilesystemObjects() -> None:
51
61
  """The registrar cleans up tmp files in the register."""
52
- for pathTmp in sorted(registerOfTemporaryFilesystemObjects, reverse=True):
53
- try:
54
- if pathTmp.is_file():
55
- pathTmp.unlink(missing_ok=True)
56
- elif pathTmp.is_dir():
57
- shutil.rmtree(pathTmp, ignore_errors=True)
58
- except Exception as ERRORmessage:
59
- print(f"Warning: Failed to clean up {pathTmp}: {ERRORmessage}")
62
+ for path_tmp in sorted(registerOfTemporaryFilesystemObjects, reverse=True):
63
+ if path_tmp.is_file():
64
+ path_tmp.unlink(missing_ok=True)
65
+ elif path_tmp.is_dir():
66
+ shutil.rmtree(path_tmp, ignore_errors=True)
60
67
  registerOfTemporaryFilesystemObjects.clear()
61
68
 
62
69
  @pytest.fixture(scope="session", autouse=True)
63
- def setupTeardownTmpObjects() -> Generator[None, None, None]:
64
- """Auto-fixture to setup test data directories and cleanup after."""
70
+ def setupTeardownTemporaryFilesystemObjects() -> Generator[None, None, None]:
71
+ """Auto-fixture to setup test data directories and cleanup after.
72
+
73
+ Returns
74
+ -------
75
+ contextManager : Generator[None, None, None]
76
+ Context manager that sets up test directories and ensures cleanup.
77
+
78
+ """
65
79
  pathDataSamples.mkdir(exist_ok=True)
66
- pathTmpRoot.mkdir(exist_ok=True)
80
+ path_tmpRoot.mkdir(exist_ok=True)
67
81
  yield
68
- registrarDeletesTmpObjects()
82
+ registrarDeletesTemporaryFilesystemObjects()
69
83
 
70
84
  @pytest.fixture
71
- def pathTmpTesting(request: pytest.FixtureRequest) -> Path:
85
+ def path_tmpTesting(request: pytest.FixtureRequest) -> Path:
86
+ """Creates a unique temporary directory for testing.
87
+
88
+ Parameters
89
+ ----------
90
+ request : pytest.FixtureRequest
91
+ The pytest request object providing test context.
92
+
93
+ Returns
94
+ -------
95
+ temporaryPath : Path
96
+ Path to a unique temporary directory that will be cleaned up automatically.
97
+
98
+ """
72
99
  # "Z0Z_" ensures the directory name does not start with a number, which would make it an invalid Python identifier
73
- pathTmp: Path = pathTmpRoot / ("Z0Z_" + str(uuid.uuid4().hex))
74
- pathTmp.mkdir(parents=True, exist_ok=False)
100
+ path_tmp: Path = path_tmpRoot / ("Z0Z_" + str(uuid.uuid4().hex))
101
+ path_tmp.mkdir(parents=True, exist_ok=False)
75
102
 
76
- registrarRecordsTmpObject(pathTmp)
77
- return pathTmp
103
+ registrarRecordsTemporaryFilesystemObject(path_tmp)
104
+ return path_tmp
78
105
 
79
106
  @pytest.fixture
80
- def pathFilenameTmpTesting(request: pytest.FixtureRequest) -> Path:
107
+ def pathFilename_tmpTesting(request: pytest.FixtureRequest) -> Path:
108
+ """Creates a unique temporary file path for testing.
109
+
110
+ Parameters
111
+ ----------
112
+ request : pytest.FixtureRequest
113
+ The pytest request object, optionally containing `param` for file extension.
114
+
115
+ Returns
116
+ -------
117
+ temporaryFilePath : Path
118
+ Path to a unique temporary file that will be cleaned up automatically.
119
+
120
+ """
81
121
  try:
82
122
  extension = request.param
83
123
  except AttributeError:
@@ -88,32 +128,62 @@ def pathFilenameTmpTesting(request: pytest.FixtureRequest) -> Path:
88
128
  subpath = "Z0Z_" + uuidHex[0:-8]
89
129
  filenameStem = "Z0Z_" + uuidHex[-8:None]
90
130
 
91
- pathFilenameTmp = Path(pathTmpRoot, subpath, filenameStem + extension)
92
- pathFilenameTmp.parent.mkdir(parents=True, exist_ok=False)
131
+ pathFilename_tmp = Path(path_tmpRoot, subpath, filenameStem + extension)
132
+ pathFilename_tmp.parent.mkdir(parents=True, exist_ok=False)
93
133
 
94
- registrarRecordsTmpObject(pathFilenameTmp)
95
- return pathFilenameTmp
134
+ registrarRecordsTemporaryFilesystemObject(pathFilename_tmp.parent)
135
+ return pathFilename_tmp
96
136
 
97
137
  @pytest.fixture
98
- def pathCacheTesting(pathTmpTesting: Path) -> Generator[Path, Any, None]:
99
- """Temporarily replace the OEIS cache directory with a test directory."""
100
- import mapFolding.oeis as oeis
138
+ def pathCacheTesting(path_tmpTesting: Path) -> Generator[Path, Any, None]:
139
+ """Temporarily replace the OEIS cache directory with a test directory.
140
+
141
+ Parameters
142
+ ----------
143
+ pathTmpTesting : Path
144
+ Temporary directory path from the `pathTmpTesting` fixture.
145
+
146
+ Returns
147
+ -------
148
+ temporaryCachePath : Generator[Path, Any, None]
149
+ Context manager that provides the temporary cache path and restores original.
150
+
151
+ """
101
152
  pathCacheOriginal = oeis.pathCache
102
- oeis.pathCache = pathTmpTesting
103
- yield pathTmpTesting
153
+ oeis.pathCache = path_tmpTesting
154
+ yield path_tmpTesting
104
155
  oeis.pathCache = pathCacheOriginal
105
156
 
106
157
  @pytest.fixture
107
- def pathFilenameFoldsTotalTesting(pathTmpTesting: Path) -> Path:
108
- return pathTmpTesting.joinpath("foldsTotalTest.txt")
158
+ def pathFilenameFoldsTotalTesting(path_tmpTesting: Path) -> Path:
159
+ """Creates a temporary file path for folds total testing.
160
+
161
+ Parameters
162
+ ----------
163
+ pathTmpTesting : Path
164
+ Temporary directory path from the `pathTmpTesting` fixture.
165
+
166
+ Returns
167
+ -------
168
+ foldsTotalFilePath : Path
169
+ Path to a temporary file for testing folds total functionality.
170
+
171
+ """
172
+ return path_tmpTesting.joinpath("foldsTotalTest.txt")
109
173
 
110
174
  """
111
175
  Section: Fixtures"""
112
176
 
113
177
  @pytest.fixture(autouse=True)
114
178
  def setupWarningsAsErrors() -> Generator[None, Any, None]:
115
- """Convert all warnings to errors for all tests."""
116
- import warnings
179
+ """Convert all warnings to errors for all tests.
180
+
181
+ Returns
182
+ -------
183
+ contextManager : Generator[None, Any, None]
184
+ Context manager that configures warnings as errors and restores settings.
185
+
186
+ """
117
187
  warnings.filterwarnings("error")
118
188
  yield
119
189
  warnings.resetwarnings()
@@ -129,6 +199,17 @@ def oneTestCuzTestsOverwritingTests(oeisID_1random: str) -> tuple[int, ...]:
129
199
 
130
200
  The returned map shape is guaranteed to be computationally feasible for testing purposes,
131
201
  avoiding cases that would take excessive time to complete during test runs.
202
+
203
+ Parameters
204
+ ----------
205
+ oeisID_1random : str
206
+ Random OEIS sequence identifier from the `oeisID_1random` fixture.
207
+
208
+ Returns
209
+ -------
210
+ mapDimensions : tuple[int, ...]
211
+ Valid map dimensions suitable for testing fold counting operations.
212
+
132
213
  """
133
214
  while True:
134
215
  n = random.choice(settingsOEIS[oeisID_1random]['valuesTestValidation'])
@@ -143,8 +224,19 @@ def oneTestCuzTestsOverwritingTests(oeisID_1random: str) -> tuple[int, ...]:
143
224
 
144
225
  @pytest.fixture
145
226
  def mapShapeTestCountFolds(oeisID: str) -> tuple[int, ...]:
146
- """For each `oeisID` from the `pytest.fixture`, returns `listDimensions` from `valuesTestValidation`
147
- if `validateListDimensions` approves. Each `listDimensions` is suitable for testing counts."""
227
+ """For each `oeisID` from the `pytest.fixture`, returns `listDimensions` from `valuesTestValidation` if `validateListDimensions` approves. Each `listDimensions` is suitable for testing counts.
228
+
229
+ Parameters
230
+ ----------
231
+ oeisID : str
232
+ OEIS sequence identifier from the `oeisID` fixture.
233
+
234
+ Returns
235
+ -------
236
+ mapDimensions : tuple[int, ...]
237
+ Valid map dimensions suitable for testing fold counting operations.
238
+
239
+ """
148
240
  while True:
149
241
  n = random.choice(settingsOEIS[oeisID]['valuesTestValidation'])
150
242
  if n < 2:
@@ -158,9 +250,21 @@ def mapShapeTestCountFolds(oeisID: str) -> tuple[int, ...]:
158
250
 
159
251
  @pytest.fixture
160
252
  def mapShapeTestFunctionality(oeisID_1random: str) -> tuple[int, ...]:
161
- """To test functionality, get one `listDimensions` from `valuesTestValidation` if
162
- `validateListDimensions` approves. The algorithm can count the folds of the returned
163
- `listDimensions` in a short enough time suitable for testing."""
253
+ """To test functionality, get one `listDimensions` from `valuesTestValidation` if `validateListDimensions` approves.
254
+
255
+ The algorithm can count the folds of the returned `listDimensions` in a short enough time suitable for testing.
256
+
257
+ Parameters
258
+ ----------
259
+ oeisID_1random : str
260
+ Random OEIS sequence identifier from the `oeisID_1random` fixture.
261
+
262
+ Returns
263
+ -------
264
+ mapDimensions : tuple[int, ...]
265
+ Valid map dimensions that can be processed quickly for functional testing.
266
+
267
+ """
164
268
  while True:
165
269
  n = random.choice(settingsOEIS[oeisID_1random]['valuesTestValidation'])
166
270
  if n < 2:
@@ -174,20 +278,46 @@ def mapShapeTestFunctionality(oeisID_1random: str) -> tuple[int, ...]:
174
278
 
175
279
  @pytest.fixture
176
280
  def mapShapeTestParallelization(oeisID: str) -> tuple[int, ...]:
177
- """For each `oeisID` from the `pytest.fixture`, returns `listDimensions` from `valuesTestParallelization`"""
281
+ """For each `oeisID` from the `pytest.fixture`, returns `listDimensions` from `valuesTestParallelization`.
282
+
283
+ Parameters
284
+ ----------
285
+ oeisID : str
286
+ OEIS sequence identifier from the `oeisID` fixture.
287
+
288
+ Returns
289
+ -------
290
+ mapDimensions : tuple[int, ...]
291
+ Map dimensions suitable for testing parallelization features.
292
+
293
+ """
178
294
  n = random.choice(settingsOEIS[oeisID]['valuesTestParallelization'])
179
295
  return settingsOEIS[oeisID]['getMapShape'](n)
180
296
 
181
297
  @pytest.fixture
182
298
  def mockBenchmarkTimer() -> Generator[unittest.mock.MagicMock | unittest.mock.AsyncMock, Any, None]:
183
- """Mock time.perf_counter_ns for consistent benchmark timing."""
299
+ """Mock time.perf_counter_ns for consistent benchmark timing.
300
+
301
+ Returns
302
+ -------
303
+ mockTimer : Generator[unittest.mock.MagicMock | unittest.mock.AsyncMock, Any, None]
304
+ Mock timer that returns predictable timing values for testing benchmarks.
305
+
306
+ """
184
307
  with unittest.mock.patch('time.perf_counter_ns') as mockTimer:
185
308
  mockTimer.side_effect = [0, 1e9] # Start and end times for 1 second
186
309
  yield mockTimer
187
310
 
188
311
  @pytest.fixture
189
312
  def mockFoldingFunction() -> Callable[..., Callable[..., None]]:
190
- """Creates a mock function that simulates _countFolds behavior."""
313
+ """Creates a mock function that simulates _countFolds behavior.
314
+
315
+ Returns
316
+ -------
317
+ mockFactory : Callable[..., Callable[..., None]]
318
+ Factory function that creates mock folding functions with specified behavior.
319
+
320
+ """
191
321
  def make_mock(foldsValue: int, listDimensions: list[int]) -> Callable[..., None]:
192
322
  mock_array = makeDataContainer(2, numpy.int32)
193
323
  mock_array[0] = foldsValue
@@ -196,18 +326,39 @@ def mockFoldingFunction() -> Callable[..., Callable[..., None]]:
196
326
 
197
327
  def mock_countFolds(**keywordArguments: Any) -> None:
198
328
  keywordArguments['foldGroups'][:] = mock_array
199
- return None
200
329
 
201
330
  return mock_countFolds
202
331
  return make_mock
203
332
 
204
333
  @pytest.fixture(params=oeisIDsImplemented)
205
334
  def oeisID(request: pytest.FixtureRequest) -> Any:
335
+ """Parametrized fixture providing all implemented OEIS sequence identifiers.
336
+
337
+ (AI generated docstring)
338
+
339
+ Parameters
340
+ ----------
341
+ request : pytest.FixtureRequest
342
+ The pytest request object containing the current parameter value.
343
+
344
+ Returns
345
+ -------
346
+ sequenceIdentifier : Any
347
+ OEIS sequence identifier for testing across all implemented sequences.
348
+
349
+ """
206
350
  return request.param
207
351
 
208
352
  @pytest.fixture
209
353
  def oeisID_1random() -> str:
210
- """Return one random valid OEIS ID."""
354
+ """Return one random valid OEIS ID.
355
+
356
+ Returns
357
+ -------
358
+ randomSequenceIdentifier : str
359
+ Randomly selected OEIS sequence identifier from implemented sequences.
360
+
361
+ """
211
362
  return random.choice(oeisIDsImplemented)
212
363
 
213
364
  def uniformTestMessage(expected: Any, actual: Any, functionName: str, *arguments: Any) -> str:
@@ -219,13 +370,21 @@ def uniformTestMessage(expected: Any, actual: Any, functionName: str, *arguments
219
370
  test suite.
220
371
 
221
372
  Parameters
222
- expected: The value or exception type that was expected
223
- actual: The value or exception type that was actually received
224
- functionName: Name of the function being tested
225
- arguments: Arguments that were passed to the function
373
+ ----------
374
+ expected : Any
375
+ The value or exception type that was expected.
376
+ actual : Any
377
+ The value or exception type that was actually received.
378
+ functionName : str
379
+ Name of the function being tested.
380
+ arguments : Any
381
+ Arguments that were passed to the function.
226
382
 
227
383
  Returns
228
- formattedMessage: A formatted string showing the test context and comparison
384
+ -------
385
+ formattedMessage : str
386
+ A formatted string showing the test context and comparison.
387
+
229
388
  """
230
389
  return (f"\nTesting: `{functionName}({', '.join(str(parameter) for parameter in arguments)})`\n"
231
390
  f"Expected: {expected}\n"
@@ -243,9 +402,14 @@ def standardizedEqualToCallableReturn(expected: Any, functionTarget: Callable[..
243
402
  return value.
244
403
 
245
404
  Parameters
246
- expected: Expected return value or exception type
247
- functionTarget: The function to test
248
- arguments: Arguments to pass to the function
405
+ ----------
406
+ expected : Any
407
+ Expected return value or exception type.
408
+ functionTarget : Callable[..., Any]
409
+ The function to test.
410
+ arguments : Any
411
+ Arguments to pass to the function.
412
+
249
413
  """
250
414
  if type(expected) is type[Exception]:
251
415
  messageExpected = expected.__name__
@@ -264,13 +428,18 @@ def standardizedSystemExit(expected: str | int | Sequence[int], functionTarget:
264
428
  """Template for tests expecting SystemExit.
265
429
 
266
430
  Parameters
267
- expected: Exit code expectation:
268
- - "error": any non-zero exit code
269
- - "nonError": specifically zero exit code
270
- - int: exact exit code match
271
- - Sequence[int]: exit code must be one of these values
272
- functionTarget: The function to test
273
- arguments: Arguments to pass to the function
431
+ ----------
432
+ expected : str | int | Sequence[int]
433
+ Exit code expectation:
434
+ - "error": any non-zero exit code
435
+ - "nonError": specifically zero exit code
436
+ - int: exact exit code match
437
+ - Sequence[int]: exit code must be one of these values
438
+ functionTarget : Callable[..., Any]
439
+ The function to test.
440
+ arguments : Any
441
+ Arguments to pass to the function.
442
+
274
443
  """
275
444
  with pytest.raises(SystemExit) as exitInfo:
276
445
  functionTarget(*arguments)
@@ -1,5 +1,7 @@
1
1
  """Core computational verification and algorithm validation tests.
2
2
 
3
+ (AI generated docstring)
4
+
3
5
  This module validates the mathematical correctness of map folding computations and
4
6
  serves as the primary testing ground for new computational approaches. It's the most
5
7
  important module for users who create custom folding algorithms or modify existing ones.
@@ -26,10 +28,11 @@ which is useful if you're working with the code synthesis features of the packag
26
28
  from mapFolding import countFolds, getFoldsTotalKnown, oeisIDfor_n
27
29
  from mapFolding.dataBaskets import MapFoldingState
28
30
  from mapFolding.oeis import settingsOEIS
29
- from mapFolding.someAssemblyRequired.RecipeJob import RecipeJobTheorem2Numba
31
+ from mapFolding.someAssemblyRequired.RecipeJob import RecipeJobTheorem2
32
+ from mapFolding.someAssemblyRequired.makeAllModules import parametersNumbaLight
30
33
  from mapFolding.syntheticModules.initializeCount import initializeGroupsOfFolds
34
+ from mapFolding.tests.conftest import registrarRecordsTemporaryFilesystemObject, standardizedEqualToCallableReturn
31
35
  from pathlib import Path, PurePosixPath
32
- from tests.conftest import registrarRecordsTmpObject, standardizedEqualToCallableReturn
33
36
  from typing import Literal
34
37
  import importlib.util
35
38
  import multiprocessing
@@ -42,12 +45,22 @@ if __name__ == '__main__':
42
45
  def test_flowControl(mapShapeTestCountFolds: tuple[int, ...], flow: Literal['daoOfMapFolding', 'theorem2', 'theorem2numba']) -> None:
43
46
  """Validate that different computational flows produce identical results.
44
47
 
48
+ (AI generated docstring)
49
+
45
50
  This is the primary test for ensuring mathematical consistency across different
46
51
  algorithmic implementations. When adding a new computational approach, include
47
52
  it in the parametrized flow list to verify it produces correct results.
48
53
 
49
54
  The test compares the output of each flow against known correct values from
50
55
  OEIS sequences, ensuring that optimization techniques don't compromise accuracy.
56
+
57
+ Parameters
58
+ ----------
59
+ mapShapeTestCountFolds : tuple[int, ...]
60
+ The map shape dimensions to test fold counting for.
61
+ flow : Literal['daoOfMapFolding', 'theorem2', 'theorem2numba']
62
+ The computational flow algorithm to validate.
63
+
51
64
  """
52
65
  standardizedEqualToCallableReturn(getFoldsTotalKnown(mapShapeTestCountFolds), countFolds, None, None, None, None, mapShapeTestCountFolds, None, None, flow)
53
66
 
@@ -73,10 +86,12 @@ def test_aOFn_calculate_value(oeisID: str) -> None:
73
86
  for n in settingsOEIS[oeisID]['valuesTestValidation']:
74
87
  standardizedEqualToCallableReturn(settingsOEIS[oeisID]['valuesKnown'][n], oeisIDfor_n, oeisID, n)
75
88
 
76
- @pytest.mark.parametrize('pathFilenameTmpTesting', ['.py'], indirect=True)
77
- def test_writeJobNumba(oneTestCuzTestsOverwritingTests: tuple[int, ...], pathFilenameTmpTesting: Path) -> None:
89
+ @pytest.mark.parametrize('pathFilename_tmpTesting', ['.py'], indirect=True)
90
+ def test_writeJobNumba(oneTestCuzTestsOverwritingTests: tuple[int, ...], pathFilename_tmpTesting: Path) -> None:
78
91
  """Test dynamic code generation and execution for computational modules.
79
92
 
93
+ (AI generated docstring)
94
+
80
95
  This test validates the package's ability to generate, compile, and execute
81
96
  optimized computational code at runtime. It's essential for users working with
82
97
  the code synthesis features or implementing custom optimization strategies.
@@ -84,31 +99,38 @@ def test_writeJobNumba(oneTestCuzTestsOverwritingTests: tuple[int, ...], pathFil
84
99
  The test creates a complete computational module, executes it, and verifies
85
100
  that the generated code produces mathematically correct results. This pattern
86
101
  can be adapted for testing other dynamically generated computational approaches.
102
+
103
+ Parameters
104
+ ----------
105
+ oneTestCuzTestsOverwritingTests : tuple[int, ...]
106
+ The map shape dimensions for testing code generation.
107
+ pathFilename_tmpTesting : Path
108
+ The temporary file path for generated module testing.
109
+
87
110
  """
88
111
  from mapFolding.someAssemblyRequired.makeJobTheorem2Numba import makeJobNumba # noqa: PLC0415
89
112
  from mapFolding.someAssemblyRequired.toolkitNumba import SpicesJobNumba # noqa: PLC0415
90
113
  mapShape = oneTestCuzTestsOverwritingTests
91
- state = MapFoldingState(mapShape)
92
- state = initializeGroupsOfFolds(state)
114
+ state = initializeGroupsOfFolds(MapFoldingState(mapShape))
93
115
 
94
- pathFilenameModule = pathFilenameTmpTesting.absolute()
116
+ pathFilenameModule = pathFilename_tmpTesting.absolute()
95
117
  pathFilenameFoldsTotal = pathFilenameModule.with_suffix('.foldsTotalTesting')
96
- registrarRecordsTmpObject(pathFilenameFoldsTotal)
118
+ registrarRecordsTemporaryFilesystemObject(pathFilenameFoldsTotal)
97
119
 
98
- jobTest = RecipeJobTheorem2Numba(state
120
+ jobTest = RecipeJobTheorem2(state
99
121
  , pathModule=PurePosixPath(pathFilenameModule.parent)
100
122
  , moduleIdentifier=pathFilenameModule.stem
101
123
  , pathFilenameFoldsTotal=PurePosixPath(pathFilenameFoldsTotal))
102
- spices = SpicesJobNumba(useNumbaProgressBar=False)
124
+ spices = SpicesJobNumba(useNumbaProgressBar=False, parametersNumba=parametersNumbaLight)
103
125
  makeJobNumba(jobTest, spices)
104
126
 
105
127
  Don_Lapre_Road_to_Self_Improvement = importlib.util.spec_from_file_location("__main__", pathFilenameModule)
106
128
  if Don_Lapre_Road_to_Self_Improvement is None:
107
- msg = f"Failed to create module specification from {pathFilenameModule}"
108
- raise ImportError(msg)
129
+ message = f"Failed to create module specification from {pathFilenameModule}"
130
+ raise ImportError(message)
109
131
  if Don_Lapre_Road_to_Self_Improvement.loader is None:
110
- msg = f"Failed to get loader for module {pathFilenameModule}"
111
- raise ImportError(msg)
132
+ message = f"Failed to get loader for module {pathFilenameModule}"
133
+ raise ImportError(message)
112
134
  module = importlib.util.module_from_spec(Don_Lapre_Road_to_Self_Improvement)
113
135
 
114
136
  module.__name__ = "__main__"
@@ -21,23 +21,20 @@ stores computational results or adding new file formats.
21
21
 
22
22
  from contextlib import redirect_stdout
23
23
  from mapFolding import (
24
- getFilenameFoldsTotal, getPathFilenameFoldsTotal, getPathRootJobDEFAULT, saveFoldsTotal,
25
- validateListDimensions,
26
- )
24
+ getFilenameFoldsTotal, getPathFilenameFoldsTotal, getPathRootJobDEFAULT, saveFoldsTotal, validateListDimensions)
27
25
  from pathlib import Path
28
26
  import io
29
27
  import pytest
30
28
  import unittest.mock
31
29
 
32
- def test_saveFoldsTotal_fallback(pathTmpTesting: Path) -> None:
30
+ def test_saveFoldsTotal_fallback(path_tmpTesting: Path) -> None:
33
31
  foldsTotal = 123
34
- pathFilename = pathTmpTesting / "foldsTotal.txt"
35
- with unittest.mock.patch("pathlib.Path.write_text", side_effect=OSError("Simulated write failure")):
36
- with unittest.mock.patch("os.getcwd", return_value=str(pathTmpTesting)):
37
- capturedOutput = io.StringIO()
38
- with redirect_stdout(capturedOutput):
39
- saveFoldsTotal(pathFilename, foldsTotal)
40
- fallbackFiles = list(pathTmpTesting.glob("foldsTotalYO_*.txt"))
32
+ pathFilename = path_tmpTesting / "foldsTotal.txt"
33
+ with unittest.mock.patch("pathlib.Path.write_text", side_effect=OSError("Simulated write failure")), unittest.mock.patch("os.getcwd", return_value=str(path_tmpTesting)):
34
+ capturedOutput = io.StringIO()
35
+ with redirect_stdout(capturedOutput):
36
+ saveFoldsTotal(pathFilename, foldsTotal)
37
+ fallbackFiles = list(path_tmpTesting.glob("foldsTotalYO_*.txt"))
41
38
  assert len(fallbackFiles) == 1, "Fallback file was not created upon write failure."
42
39
 
43
40
  @pytest.mark.parametrize("listDimensions, expectedFilename", [
@@ -64,9 +61,9 @@ def test_getPathFilenameFoldsTotal_relativeFilename(mapShapeTestFunctionality: t
64
61
  assert pathFilenameFoldsTotal.is_absolute(), "Path should be absolute"
65
62
  assert pathFilenameFoldsTotal == getPathRootJobDEFAULT() / relativeFilename, "Relative path should be appended to default job root"
66
63
 
67
- def test_getPathFilenameFoldsTotal_createsDirs(pathTmpTesting: Path, mapShapeTestFunctionality: tuple[int, ...]) -> None:
64
+ def test_getPathFilenameFoldsTotal_createsDirs(path_tmpTesting: Path, mapShapeTestFunctionality: tuple[int, ...]) -> None:
68
65
  """Test that getPathFilenameFoldsTotal creates necessary directories."""
69
- nestedPath = pathTmpTesting / "deep/nested/structure"
66
+ nestedPath = path_tmpTesting / "deep/nested/structure"
70
67
  pathFilenameFoldsTotal = getPathFilenameFoldsTotal(mapShapeTestFunctionality, nestedPath)
71
68
  assert pathFilenameFoldsTotal.parent.exists(), "Parent directories should be created"
72
69
  assert pathFilenameFoldsTotal.parent.is_dir(), "Created path should be a directory"
@@ -26,19 +26,14 @@ which is crucial for maintaining package reliability in production environments.
26
26
 
27
27
  from contextlib import redirect_stdout
28
28
  from mapFolding.oeis import (
29
- clearOEIScache, getOEISids, getOEISidValues, OEIS_for_n, oeisIDfor_n, oeisIDsImplemented,
30
- settingsOEIS, validateOEISid,
31
- )
32
- from pathlib import Path
33
- from tests.conftest import standardizedEqualToCallableReturn, standardizedSystemExit
34
- from typing import Any, NoReturn
35
- from urllib.error import URLError
29
+ clearOEIScache, getOEISids, OEIS_for_n, oeisIDfor_n, oeisIDsImplemented, settingsOEIS, validateOEISid)
30
+ from mapFolding.tests.conftest import standardizedEqualToCallableReturn, standardizedSystemExit
31
+ from typing import Any
36
32
  import io
37
33
  import pytest
38
34
  import random
39
35
  import re as regex
40
36
  import unittest.mock
41
- import urllib.request
42
37
 
43
38
  @pytest.mark.parametrize("badID", ["A999999", " A999999 ", "A999999extra"])
44
39
  def test__validateOEISid_invalid_id(badID: str) -> None:
@@ -56,11 +51,11 @@ def test__validateOEISid_valid_id_case_insensitive(oeisID: str) -> None:
56
51
  standardizedEqualToCallableReturn(oeisID.upper(), validateOEISid, oeisID.swapcase())
57
52
 
58
53
  parameters_test_aOFn_invalid_n = [
59
- (-random.randint(1, 100), "randomNegative"),
54
+ (-random.randint(1, 100), "randomNegative"), # noqa: S311
60
55
  ("foo", "string"),
61
56
  (1.5, "float")
62
57
  ]
63
- badValues, badValuesIDs = zip(*parameters_test_aOFn_invalid_n)
58
+ badValues, badValuesIDs = zip(*parameters_test_aOFn_invalid_n, strict=True)
64
59
  @pytest.mark.parametrize("badN", badValues, ids=badValuesIDs)
65
60
  def test_aOFn_invalid_n(oeisID_1random: str, badN: Any) -> None:
66
61
  """Check that negative or non-integer n raises ValueError."""
@@ -87,15 +82,6 @@ def test_clearOEIScache(mock_unlink: unittest.mock.MagicMock, mock_exists: unitt
87
82
  mock_exists.assert_called_once()
88
83
  mock_unlink.assert_not_called()
89
84
 
90
- # Monkey tests
91
- # def testNetworkError(monkeypatch: pytest.MonkeyPatch, pathCacheTesting: Path) -> None:
92
- # """Test network error handling."""
93
- # def mockUrlopen(*args: Any, **kwargs: Any) -> NoReturn:
94
- # raise URLError("Network error")
95
-
96
- # monkeypatch.setattr(urllib.request, 'urlopen', mockUrlopen)
97
- # standardizedEqualToCallableReturn(URLError, getOEISidValues, next(iter(settingsOEIS)))
98
-
99
85
  # ===== Command Line Interface Tests =====
100
86
  def testHelpText() -> None:
101
87
  """Test that help text is complete and examples are valid."""
@@ -29,7 +29,7 @@ from collections.abc import Callable
29
29
  from hunterMakesPy import intInnit
30
30
  from hunterMakesPy.pytestForYourUse import PytestFor_intInnit, PytestFor_oopsieKwargsie
31
31
  from mapFolding import getLeavesTotal, setProcessorLimit, validateListDimensions
32
- from tests.conftest import standardizedEqualToCallableReturn
32
+ from mapFolding.tests.conftest import standardizedEqualToCallableReturn
33
33
  from typing import Any, Literal
34
34
  import multiprocessing
35
35
  import numba
@@ -60,11 +60,11 @@ import sys
60
60
  ([float('nan')], ValueError, ValueError), # NaN
61
61
  ([sys.maxsize, sys.maxsize], [sys.maxsize, sys.maxsize], (sys.maxsize, sys.maxsize)), # overflow protection
62
62
  (range(3, 7), [3, 4, 5, 6], (3, 4, 5, 6)), # range sequence type
63
- (tuple([3, 5, 7]), [3, 5, 7], (3, 5, 7)), # tuple sequence type
63
+ (tuple([3, 5, 7]), [3, 5, 7], (3, 5, 7)), # tuple sequence type # noqa: C409
64
64
  ])
65
- def test_listDimensionsAsParameter(listDimensions: None | list[str] | list[int] | list[float] | list[None] | list[bool] | list[list[int]] | list[complex] | range | tuple[int, ...],
66
- expected_intInnit: type[ValueError] | list[int] | type[TypeError],
67
- expected_validateListDimensions: type[ValueError] | type[NotImplementedError] | tuple[int, ...] | type[TypeError]) -> None:
65
+ def test_listDimensionsAsParameter(listDimensions: None | list[Any] | range | tuple[Any, ...]
66
+ , expected_intInnit: type[Any] | list[int]
67
+ , expected_validateListDimensions: type[Any] | tuple[int, ...]) -> None:
68
68
  """Test both validateListDimensions and getLeavesTotal with the same inputs."""
69
69
  standardizedEqualToCallableReturn(expected_intInnit, intInnit, listDimensions)
70
70
  standardizedEqualToCallableReturn(expected_validateListDimensions, validateListDimensions, listDimensions)
@@ -98,6 +98,6 @@ def testOopsieKwargsie(nameOfTest: str, callablePytest: Callable[[], None]) -> N
98
98
  (0, numba.get_num_threads()),
99
99
  (1, 1),
100
100
  ])
101
- def test_setCPUlimitNumba(CPUlimit: None | float | bool | Literal[4] | Literal[-2] | Literal[0] | Literal[1], expectedLimit: Any | int) -> None:
101
+ def test_setCPUlimitNumba(CPUlimit: Literal[4, -2, 0, 1] | None | float | bool, expectedLimit: Any | int) -> None:
102
102
  numba.set_num_threads(multiprocessing.cpu_count())
103
103
  standardizedEqualToCallableReturn(expectedLimit, setProcessorLimit, CPUlimit, 'numba')