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
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from tests.conftest import *
|
|
3
|
+
import importlib.util
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
def test_algorithmSourceParallel(listDimensionsTestParallelization: List[int], foldsTotalKnown: Dict[Tuple[int, ...], int], useAlgorithmSourceDispatcher: None) -> None:
|
|
7
|
+
standardizedEqualTo(foldsTotalKnown[tuple(listDimensionsTestParallelization)], countFolds, listDimensionsTestParallelization, None, 'maximum')
|
|
8
|
+
|
|
9
|
+
def test_algorithmSourceSequential(listDimensionsTestCountFolds: List[int], foldsTotalKnown: Dict[Tuple[int, ...], int], useAlgorithmSourceDispatcher: None) -> None:
|
|
10
|
+
standardizedEqualTo(foldsTotalKnown[tuple(listDimensionsTestCountFolds)], countFolds, listDimensionsTestCountFolds)
|
|
11
|
+
|
|
12
|
+
def test_aOFn_calculate_value(oeisID: str) -> None:
|
|
13
|
+
for n in settingsOEIS[oeisID]['valuesTestValidation']:
|
|
14
|
+
standardizedEqualTo(settingsOEIS[oeisID]['valuesKnown'][n], oeisIDfor_n, oeisID, n)
|
|
15
|
+
|
|
16
|
+
# Python doesn't want me to test this
|
|
17
|
+
# @pytest.mark.parametrize('pathFilenameTmpTesting', ['.py'], indirect=True)
|
|
18
|
+
# def test_writeJobNumba(listDimensionsTestCountFolds: List[int], foldsTotalKnown: Dict[Tuple[int, ...], int], pathFilenameTmpTesting: Path) -> None:
|
|
19
|
+
# from mapFolding.syntheticModules import numba_countSequential
|
|
20
|
+
# algorithmSourceHARDCODED: ModuleType = numba_countSequential
|
|
21
|
+
# algorithmSource = algorithmSourceHARDCODED
|
|
22
|
+
# pathFilenameModule = writeJobNumba(listDimensionsTestCountFolds, algorithmSource, pathFilenameWriteJob=pathFilenameTmpTesting.absolute())
|
|
23
|
+
|
|
24
|
+
# Don_Lapre_Road_to_Self_Improvement = importlib.util.spec_from_file_location("__main__", pathFilenameModule)
|
|
25
|
+
# if Don_Lapre_Road_to_Self_Improvement is None:
|
|
26
|
+
# raise ImportError(f"Failed to create module specification from {pathFilenameModule}")
|
|
27
|
+
# if Don_Lapre_Road_to_Self_Improvement.loader is None:
|
|
28
|
+
# raise ImportError(f"Failed to get loader for module {pathFilenameModule}")
|
|
29
|
+
# module = importlib.util.module_from_spec(Don_Lapre_Road_to_Self_Improvement)
|
|
30
|
+
|
|
31
|
+
# module.__name__ = "__main__"
|
|
32
|
+
# Don_Lapre_Road_to_Self_Improvement.loader.exec_module(module)
|
|
33
|
+
|
|
34
|
+
# pathFilenameFoldsTotal = getPathFilenameFoldsTotal(listDimensionsTestCountFolds)
|
|
35
|
+
# standardizedEqualTo(str(foldsTotalKnown[tuple(listDimensionsTestCountFolds)]), pathFilenameFoldsTotal.read_text().strip)
|
|
36
|
+
|
|
37
|
+
# def test_makeFlowNumbaOptimized(pathTmpTesting: Path, useThisDispatcher):
|
|
38
|
+
# def test_makeFlowNumbaOptimized(useThisDispatcher):
|
|
39
|
+
# """To get this to work:
|
|
40
|
+
# walk_up=True doesn't work on 3.10, so that has to go
|
|
41
|
+
# the _logical_ import must be in the logical path of the package
|
|
42
|
+
# fuck python
|
|
43
|
+
# """
|
|
44
|
+
# listCallablesInlineHARDCODED: List[str] = ['countInitialize', 'countParallel', 'countSequential']
|
|
45
|
+
# listCallablesInline = listCallablesInlineHARDCODED
|
|
46
|
+
# callableDispatcher = True
|
|
47
|
+
# algorithmSource = None
|
|
48
|
+
# relativePathWrite = None
|
|
49
|
+
# # relativePathWrite = pathTmpTesting.absolute().relative_to(getPathPackage(), walk_up=True)
|
|
50
|
+
# formatFilenameWrite = "pytest_{callableTarget}"
|
|
51
|
+
# listSynthesizedModules: List[youOughtaKnow] = makeFlowNumbaOptimized(listCallablesInline, callableDispatcher, algorithmSource, relativePathWrite, formatFilenameWrite)
|
|
52
|
+
# for stuff in listSynthesizedModules:
|
|
53
|
+
# registrarRecordsTmpObject(stuff.pathFilenameForMe)
|
|
54
|
+
# if stuff.callableSynthesized not in listCallablesInline:
|
|
55
|
+
# dispatcherSynthetic: youOughtaKnow = stuff
|
|
56
|
+
# if not dispatcherSynthetic: raise FREAKOUT
|
|
57
|
+
# # dispatcherSynthetic: youOughtaKnow = next(filter(lambda x: x.callableSynthesized not in listCallablesInline, listSynthesizedModules))
|
|
58
|
+
|
|
59
|
+
# # Import the synthetic dispatcher module to get the callable
|
|
60
|
+
# dispatcherSpec = importlib.util.spec_from_file_location(
|
|
61
|
+
# dispatcherSynthetic.callableSynthesized,
|
|
62
|
+
# dispatcherSynthetic.pathFilenameForMe
|
|
63
|
+
# )
|
|
64
|
+
# if dispatcherSpec is None:
|
|
65
|
+
# raise ImportError(f"Failed to create module specification from {dispatcherSynthetic.pathFilenameForMe}")
|
|
66
|
+
# if dispatcherSpec.loader is None:
|
|
67
|
+
# raise ImportError(f"Failed to get loader for module {dispatcherSynthetic.pathFilenameForMe}")
|
|
68
|
+
|
|
69
|
+
# dispatcherModule = importlib.util.module_from_spec(dispatcherSpec)
|
|
70
|
+
# dispatcherSpec.loader.exec_module(dispatcherModule)
|
|
71
|
+
# callableDispatcherSynthetic = getattr(dispatcherModule, dispatcherSynthetic.callableSynthesized)
|
|
72
|
+
|
|
73
|
+
# useThisDispatcher(callableDispatcherSynthetic)
|
|
74
|
+
|
|
75
|
+
# def test_syntheticSequential(listDimensionsTestCountFolds: List[int], foldsTotalKnown: Dict[Tuple[int, ...], int]):
|
|
76
|
+
# standardizedEqualTo(foldsTotalKnown[tuple(listDimensionsTestCountFolds)], countFolds, listDimensionsTestCountFolds)
|
|
77
|
+
|
|
78
|
+
# def test_syntheticParallel(listDimensionsTestParallelization: List[int], foldsTotalKnown: Dict[Tuple[int, ...], int]):
|
|
79
|
+
# standardizedEqualTo(foldsTotalKnown[tuple(listDimensionsTestParallelization)], countFolds, listDimensionsTestParallelization, None, 'maximum')
|
tests/test_oeis.py
CHANGED
|
@@ -2,7 +2,6 @@ from contextlib import redirect_stdout
|
|
|
2
2
|
from datetime import datetime, timedelta
|
|
3
3
|
from mapFolding.oeis import _getFilenameOEISbFile, _getOEISidValues, _parseBFileOEIS, _validateOEISid, _getOEISidInformation
|
|
4
4
|
from tests.conftest import *
|
|
5
|
-
from typing import NoReturn
|
|
6
5
|
from urllib.error import URLError
|
|
7
6
|
import io
|
|
8
7
|
import os
|
|
@@ -15,127 +14,119 @@ import unittest.mock
|
|
|
15
14
|
import urllib
|
|
16
15
|
import urllib.request
|
|
17
16
|
|
|
18
|
-
def test_algorithmSourceSequential(oeisID: str, useAlgorithmDirectly: None) -> None:
|
|
19
|
-
for n in settingsOEIS[oeisID]['valuesTestValidation']:
|
|
20
|
-
standardizedEqualTo(settingsOEIS[oeisID]['valuesKnown'][n], oeisIDfor_n, oeisID, n)
|
|
21
|
-
|
|
22
|
-
def test_aOFn_calculate_value(oeisID: str) -> None:
|
|
23
|
-
for n in settingsOEIS[oeisID]['valuesTestValidation']:
|
|
24
|
-
standardizedEqualTo(settingsOEIS[oeisID]['valuesKnown'][n], oeisIDfor_n, oeisID, n)
|
|
25
|
-
|
|
26
17
|
@pytest.mark.parametrize("badID", ["A999999", " A999999 ", "A999999extra"])
|
|
27
18
|
def test__validateOEISid_invalid_id(badID: str) -> None:
|
|
28
|
-
|
|
19
|
+
standardizedEqualTo(KeyError, _validateOEISid, badID)
|
|
29
20
|
|
|
30
21
|
def test__validateOEISid_partially_valid(oeisID_1random: str) -> None:
|
|
31
|
-
|
|
22
|
+
standardizedEqualTo(KeyError, _validateOEISid, f"{oeisID_1random}extra")
|
|
32
23
|
|
|
33
24
|
def test__validateOEISid_valid_id(oeisID: str) -> None:
|
|
34
|
-
|
|
25
|
+
standardizedEqualTo(oeisID, _validateOEISid, oeisID)
|
|
35
26
|
|
|
36
27
|
def test__validateOEISid_valid_id_case_insensitive(oeisID: str) -> None:
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
standardizedEqualTo(oeisID.upper(), _validateOEISid, oeisID.lower())
|
|
29
|
+
standardizedEqualTo(oeisID.upper(), _validateOEISid, oeisID.upper())
|
|
30
|
+
standardizedEqualTo(oeisID.upper(), _validateOEISid, oeisID.swapcase())
|
|
40
31
|
|
|
41
32
|
parameters_test_aOFn_invalid_n = [
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
33
|
+
# (2, "ok"), # test the test template
|
|
34
|
+
(-random.randint(1, 100), "randomNegative"),
|
|
35
|
+
("foo", "string"),
|
|
36
|
+
(1.5, "float")
|
|
46
37
|
]
|
|
47
38
|
badValues, badValuesIDs = zip(*parameters_test_aOFn_invalid_n)
|
|
48
39
|
@pytest.mark.parametrize("badN", badValues, ids=badValuesIDs)
|
|
49
40
|
def test_aOFn_invalid_n(oeisID_1random: str, badN: Any) -> None:
|
|
50
|
-
|
|
51
|
-
|
|
41
|
+
"""Check that negative or non-integer n raises ValueError."""
|
|
42
|
+
standardizedEqualTo(ValueError, oeisIDfor_n, oeisID_1random, badN)
|
|
52
43
|
|
|
53
44
|
def test_aOFn_zeroDim_A001418() -> None:
|
|
54
|
-
|
|
45
|
+
standardizedEqualTo(ArithmeticError, oeisIDfor_n, 'A001418', 0)
|
|
55
46
|
|
|
56
47
|
# ===== OEIS Cache Tests =====
|
|
57
48
|
@pytest.mark.parametrize("cacheExists", [True, False])
|
|
58
49
|
@unittest.mock.patch('pathlib.Path.exists')
|
|
59
50
|
@unittest.mock.patch('pathlib.Path.unlink')
|
|
60
51
|
def test_clearOEIScache(mock_unlink: unittest.mock.MagicMock, mock_exists: unittest.mock.MagicMock, cacheExists: bool) -> None:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
52
|
+
"""Test OEIS cache clearing with both existing and non-existing cache."""
|
|
53
|
+
mock_exists.return_value = cacheExists
|
|
54
|
+
clearOEIScache()
|
|
55
|
+
|
|
56
|
+
if cacheExists:
|
|
57
|
+
# Each OEIS ID has two cache files
|
|
58
|
+
expected_calls = len(settingsOEIS) * 2
|
|
59
|
+
assert mock_unlink.call_count == expected_calls
|
|
60
|
+
mock_unlink.assert_has_calls([unittest.mock.call(missing_ok=True)] * expected_calls)
|
|
61
|
+
else:
|
|
62
|
+
mock_exists.assert_called_once()
|
|
63
|
+
mock_unlink.assert_not_called()
|
|
73
64
|
|
|
74
65
|
def testNetworkError(monkeypatch: pytest.MonkeyPatch, pathCacheTesting: pathlib.Path) -> None:
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
66
|
+
"""Test network error handling."""
|
|
67
|
+
def mockUrlopen(*args: Any, **kwargs: Any) -> NoReturn:
|
|
68
|
+
raise URLError("Network error")
|
|
78
69
|
|
|
79
|
-
|
|
80
|
-
|
|
70
|
+
monkeypatch.setattr(urllib.request, 'urlopen', mockUrlopen)
|
|
71
|
+
standardizedEqualTo(URLError, _getOEISidValues, next(iter(settingsOEIS)))
|
|
81
72
|
|
|
82
73
|
# ===== Command Line Interface Tests =====
|
|
83
74
|
def testHelpText() -> None:
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
75
|
+
"""Test that help text is complete and examples are valid."""
|
|
76
|
+
outputStream = io.StringIO()
|
|
77
|
+
with redirect_stdout(outputStream):
|
|
78
|
+
getOEISids()
|
|
88
79
|
|
|
89
|
-
|
|
80
|
+
helpText = outputStream.getvalue()
|
|
90
81
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
82
|
+
# Verify content
|
|
83
|
+
for oeisID in oeisIDsImplemented:
|
|
84
|
+
assert oeisID in helpText
|
|
85
|
+
assert settingsOEIS[oeisID]['description'] in helpText
|
|
95
86
|
|
|
96
|
-
|
|
87
|
+
# Extract and verify examples
|
|
97
88
|
|
|
98
|
-
|
|
99
|
-
|
|
89
|
+
cliMatch = regex.search(r'OEIS_for_n (\w+) (\d+)', helpText)
|
|
90
|
+
pythonMatch = regex.search(r"oeisIDfor_n\('(\w+)', (\d+)\)", helpText)
|
|
100
91
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
92
|
+
assert cliMatch and pythonMatch, "Help text missing examples"
|
|
93
|
+
oeisID, n = pythonMatch.groups()
|
|
94
|
+
n = int(n)
|
|
104
95
|
|
|
105
|
-
|
|
106
|
-
|
|
96
|
+
# Verify CLI and Python examples use same values
|
|
97
|
+
assert cliMatch.groups() == (oeisID, str(n)), "CLI and Python examples inconsistent"
|
|
107
98
|
|
|
108
|
-
|
|
109
|
-
|
|
99
|
+
# Verify the example works
|
|
100
|
+
expectedValue = oeisIDfor_n(oeisID, n)
|
|
110
101
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
102
|
+
# Test CLI execution of the example
|
|
103
|
+
with unittest.mock.patch('sys.argv', ['OEIS_for_n', oeisID, str(n)]):
|
|
104
|
+
outputStream = io.StringIO()
|
|
105
|
+
with redirect_stdout(outputStream):
|
|
106
|
+
OEIS_for_n()
|
|
107
|
+
standardizedEqualTo(expectedValue, lambda: int(outputStream.getvalue().strip().split()[0]))
|
|
117
108
|
|
|
118
109
|
def testCLI_InvalidInputs() -> None:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
110
|
+
"""Test CLI error handling."""
|
|
111
|
+
testCases = [
|
|
112
|
+
(['OEIS_for_n'], "missing arguments"),
|
|
113
|
+
(['OEIS_for_n', 'A999999', '1'], "invalid OEIS ID"),
|
|
114
|
+
(['OEIS_for_n', 'A001415', '-1'], "negative n"),
|
|
115
|
+
(['OEIS_for_n', 'A001415', 'abc'], "non-integer n"),
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
for arguments, testID in testCases:
|
|
119
|
+
with unittest.mock.patch('sys.argv', arguments):
|
|
120
|
+
standardizedSystemExit("error", OEIS_for_n)
|
|
130
121
|
|
|
131
122
|
def testCLI_HelpFlag() -> None:
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
123
|
+
"""Verify --help output contains required information."""
|
|
124
|
+
with unittest.mock.patch('sys.argv', ['OEIS_for_n', '--help']):
|
|
125
|
+
outputStream = io.StringIO()
|
|
126
|
+
with redirect_stdout(outputStream):
|
|
127
|
+
standardizedSystemExit("nonError", OEIS_for_n)
|
|
128
|
+
|
|
129
|
+
helpOutput = outputStream.getvalue()
|
|
130
|
+
assert "Available OEIS sequences:" in helpOutput
|
|
131
|
+
assert "Usage examples:" in helpOutput
|
|
132
|
+
assert all(oeisID in helpOutput for oeisID in oeisIDsImplemented)
|