mapFolding 0.12.1__py3-none-any.whl → 0.12.2__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 (34) hide show
  1. mapFolding/__init__.py +42 -18
  2. mapFolding/_theSSOT.py +137 -0
  3. mapFolding/basecamp.py +28 -18
  4. mapFolding/beDRY.py +21 -19
  5. mapFolding/dataBaskets.py +170 -18
  6. mapFolding/datatypes.py +109 -1
  7. mapFolding/filesystemToolkit.py +38 -33
  8. mapFolding/oeis.py +209 -93
  9. mapFolding/someAssemblyRequired/RecipeJob.py +120 -9
  10. mapFolding/someAssemblyRequired/__init__.py +35 -38
  11. mapFolding/someAssemblyRequired/_toolIfThis.py +78 -16
  12. mapFolding/someAssemblyRequired/_toolkitContainers.py +121 -43
  13. mapFolding/someAssemblyRequired/infoBooth.py +37 -2
  14. mapFolding/someAssemblyRequired/makeAllModules.py +712 -0
  15. mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +102 -39
  16. mapFolding/someAssemblyRequired/toolkitNumba.py +171 -19
  17. mapFolding/someAssemblyRequired/transformationTools.py +84 -40
  18. mapfolding-0.12.2.dist-info/METADATA +167 -0
  19. mapfolding-0.12.2.dist-info/RECORD +53 -0
  20. {mapfolding-0.12.1.dist-info → mapfolding-0.12.2.dist-info}/WHEEL +1 -1
  21. tests/__init__.py +28 -44
  22. tests/conftest.py +66 -61
  23. tests/test_computations.py +39 -82
  24. tests/test_filesystem.py +25 -1
  25. tests/test_oeis.py +30 -1
  26. tests/test_other.py +27 -0
  27. tests/test_tasks.py +31 -1
  28. mapFolding/someAssemblyRequired/Z0Z_makeAllModules.py +0 -433
  29. mapFolding/theSSOT.py +0 -34
  30. mapfolding-0.12.1.dist-info/METADATA +0 -184
  31. mapfolding-0.12.1.dist-info/RECORD +0 -53
  32. {mapfolding-0.12.1.dist-info → mapfolding-0.12.2.dist-info}/entry_points.txt +0 -0
  33. {mapfolding-0.12.1.dist-info → mapfolding-0.12.2.dist-info}/licenses/LICENSE +0 -0
  34. {mapfolding-0.12.1.dist-info → mapfolding-0.12.2.dist-info}/top_level.txt +0 -0
tests/test_oeis.py CHANGED
@@ -1,5 +1,34 @@
1
+ """OEIS (Online Encyclopedia of Integer Sequences) integration testing.
2
+
3
+ This module validates the package's integration with OEIS, ensuring that sequence
4
+ identification, value retrieval, and caching mechanisms work correctly. The OEIS
5
+ connection provides the mathematical foundation that validates computational results
6
+ against established mathematical knowledge.
7
+
8
+ These tests verify both the technical aspects of OEIS integration (network requests,
9
+ caching, error handling) and the mathematical correctness of sequence identification
10
+ and value mapping.
11
+
12
+ Key Testing Areas:
13
+ - OEIS sequence ID validation and normalization
14
+ - Network request handling and error recovery
15
+ - Local caching of sequence data for offline operation
16
+ - Command-line interface for OEIS sequence queries
17
+ - Mathematical consistency between local computations and OEIS values
18
+
19
+ The caching tests are particularly important for users working in environments with
20
+ limited network access, as they ensure the package can operate effectively offline
21
+ once sequence data has been retrieved.
22
+
23
+ Network error handling tests verify graceful degradation when OEIS is unavailable,
24
+ which is crucial for maintaining package reliability in production environments.
25
+ """
26
+
1
27
  from contextlib import redirect_stdout
2
- from mapFolding.oeis import oeisIDfor_n, getOEISids, clearOEIScache, getOEISidValues, OEIS_for_n, oeisIDsImplemented, settingsOEIS, validateOEISid
28
+ from mapFolding.oeis import (
29
+ clearOEIScache, getOEISids, getOEISidValues, OEIS_for_n, oeisIDfor_n, oeisIDsImplemented,
30
+ settingsOEIS, validateOEISid,
31
+ )
3
32
  from pathlib import Path
4
33
  from tests.conftest import standardizedEqualToCallableReturn, standardizedSystemExit
5
34
  from typing import Any, NoReturn
tests/test_other.py CHANGED
@@ -1,3 +1,30 @@
1
+ """Foundational utilities and data validation testing.
2
+
3
+ This module tests the core utility functions that support the mathematical
4
+ computations but aren't specific to any particular algorithm. These are the
5
+ building blocks that ensure data integrity and proper parameter handling
6
+ throughout the package.
7
+
8
+ The tests here validate fundamental operations like dimension validation,
9
+ processor limit configuration, and basic mathematical utilities. These
10
+ functions form the foundation that other modules build upon.
11
+
12
+ Key Testing Areas:
13
+ - Input validation and sanitization for map dimensions
14
+ - Processor limit configuration for parallel computations
15
+ - Mathematical utility functions from helper modules
16
+ - Edge case handling for boundary conditions
17
+ - Type system validation and error propagation
18
+
19
+ For users extending the package: these tests demonstrate proper input validation
20
+ patterns and show how to handle edge cases gracefully. The parametrized tests
21
+ provide examples of comprehensive boundary testing that you can adapt for your
22
+ own functions.
23
+
24
+ The integration with external utility modules (Z0Z_tools) shows how to test
25
+ dependencies while maintaining clear separation of concerns.
26
+ """
27
+
1
28
  from collections.abc import Callable
2
29
  from mapFolding import getLeavesTotal, setProcessorLimit, validateListDimensions
3
30
  from tests.conftest import standardizedEqualToCallableReturn
tests/test_tasks.py CHANGED
@@ -1,5 +1,35 @@
1
+ """Parallel processing and task distribution validation.
2
+
3
+ This module tests the package's parallel processing capabilities, ensuring that
4
+ computations can be effectively distributed across multiple processors while
5
+ maintaining mathematical accuracy. These tests are crucial for performance
6
+ optimization and scalability.
7
+
8
+ The task distribution system allows large computational problems to be broken
9
+ down into smaller chunks that can be processed concurrently. These tests verify
10
+ that the distribution logic works correctly and that results remain consistent
11
+ regardless of how the work is divided.
12
+
13
+ Key Testing Areas:
14
+ - Task division strategies for different computational approaches
15
+ - Processor limit configuration and enforcement
16
+ - Parallel execution consistency and correctness
17
+ - Resource management and concurrency control
18
+ - Error handling in multi-process environments
19
+
20
+ For users working with large-scale computations: these tests demonstrate how to
21
+ configure and validate parallel processing setups. The concurrency limit tests
22
+ show how to balance performance with system resource constraints.
23
+
24
+ The multiprocessing configuration (spawn method) is essential for cross-platform
25
+ compatibility and proper resource isolation between test processes.
26
+ """
27
+
1
28
  from collections.abc import Callable
2
- from mapFolding import countFolds, getTaskDivisions, setProcessorLimit, validateListDimensions, getLeavesTotal, getFoldsTotalKnown
29
+ from mapFolding import (
30
+ countFolds, getFoldsTotalKnown, getLeavesTotal, getTaskDivisions, setProcessorLimit,
31
+ validateListDimensions,
32
+ )
3
33
  from tests.conftest import standardizedEqualToCallableReturn
4
34
  from typing import Literal
5
35
  from Z0Z_tools.pytestForYourUse import PytestFor_defineConcurrencyLimit
@@ -1,433 +0,0 @@
1
- from astToolkit import (
2
- astModuleToIngredientsFunction,
3
- Be,
4
- ClassIsAndAttribute,
5
- DOT,
6
- extractClassDef,
7
- extractFunctionDef,
8
- Grab,
9
- IngredientsFunction,
10
- IngredientsModule,
11
- LedgerOfImports,
12
- Make,
13
- NodeChanger,
14
- NodeTourist,
15
- parseLogicalPath2astModule,
16
- parsePathFilename2astModule,
17
- str_nameDOTname,
18
- Then,
19
- )
20
- from astToolkit.transformationTools import inlineFunctionDef, removeUnusedParameters, write_astModule
21
- from collections.abc import Sequence
22
- from mapFolding import packageSettings
23
- from mapFolding.someAssemblyRequired import (
24
- DeReConstructField2ast,
25
- IfThis,
26
- raiseIfNone,
27
- ShatteredDataclass,
28
- sourceCallableDispatcherDEFAULT,
29
- )
30
- from mapFolding.someAssemblyRequired.infoBooth import algorithmSourceModuleDEFAULT, dataPackingModuleIdentifierDEFAULT, logicalPathInfixDEFAULT, sourceCallableIdentifierDEFAULT, theCountingIdentifierDEFAULT
31
- from mapFolding.someAssemblyRequired.toolkitNumba import decorateCallableWithNumba, parametersNumbaLight
32
- from mapFolding.someAssemblyRequired.transformationTools import (
33
- removeDataclassFromFunction,
34
- shatter_dataclassesDOTdataclass,
35
- unpackDataclassCallFunctionRepackDataclass,
36
- )
37
- from os import PathLike
38
- from pathlib import PurePath
39
- from typing import cast
40
- from Z0Z_tools import importLogicalPath2Callable
41
- import ast
42
- import dataclasses
43
-
44
- def findDataclass(ingredientsFunction: IngredientsFunction) -> tuple[str, str, str]:
45
- dataclassName: ast.expr = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.annotation)).captureLastMatch(ingredientsFunction.astFunctionDef))
46
- dataclassIdentifier: str = raiseIfNone(NodeTourist(Be.Name, Then.extractIt(DOT.id)).captureLastMatch(dataclassName))
47
- dataclassLogicalPathModule = None
48
- for moduleWithLogicalPath, listNameTuples in ingredientsFunction.imports.dictionaryImportFrom.items():
49
- for nameTuple in listNameTuples:
50
- if nameTuple[0] == dataclassIdentifier:
51
- dataclassLogicalPathModule = moduleWithLogicalPath
52
- break
53
- if dataclassLogicalPathModule:
54
- break
55
- dataclassInstanceIdentifier = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
56
- return raiseIfNone(dataclassLogicalPathModule), dataclassIdentifier, dataclassInstanceIdentifier
57
-
58
- def _getLogicalPath(packageName: str | None = None, logicalPathInfix: str | None = None, moduleIdentifier: str | None = None, *modules: str) -> str_nameDOTname:
59
- listLogicalPathParts: list[str] = []
60
- if packageName:
61
- listLogicalPathParts.append(packageName)
62
- if logicalPathInfix:
63
- listLogicalPathParts.append(logicalPathInfix)
64
- if moduleIdentifier:
65
- listLogicalPathParts.append(moduleIdentifier)
66
- if modules:
67
- listLogicalPathParts.extend(modules)
68
- logicalPath = '.'.join(listLogicalPathParts)
69
- return logicalPath
70
-
71
- def getModule(packageName: str | None = packageSettings.packageName, logicalPathInfix: str | None = logicalPathInfixDEFAULT, moduleIdentifier: str | None = algorithmSourceModuleDEFAULT) -> ast.Module:
72
- logicalPathSourceModule = _getLogicalPath(packageName, logicalPathInfix, moduleIdentifier)
73
- astModule = parseLogicalPath2astModule(logicalPathSourceModule)
74
- return astModule
75
-
76
- def _getPathFilename(pathRoot: PathLike[str] | PurePath | None = packageSettings.pathPackage, logicalPathInfix: PathLike[str] | PurePath | str | None = None, moduleIdentifier: str = '', fileExtension: str = packageSettings.fileExtension) -> PurePath:
77
- pathFilename = PurePath(moduleIdentifier + fileExtension)
78
- if logicalPathInfix:
79
- pathFilename = PurePath(logicalPathInfix, pathFilename)
80
- if pathRoot:
81
- pathFilename = PurePath(pathRoot, pathFilename)
82
- return pathFilename
83
-
84
- def makeInitializeGroupsOfFolds(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
85
- sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
86
- if callableIdentifier is None:
87
- callableIdentifier = sourceCallableIdentifier
88
- ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
89
- ingredientsFunction.astFunctionDef.name = callableIdentifier
90
-
91
- dataclassInstanceIdentifier = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
92
- theCountingIdentifier = theCountingIdentifierDEFAULT
93
-
94
- findThis = IfThis.isWhileAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
95
- doThat = Grab.testAttribute(Grab.andDoAllOf([Grab.opsAttribute(Then.replaceWith([ast.Eq()])), Grab.leftAttribute(Grab.attrAttribute(Then.replaceWith(theCountingIdentifier)))])) # pyright: ignore[reportArgumentType]
96
- NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef.body[0])
97
-
98
- ingredientsModule = IngredientsModule(ingredientsFunction)
99
- pathFilename = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
100
- write_astModule(ingredientsModule, pathFilename, packageSettings.packageName)
101
-
102
- return pathFilename
103
-
104
- def makeDaoOfMapFolding(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
105
- sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
106
- ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
107
-
108
- if callableIdentifier is None:
109
- callableIdentifier = sourceCallableIdentifier
110
- ingredientsFunction.astFunctionDef.name = callableIdentifier
111
-
112
- shatteredDataclass = shatter_dataclassesDOTdataclass(*findDataclass(ingredientsFunction))
113
-
114
- ingredientsFunction.imports.update(shatteredDataclass.imports)
115
- ingredientsFunction = removeDataclassFromFunction(ingredientsFunction, shatteredDataclass)
116
- ingredientsFunction = removeUnusedParameters(ingredientsFunction)
117
- ingredientsFunction = decorateCallableWithNumba(ingredientsFunction, parametersNumbaLight)
118
-
119
- ingredientsModule = IngredientsModule(ingredientsFunction)
120
-
121
- if sourceCallableDispatcher is not None:
122
-
123
- ingredientsFunctionDispatcher: IngredientsFunction = astModuleToIngredientsFunction(astModule, sourceCallableDispatcher)
124
- ingredientsFunctionDispatcher.imports.update(shatteredDataclass.imports)
125
- targetCallableIdentifier = ingredientsFunction.astFunctionDef.name
126
- ingredientsFunctionDispatcher = unpackDataclassCallFunctionRepackDataclass(ingredientsFunctionDispatcher, targetCallableIdentifier, shatteredDataclass)
127
- astTuple = raiseIfNone(NodeTourist(Be.Return, Then.extractIt(DOT.value)).captureLastMatch(ingredientsFunction.astFunctionDef))
128
- cast(ast.Tuple, astTuple).ctx = ast.Store()
129
-
130
- findThis = ClassIsAndAttribute.valueIs(ast.Assign, IfThis.isCallIdentifier(targetCallableIdentifier))
131
- doThat = Then.replaceWith(Make.Assign([astTuple], value=Make.Call(Make.Name(targetCallableIdentifier), cast(ast.Tuple, astTuple).elts)))
132
- changeAssignCallToTarget = NodeChanger(findThis, doThat)
133
- changeAssignCallToTarget.visit(ingredientsFunctionDispatcher.astFunctionDef)
134
-
135
- ingredientsModule.appendIngredientsFunction(ingredientsFunctionDispatcher)
136
-
137
- ingredientsModule.removeImportFromModule('numpy')
138
-
139
- pathFilename = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
140
-
141
- write_astModule(ingredientsModule, pathFilename, packageSettings.packageName)
142
-
143
- return pathFilename
144
-
145
- def makeDaoOfMapFoldingParallel(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
146
- sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
147
- if callableIdentifier is None:
148
- callableIdentifier = sourceCallableIdentifier
149
- ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
150
- ingredientsFunction.astFunctionDef.name = callableIdentifier
151
-
152
- dataclassName: ast.expr = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.annotation)).captureLastMatch(ingredientsFunction.astFunctionDef))
153
- dataclassIdentifier: str = raiseIfNone(NodeTourist(Be.Name, Then.extractIt(DOT.id)).captureLastMatch(dataclassName))
154
-
155
- dataclassLogicalPathModule = None
156
- for moduleWithLogicalPath, listNameTuples in ingredientsFunction.imports.dictionaryImportFrom.items():
157
- for nameTuple in listNameTuples:
158
- if nameTuple[0] == dataclassIdentifier:
159
- dataclassLogicalPathModule = moduleWithLogicalPath
160
- break
161
- if dataclassLogicalPathModule:
162
- break
163
- if dataclassLogicalPathModule is None: raise Exception
164
- dataclassInstanceIdentifier = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
165
- shatteredDataclass = shatter_dataclassesDOTdataclass(dataclassLogicalPathModule, dataclassIdentifier, dataclassInstanceIdentifier)
166
-
167
- # Start add the parallel state fields to the count function ================================================
168
- dataclassBaseFields = dataclasses.fields(importLogicalPath2Callable(dataclassLogicalPathModule, dataclassIdentifier)) # pyright: ignore [reportArgumentType]
169
- dataclassIdentifierParallel = 'Parallel' + dataclassIdentifier
170
- dataclassFieldsParallel = dataclasses.fields(importLogicalPath2Callable(dataclassLogicalPathModule, dataclassIdentifierParallel)) # pyright: ignore [reportArgumentType]
171
- onlyParallelFields = [field for field in dataclassFieldsParallel if field.name not in [fieldBase.name for fieldBase in dataclassBaseFields]]
172
-
173
- Official_fieldOrder: list[str] = []
174
- dictionaryDeReConstruction: dict[str, DeReConstructField2ast] = {}
175
-
176
- dataclassClassDef = extractClassDef(parseLogicalPath2astModule(dataclassLogicalPathModule), dataclassIdentifierParallel)
177
- if not isinstance(dataclassClassDef, ast.ClassDef): raise ValueError(f"I could not find `{dataclassIdentifierParallel = }` in `{dataclassLogicalPathModule = }`.")
178
-
179
- for aField in onlyParallelFields:
180
- Official_fieldOrder.append(aField.name)
181
- dictionaryDeReConstruction[aField.name] = DeReConstructField2ast(dataclassLogicalPathModule, dataclassClassDef, dataclassInstanceIdentifier, aField)
182
-
183
- shatteredDataclassParallel = ShatteredDataclass(
184
- countingVariableAnnotation=shatteredDataclass.countingVariableAnnotation,
185
- countingVariableName=shatteredDataclass.countingVariableName,
186
- field2AnnAssign={**shatteredDataclass.field2AnnAssign, **{dictionaryDeReConstruction[field].name: dictionaryDeReConstruction[field].astAnnAssignConstructor for field in Official_fieldOrder}},
187
- Z0Z_field2AnnAssign={**shatteredDataclass.Z0Z_field2AnnAssign, **{dictionaryDeReConstruction[field].name: dictionaryDeReConstruction[field].Z0Z_hack for field in Official_fieldOrder}},
188
- list_argAnnotated4ArgumentsSpecification=shatteredDataclass.list_argAnnotated4ArgumentsSpecification + [dictionaryDeReConstruction[field].ast_argAnnotated for field in Official_fieldOrder],
189
- list_keyword_field__field4init=shatteredDataclass.list_keyword_field__field4init + [dictionaryDeReConstruction[field].ast_keyword_field__field for field in Official_fieldOrder if dictionaryDeReConstruction[field].init],
190
- listAnnotations=shatteredDataclass.listAnnotations + [dictionaryDeReConstruction[field].astAnnotation for field in Official_fieldOrder],
191
- listName4Parameters=shatteredDataclass.listName4Parameters + [dictionaryDeReConstruction[field].astName for field in Official_fieldOrder],
192
- listUnpack=shatteredDataclass.listUnpack + [Make.AnnAssign(dictionaryDeReConstruction[field].astName, dictionaryDeReConstruction[field].astAnnotation, dictionaryDeReConstruction[field].ast_nameDOTname) for field in Official_fieldOrder],
193
- map_stateDOTfield2Name={**shatteredDataclass.map_stateDOTfield2Name, **{dictionaryDeReConstruction[field].ast_nameDOTname: dictionaryDeReConstruction[field].astName for field in Official_fieldOrder}},
194
- )
195
- shatteredDataclassParallel.fragments4AssignmentOrParameters = Make.Tuple(shatteredDataclassParallel.listName4Parameters, ast.Store())
196
- shatteredDataclassParallel.repack = Make.Assign([Make.Name(dataclassInstanceIdentifier)], value=Make.Call(Make.Name(dataclassIdentifierParallel), list_keyword=shatteredDataclassParallel.list_keyword_field__field4init))
197
- shatteredDataclassParallel.signatureReturnAnnotation = Make.Subscript(Make.Name('tuple'), Make.Tuple(shatteredDataclassParallel.listAnnotations))
198
-
199
- shatteredDataclassParallel.imports.update(*(dictionaryDeReConstruction[field].ledger for field in Official_fieldOrder))
200
- shatteredDataclassParallel.imports.addImportFrom_asStr(dataclassLogicalPathModule, dataclassIdentifierParallel)
201
- shatteredDataclassParallel.imports.update(shatteredDataclass.imports)
202
- shatteredDataclassParallel.imports.removeImportFrom(dataclassLogicalPathModule, dataclassIdentifier)
203
-
204
- # End add the parallel state fields to the count function ================================================
205
-
206
- ingredientsFunction.imports.update(shatteredDataclassParallel.imports)
207
- ingredientsFunction = removeDataclassFromFunction(ingredientsFunction, shatteredDataclassParallel)
208
-
209
- # Start add the parallel logic to the count function ================================================
210
-
211
- findThis = ClassIsAndAttribute.testIs(ast.While, ClassIsAndAttribute.leftIs(ast.Compare, IfThis.isNameIdentifier('leafConnectee')))
212
- doThat = Then.extractIt(DOT.body)
213
- captureCountGapsCodeBlock: NodeTourist[ast.While, Sequence[ast.stmt]] = NodeTourist(findThis, doThat)
214
- countGapsCodeBlock = raiseIfNone(captureCountGapsCodeBlock.captureLastMatch(ingredientsFunction.astFunctionDef))
215
-
216
- thisIsMyTaskIndexCodeBlock = ast.If(ast.BoolOp(ast.Or()
217
- , values=[ast.Compare(ast.Name('leaf1ndex'), ops=[ast.NotEq()], comparators=[ast.Name('taskDivisions')])
218
- , ast.Compare(ast.BinOp(ast.Name('leafConnectee'), op=ast.Mod(), right=ast.Name('taskDivisions')), ops=[ast.Eq()], comparators=[ast.Name('taskIndex')])])
219
- , body=list(countGapsCodeBlock[0:-1]))
220
-
221
- countGapsCodeBlockNew: list[ast.stmt] = [thisIsMyTaskIndexCodeBlock, countGapsCodeBlock[-1]]
222
-
223
- doThat = Grab.bodyAttribute(Then.replaceWith(countGapsCodeBlockNew))
224
- NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
225
-
226
- # End add the parallel logic to the count function ================================================
227
-
228
- ingredientsFunction = removeUnusedParameters(ingredientsFunction)
229
-
230
- ingredientsFunction = decorateCallableWithNumba(ingredientsFunction, parametersNumbaLight)
231
-
232
- # Start unpack/repack the dataclass function ================================================
233
- sourceCallableIdentifier = sourceCallableDispatcherDEFAULT
234
-
235
- unRepackDataclass: IngredientsFunction = astModuleToIngredientsFunction(astModule, sourceCallableIdentifier)
236
- unRepackDataclass.astFunctionDef.name = 'unRepack' + dataclassIdentifierParallel
237
- unRepackDataclass.imports.update(shatteredDataclassParallel.imports)
238
- findThis = ClassIsAndAttribute.annotationIs(ast.arg, IfThis.isNameIdentifier(dataclassIdentifier)) # pyright: ignore[reportArgumentType, reportUnknownVariableType, reportCallIssue]
239
- doThat = Grab.annotationAttribute(Grab.idAttribute(Then.replaceWith(dataclassIdentifierParallel))) # pyright: ignore[reportArgumentType]
240
- NodeChanger(findThis, doThat).visit(unRepackDataclass.astFunctionDef) # pyright: ignore[reportUnknownArgumentType]
241
- unRepackDataclass.astFunctionDef.returns = Make.Name(dataclassIdentifierParallel)
242
- targetCallableIdentifier = ingredientsFunction.astFunctionDef.name
243
- unRepackDataclass = unpackDataclassCallFunctionRepackDataclass(unRepackDataclass, targetCallableIdentifier, shatteredDataclassParallel)
244
-
245
- astTuple = raiseIfNone(NodeTourist(Be.Return, Then.extractIt(DOT.value)).captureLastMatch(ingredientsFunction.astFunctionDef))
246
- cast(ast.Tuple, astTuple).ctx = ast.Store()
247
- findThis = ClassIsAndAttribute.valueIs(ast.Assign, IfThis.isCallIdentifier(targetCallableIdentifier))
248
- doThat = Then.replaceWith(Make.Assign([astTuple], value=Make.Call(Make.Name(targetCallableIdentifier), cast(ast.Tuple, astTuple).elts)))
249
- changeAssignCallToTarget = NodeChanger(findThis, doThat)
250
- changeAssignCallToTarget.visit(unRepackDataclass.astFunctionDef)
251
-
252
- ingredientsDoTheNeedful: IngredientsFunction = IngredientsFunction(
253
- astFunctionDef = ast.FunctionDef(name='doTheNeedful'
254
- , args=ast.arguments(args=[ast.arg('state', annotation=ast.Name(dataclassIdentifierParallel)), ast.arg('concurrencyLimit', annotation=ast.Name('int'))])
255
- , body=[ast.Assign(targets=[ast.Name('stateParallel', ctx=ast.Store())], value=ast.Call(func=ast.Name('deepcopy'), args=[ast.Name('state')]))
256
- , ast.AnnAssign(target=ast.Name('listStatesParallel', ctx=ast.Store()), annotation=ast.Subscript(value=ast.Name('list'), slice=ast.Name(dataclassIdentifierParallel)), value=ast.BinOp(left=ast.List(elts=[ast.Name('stateParallel')]), op=ast.Mult(), right=ast.Attribute(value=ast.Name('stateParallel'), attr='taskDivisions')), simple=1)
257
- , ast.AnnAssign(target=ast.Name('groupsOfFoldsTotal', ctx=ast.Store()), annotation=ast.Name('int'), value=ast.Constant(value=0), simple=1)
258
-
259
- , ast.AnnAssign(target=ast.Name('dictionaryConcurrency', ctx=ast.Store()), annotation=ast.Subscript(value=ast.Name('dict'), slice=ast.Tuple(elts=[ast.Name('int'), ast.Subscript(value=ast.Name('ConcurrentFuture'), slice=ast.Name(dataclassIdentifierParallel))])), value=ast.Dict(), simple=1)
260
- , ast.With(items=[ast.withitem(context_expr=ast.Call(func=ast.Name('ProcessPoolExecutor'), args=[ast.Name('concurrencyLimit')]), optional_vars=ast.Name('concurrencyManager', ctx=ast.Store()))]
261
- , body=[ast.For(target=ast.Name('indexSherpa', ctx=ast.Store()), iter=ast.Call(func=ast.Name('range'), args=[ast.Attribute(value=ast.Name('stateParallel'), attr='taskDivisions')])
262
- , body=[ast.Assign(targets=[ast.Name('state', ctx=ast.Store())], value=ast.Call(func=ast.Name('deepcopy'), args=[ast.Name('stateParallel')]))
263
- , ast.Assign(targets=[ast.Attribute(value=ast.Name('state'), attr='taskIndex', ctx=ast.Store())], value=ast.Name('indexSherpa'))
264
- , ast.Assign(targets=[ast.Subscript(value=ast.Name('dictionaryConcurrency'), slice=ast.Name('indexSherpa'), ctx=ast.Store())], value=ast.Call(func=ast.Attribute(value=ast.Name('concurrencyManager'), attr='submit'), args=[ast.Name(unRepackDataclass.astFunctionDef.name), ast.Name('state')]))])
265
- , ast.For(target=ast.Name('indexSherpa', ctx=ast.Store()), iter=ast.Call(func=ast.Name('range'), args=[ast.Attribute(value=ast.Name('stateParallel'), attr='taskDivisions')])
266
- , body=[ast.Assign(targets=[ast.Subscript(value=ast.Name('listStatesParallel'), slice=ast.Name('indexSherpa'), ctx=ast.Store())], value=ast.Call(func=ast.Attribute(value=ast.Subscript(value=ast.Name('dictionaryConcurrency'), slice=ast.Name('indexSherpa')), attr='result')))
267
- , ast.AugAssign(target=ast.Name('groupsOfFoldsTotal', ctx=ast.Store()), op=ast.Add(), value=ast.Attribute(value=ast.Subscript(value=ast.Name('listStatesParallel'), slice=ast.Name('indexSherpa')), attr='groupsOfFolds'))])])
268
-
269
- , ast.AnnAssign(target=ast.Name('foldsTotal', ctx=ast.Store()), annotation=ast.Name('int'), value=ast.BinOp(left=ast.Name('groupsOfFoldsTotal'), op=ast.Mult(), right=ast.Attribute(value=ast.Name('stateParallel'), attr='leavesTotal')), simple=1)
270
- , ast.Return(value=ast.Tuple(elts=[ast.Name('foldsTotal'), ast.Name('listStatesParallel')]))]
271
- , returns=ast.Subscript(value=ast.Name('tuple'), slice=ast.Tuple(elts=[ast.Name('int'), ast.Subscript(value=ast.Name('list'), slice=ast.Name(dataclassIdentifierParallel))])))
272
- , imports = LedgerOfImports(Make.Module([ast.ImportFrom(module='concurrent.futures', names=[ast.alias(name='Future', asname='ConcurrentFuture'), ast.alias(name='ProcessPoolExecutor')], level=0),
273
- ast.ImportFrom(module='copy', names=[ast.alias(name='deepcopy')], level=0),
274
- ast.ImportFrom(module='multiprocessing', names=[ast.alias(name='set_start_method', asname='multiprocessing_set_start_method')], level=0),])
275
- )
276
- )
277
-
278
- ingredientsModule = IngredientsModule([ingredientsFunction, unRepackDataclass, ingredientsDoTheNeedful]
279
- , prologue = Make.Module([ast.If(test=ast.Compare(left=ast.Name('__name__'), ops=[ast.Eq()], comparators=[ast.Constant(value='__main__')]), body=[ast.Expr(value=ast.Call(func=ast.Name('multiprocessing_set_start_method'), args=[ast.Constant(value='spawn')]))])])
280
- )
281
- ingredientsModule.removeImportFromModule('numpy')
282
-
283
- pathFilename = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
284
-
285
- write_astModule(ingredientsModule, pathFilename, packageSettings.packageName)
286
- return pathFilename
287
-
288
- def makeTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
289
- sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
290
- if callableIdentifier is None:
291
- callableIdentifier = sourceCallableIdentifier
292
- ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
293
- ingredientsFunction.astFunctionDef.name = callableIdentifier
294
-
295
- dataclassInstanceIdentifier = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
296
-
297
- findThis = IfThis.isWhileAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
298
- doThat = Grab.testAttribute(Grab.comparatorsAttribute(Then.replaceWith([Make.Constant(4)]))) # pyright: ignore[reportArgumentType]
299
- NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
300
-
301
- findThis = IfThis.isIfAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
302
- doThat = Then.extractIt(DOT.body)
303
- insertLeaf = NodeTourist(findThis, doThat).captureLastMatch(ingredientsFunction.astFunctionDef)
304
- findThis = IfThis.isIfAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
305
- doThat = Then.replaceWith(insertLeaf)
306
- NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
307
-
308
- findThis = IfThis.isAttributeNamespaceIdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
309
- doThat = Then.removeIt
310
- NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
311
-
312
- findThis = IfThis.isAttributeNamespaceIdentifierLessThanOrEqual0(dataclassInstanceIdentifier, 'leaf1ndex')
313
- doThat = Then.removeIt
314
- NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
315
-
316
- theCountingIdentifier = theCountingIdentifierDEFAULT
317
- doubleTheCount = Make.AugAssign(Make.Attribute(ast.Name(dataclassInstanceIdentifier), theCountingIdentifier), ast.Mult(), Make.Constant(2))
318
- findThis = Be.Return
319
- doThat = Then.insertThisAbove([doubleTheCount])
320
- NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
321
-
322
- ingredientsModule = IngredientsModule(ingredientsFunction)
323
-
324
- if sourceCallableDispatcher is not None:
325
- raise NotImplementedError('sourceCallableDispatcher is not implemented yet')
326
-
327
- pathFilename = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
328
-
329
- write_astModule(ingredientsModule, pathFilename, packageSettings.packageName)
330
-
331
- return pathFilename
332
-
333
- def trimTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
334
- sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
335
- if callableIdentifier is None:
336
- callableIdentifier = sourceCallableIdentifier
337
- ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
338
- ingredientsFunction.astFunctionDef.name = callableIdentifier
339
-
340
- dataclassInstanceIdentifier = raiseIfNone(NodeTourist(Be.arg, Then.extractIt(DOT.arg)).captureLastMatch(ingredientsFunction.astFunctionDef))
341
-
342
- findThis = IfThis.isIfUnaryNotAttributeNamespaceIdentifier(dataclassInstanceIdentifier, 'dimensionsUnconstrained')
343
- doThat = Then.removeIt
344
- NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
345
-
346
- ingredientsModule = IngredientsModule(ingredientsFunction)
347
- ingredientsModule.removeImportFromModule('numpy')
348
-
349
- pathFilename = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
350
-
351
- write_astModule(ingredientsModule, pathFilename, packageSettings.packageName)
352
-
353
- return pathFilename
354
-
355
- def numbaOnTheorem2(astModule: ast.Module, moduleIdentifier: str, callableIdentifier: str | None = None, logicalPathInfix: PathLike[str] | PurePath | str | None = None, sourceCallableDispatcher: str | None = None) -> PurePath:
356
- sourceCallableIdentifier = sourceCallableIdentifierDEFAULT
357
- if callableIdentifier is None:
358
- callableIdentifier = sourceCallableIdentifier
359
- ingredientsFunction = IngredientsFunction(inlineFunctionDef(sourceCallableIdentifier, astModule), LedgerOfImports(astModule))
360
- ingredientsFunction.astFunctionDef.name = callableIdentifier
361
-
362
- shatteredDataclass = shatter_dataclassesDOTdataclass(*findDataclass(ingredientsFunction))
363
-
364
- ingredientsFunction.imports.update(shatteredDataclass.imports)
365
- ingredientsFunction = removeDataclassFromFunction(ingredientsFunction, shatteredDataclass)
366
- ingredientsFunction = removeUnusedParameters(ingredientsFunction)
367
- ingredientsFunction = decorateCallableWithNumba(ingredientsFunction, parametersNumbaLight)
368
-
369
- ingredientsModule = IngredientsModule(ingredientsFunction)
370
- ingredientsModule.removeImportFromModule('numpy')
371
-
372
- pathFilename = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
373
-
374
- write_astModule(ingredientsModule, pathFilename, packageSettings.packageName)
375
-
376
- return pathFilename
377
-
378
- def makeUnRePackDataclass(astImportFrom: ast.ImportFrom) -> None:
379
- callableIdentifierHARDCODED: str = 'sequential'
380
-
381
- algorithmSourceModule = algorithmSourceModuleDEFAULT
382
- sourceCallableIdentifier = sourceCallableDispatcherDEFAULT
383
- logicalPathSourceModule = '.'.join([packageSettings.packageName, algorithmSourceModule])
384
-
385
- logicalPathInfix = logicalPathInfixDEFAULT
386
- moduleIdentifier = dataPackingModuleIdentifierDEFAULT
387
- callableIdentifier = callableIdentifierHARDCODED
388
-
389
- ingredientsFunction: IngredientsFunction = astModuleToIngredientsFunction(parseLogicalPath2astModule(logicalPathSourceModule), sourceCallableIdentifier)
390
- ingredientsFunction.astFunctionDef.name = callableIdentifier
391
-
392
- shatteredDataclass = shatter_dataclassesDOTdataclass(*findDataclass(ingredientsFunction))
393
-
394
- ingredientsFunction.imports.update(shatteredDataclass.imports)
395
- ingredientsFunction.imports.addAst(astImportFrom)
396
- targetCallableIdentifier = astImportFrom.names[0].name
397
- ingredientsFunction = raiseIfNone(unpackDataclassCallFunctionRepackDataclass(ingredientsFunction, targetCallableIdentifier, shatteredDataclass))
398
- targetFunctionDef = raiseIfNone(extractFunctionDef(parseLogicalPath2astModule(raiseIfNone(astImportFrom.module)), targetCallableIdentifier))
399
- astTuple = raiseIfNone(NodeTourist(Be.Return, Then.extractIt(DOT.value)).captureLastMatch(targetFunctionDef))
400
- cast(ast.Tuple, astTuple).ctx = ast.Store()
401
-
402
- findThis = ClassIsAndAttribute.valueIs(ast.Assign, IfThis.isCallIdentifier(targetCallableIdentifier))
403
- doThat = Then.replaceWith(Make.Assign([astTuple], value=Make.Call(Make.Name(targetCallableIdentifier), cast(ast.Tuple, astTuple).elts)))
404
- NodeChanger(findThis, doThat).visit(ingredientsFunction.astFunctionDef)
405
-
406
- ingredientsModule = IngredientsModule(ingredientsFunction)
407
- ingredientsModule.removeImportFromModule('numpy')
408
-
409
- pathFilename = _getPathFilename(packageSettings.pathPackage, logicalPathInfix, moduleIdentifier)
410
-
411
- write_astModule(ingredientsModule, pathFilename, packageSettings.packageName)
412
-
413
- if __name__ == '__main__':
414
- astModule = getModule(logicalPathInfix=None)
415
- makeInitializeGroupsOfFolds(astModule, 'initializeCount', 'initializeGroupsOfFolds', logicalPathInfixDEFAULT)
416
-
417
- astModule = getModule(logicalPathInfix=None)
418
- pathFilename = makeDaoOfMapFolding(astModule, 'daoOfMapFolding', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
419
-
420
- astModule = getModule(logicalPathInfix=None)
421
- pathFilename = makeDaoOfMapFoldingParallel(astModule, 'countParallel', None, logicalPathInfixDEFAULT, sourceCallableDispatcherDEFAULT)
422
-
423
- astModule = getModule(logicalPathInfix=None)
424
- pathFilename = makeTheorem2(astModule, 'theorem2', None, logicalPathInfixDEFAULT, None)
425
-
426
- astModule = parsePathFilename2astModule(pathFilename)
427
- pathFilename = trimTheorem2(astModule, 'theorem2Trimmed', None, logicalPathInfixDEFAULT, None)
428
-
429
- astModule = parsePathFilename2astModule(pathFilename)
430
- pathFilename = numbaOnTheorem2(astModule, 'theorem2Numba', None, logicalPathInfixDEFAULT, None)
431
-
432
- astImportFrom = Make.ImportFrom(_getLogicalPath(packageSettings.packageName, logicalPathInfixDEFAULT, 'theorem2Numba'), list_alias=[Make.alias(sourceCallableIdentifierDEFAULT)])
433
- makeUnRePackDataclass(astImportFrom)
mapFolding/theSSOT.py DELETED
@@ -1,34 +0,0 @@
1
- from importlib import import_module as importlib_import_module
2
- from inspect import getfile as inspect_getfile
3
- from pathlib import Path
4
- from tomli import load as tomli_load
5
- import dataclasses
6
-
7
- packageNamePACKAGING_HARDCODED = "mapFolding"
8
- concurrencyPackageHARDCODED = 'multiprocessing'
9
-
10
- # Evaluate When Packaging
11
- # https://github.com/hunterhogan/mapFolding/issues/18
12
- try:
13
- packageNamePACKAGING: str = tomli_load(Path("../pyproject.toml").open('rb'))["project"]["name"]
14
- except Exception:
15
- packageNamePACKAGING = packageNamePACKAGING_HARDCODED
16
-
17
- # Evaluate When Installing
18
- # https://github.com/hunterhogan/mapFolding/issues/18
19
- def getPathPackageINSTALLING() -> Path:
20
- pathPackage: Path = Path(inspect_getfile(importlib_import_module(packageNamePACKAGING)))
21
- if pathPackage.is_file():
22
- pathPackage = pathPackage.parent
23
- return pathPackage
24
-
25
- @dataclasses.dataclass
26
- class PackageSettings:
27
- fileExtension: str = dataclasses.field(default='.py', metadata={'evaluateWhen': 'installing'})
28
- packageName: str = dataclasses.field(default = packageNamePACKAGING, metadata={'evaluateWhen': 'packaging'})
29
- pathPackage: Path = dataclasses.field(default_factory=getPathPackageINSTALLING, metadata={'evaluateWhen': 'installing'})
30
- concurrencyPackage: str | None = None
31
- """Package to use for concurrent execution (e.g., 'multiprocessing', 'numba')."""
32
-
33
- concurrencyPackage = concurrencyPackageHARDCODED
34
- packageSettings = PackageSettings(concurrencyPackage=concurrencyPackage)