mapFolding 0.8.4__py3-none-any.whl → 0.8.6__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 (36) hide show
  1. mapFolding/__init__.py +10 -6
  2. mapFolding/basecamp.py +3 -3
  3. mapFolding/beDRY.py +241 -68
  4. mapFolding/oeis.py +41 -26
  5. mapFolding/reference/hunterNumba.py +1 -1
  6. mapFolding/someAssemblyRequired/__init__.py +16 -15
  7. mapFolding/someAssemblyRequired/_theTypes.py +31 -13
  8. mapFolding/someAssemblyRequired/_tool_Make.py +13 -5
  9. mapFolding/someAssemblyRequired/_tool_Then.py +12 -5
  10. mapFolding/someAssemblyRequired/_toolboxAntecedents.py +131 -99
  11. mapFolding/someAssemblyRequired/_toolboxContainers.py +92 -15
  12. mapFolding/someAssemblyRequired/_toolboxPython.py +17 -31
  13. mapFolding/someAssemblyRequired/getLLVMforNoReason.py +2 -2
  14. mapFolding/someAssemblyRequired/newInliner.py +22 -0
  15. mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +65 -116
  16. mapFolding/someAssemblyRequired/toolboxNumba.py +364 -0
  17. mapFolding/someAssemblyRequired/transformationTools.py +262 -41
  18. mapFolding/syntheticModules/numbaCount_doTheNeedful.py +0 -1
  19. mapFolding/theSSOT.py +30 -33
  20. mapFolding/{filesystem.py → toolboxFilesystem.py} +90 -25
  21. {mapfolding-0.8.4.dist-info → mapfolding-0.8.6.dist-info}/METADATA +3 -2
  22. mapfolding-0.8.6.dist-info/RECORD +47 -0
  23. tests/conftest.py +30 -31
  24. tests/test_computations.py +8 -7
  25. tests/test_filesystem.py +2 -2
  26. tests/test_other.py +2 -2
  27. tests/test_tasks.py +3 -3
  28. mapFolding/noHomeYet.py +0 -32
  29. mapFolding/someAssemblyRequired/ingredientsNumba.py +0 -199
  30. mapFolding/someAssemblyRequired/synthesizeNumbaFlow.py +0 -156
  31. mapFolding/someAssemblyRequired/transformDataStructures.py +0 -235
  32. mapfolding-0.8.4.dist-info/RECORD +0 -49
  33. {mapfolding-0.8.4.dist-info → mapfolding-0.8.6.dist-info}/WHEEL +0 -0
  34. {mapfolding-0.8.4.dist-info → mapfolding-0.8.6.dist-info}/entry_points.txt +0 -0
  35. {mapfolding-0.8.4.dist-info → mapfolding-0.8.6.dist-info}/licenses/LICENSE +0 -0
  36. {mapfolding-0.8.4.dist-info → mapfolding-0.8.6.dist-info}/top_level.txt +0 -0
@@ -7,9 +7,10 @@ circular imports while providing reusable data structures.
7
7
  """
8
8
  from collections import defaultdict
9
9
  from collections.abc import Sequence
10
- from mapFolding.someAssemblyRequired import ast_Identifier, be, ifThis, Make, parseLogicalPath2astModule, str_nameDOTname
11
- from mapFolding.theSSOT import callableDispatcherHARDCODED, raiseIfNoneGitHubIssueNumber3, The
10
+ from mapFolding.someAssemblyRequired import ImaAnnotationType, ast_Identifier, be, Make, parseLogicalPath2astModule, str_nameDOTname
11
+ from mapFolding.theSSOT import callableDispatcherHARDCODED, The
12
12
  from pathlib import Path, PurePosixPath
13
+ from typing import Literal
13
14
  from Z0Z_tools import updateExtendPolishDictionaryLists
14
15
  import ast
15
16
  import dataclasses
@@ -36,11 +37,45 @@ class LedgerOfImports:
36
37
  for alias in astImport____.names:
37
38
  self.dictionaryImportFrom[astImport____.module].append((alias.name, alias.asname))
38
39
 
39
- def addImport_asStr(self, moduleIdentifier: str_nameDOTname) -> None:
40
- self.listImport.append(moduleIdentifier)
41
-
42
- def addImportFrom_asStr(self, moduleIdentifier: ast_Identifier, name: ast_Identifier, asname: ast_Identifier | None = None) -> None:
43
- self.dictionaryImportFrom[moduleIdentifier].append((name, asname))
40
+ def addImport_asStr(self, moduleWithLogicalPath: str_nameDOTname) -> None:
41
+ self.listImport.append(moduleWithLogicalPath)
42
+
43
+ # def addImportFrom_asStr(self, moduleWithLogicalPath: str_nameDOTname, name: ast_Identifier, asname: ast_Identifier | None = None) -> None:
44
+ # self.dictionaryImportFrom[moduleWithLogicalPath].append((name, asname))
45
+
46
+ def addImportFrom_asStr(self, moduleWithLogicalPath: str_nameDOTname, name: ast_Identifier, asname: ast_Identifier | None = None) -> None:
47
+ if moduleWithLogicalPath not in self.dictionaryImportFrom:
48
+ self.dictionaryImportFrom[moduleWithLogicalPath] = []
49
+ self.dictionaryImportFrom[moduleWithLogicalPath].append((name, asname))
50
+
51
+ def removeImportFromModule(self, moduleWithLogicalPath: str_nameDOTname) -> None:
52
+ self.removeImportFrom(moduleWithLogicalPath, None, None)
53
+ """Remove all imports from a specific module."""
54
+
55
+ def removeImportFrom(self, moduleWithLogicalPath: str_nameDOTname, name: ast_Identifier | None, asname: ast_Identifier | None = None) -> None:
56
+ if moduleWithLogicalPath is None:
57
+ raise SyntaxError(f"I received `{moduleWithLogicalPath = }`, but it must be the name of a module.")
58
+ if moduleWithLogicalPath in self.dictionaryImportFrom:
59
+ """
60
+ name, asname Meaning
61
+ ast_Identifier, ast_Identifier : remove exact matches
62
+ ast_Identifier, None : remove exact matches
63
+ None, ast_Identifier : remove all matches for asname and if entry_asname is None remove name == ast_Identifier
64
+ None, None : remove all matches for the module
65
+ """
66
+ if name is None and asname is None:
67
+ # Remove all entries for the module
68
+ self.dictionaryImportFrom.pop(moduleWithLogicalPath)
69
+ else:
70
+ if name is None:
71
+ self.dictionaryImportFrom[moduleWithLogicalPath] = [(entry_name, entry_asname) for entry_name, entry_asname in self.dictionaryImportFrom[moduleWithLogicalPath]
72
+ if not (entry_asname == asname) and not (entry_asname is None and entry_name == asname)]
73
+ else:
74
+ # Remove exact matches for the module
75
+ self.dictionaryImportFrom[moduleWithLogicalPath] = [(entry_name, entry_asname) for entry_name, entry_asname in self.dictionaryImportFrom[moduleWithLogicalPath]
76
+ if not (entry_name == name and entry_asname == asname)]
77
+ if not self.dictionaryImportFrom[moduleWithLogicalPath]:
78
+ self.dictionaryImportFrom.pop(moduleWithLogicalPath)
44
79
 
45
80
  def exportListModuleIdentifiers(self) -> list[ast_Identifier]:
46
81
  listModuleIdentifiers: list[ast_Identifier] = list(self.dictionaryImportFrom.keys())
@@ -49,13 +84,14 @@ class LedgerOfImports:
49
84
 
50
85
  def makeList_ast(self) -> list[ast.ImportFrom | ast.Import]:
51
86
  listImportFrom: list[ast.ImportFrom] = []
52
- for moduleIdentifier, listOfNameTuples in sorted(self.dictionaryImportFrom.items()):
87
+ for moduleWithLogicalPath, listOfNameTuples in sorted(self.dictionaryImportFrom.items()):
53
88
  listOfNameTuples = sorted(list(set(listOfNameTuples)), key=lambda nameTuple: nameTuple[0])
54
89
  list_alias: list[ast.alias] = []
55
90
  for name, asname in listOfNameTuples:
56
91
  list_alias.append(Make.alias(name, asname))
57
- listImportFrom.append(Make.ImportFrom(moduleIdentifier, list_alias))
58
- list_astImport: list[ast.Import] = [Make.Import(moduleIdentifier) for moduleIdentifier in sorted(set(self.listImport))]
92
+ if list_alias:
93
+ listImportFrom.append(Make.ImportFrom(moduleWithLogicalPath, list_alias))
94
+ list_astImport: list[ast.Import] = [Make.Import(moduleWithLogicalPath) for moduleWithLogicalPath in sorted(set(self.listImport))]
59
95
  return listImportFrom + list_astImport
60
96
 
61
97
  def update(self, *fromLedger: 'LedgerOfImports') -> None:
@@ -158,6 +194,19 @@ class IngredientsModule:
158
194
  else:
159
195
  raise ValueError(f"I received `{type(allegedIngredientsFunction) = }`, but I can only accept `{IngredientsFunction}`.")
160
196
 
197
+ def removeImportFromModule(self, moduleWithLogicalPath: str_nameDOTname) -> None:
198
+ self.removeImportFrom(moduleWithLogicalPath, None, None)
199
+ """Remove all imports from a specific module."""
200
+
201
+ def removeImportFrom(self, moduleWithLogicalPath: str_nameDOTname, name: ast_Identifier | None, asname: ast_Identifier | None = None) -> None:
202
+ """
203
+ This method modifies all `LedgerOfImports` in this `IngredientsModule` and all `IngredientsFunction` in `listIngredientsFunctions`.
204
+ It is not a "blacklist", so the import from could be added after this modification.
205
+ """
206
+ self.imports.removeImportFrom(moduleWithLogicalPath, name, asname)
207
+ for ingredientsFunction in self.listIngredientsFunctions:
208
+ ingredientsFunction.imports.removeImportFrom(moduleWithLogicalPath, name, asname)
209
+
161
210
  @property
162
211
  def list_astImportImportFrom(self) -> list[ast.Import | ast.ImportFrom]:
163
212
  """List of `ast.Import` and `ast.ImportFrom` statements."""
@@ -299,8 +348,36 @@ theLogicalPathModuleDispatcherSynthetic: str = '.'.join([The.packageName, The.mo
299
348
  if self.callableDispatcher!=callableDispatcherHARDCODED:
300
349
  print(f"fyi: `{self.callableDispatcher=}` but\n\t`{callableDispatcherHARDCODED=}`.")
301
350
 
302
- def astModuleToIngredientsFunction(astModule: ast.AST, identifierFunctionDef: ast_Identifier) -> IngredientsFunction:
303
- from mapFolding.someAssemblyRequired import extractFunctionDef
304
- astFunctionDef = extractFunctionDef(astModule, identifierFunctionDef)
305
- if not astFunctionDef: raise raiseIfNoneGitHubIssueNumber3
306
- return IngredientsFunction(astFunctionDef, LedgerOfImports(astModule))
351
+ dummyAssign = Make.Assign([Make.Name("dummyTarget")], Make.Constant(None))
352
+ dummySubscript = Make.Subscript(Make.Name("dummy"), Make.Name("slice"))
353
+ dummyTuple = Make.Tuple([Make.Name("dummyElement")])
354
+
355
+ @dataclasses.dataclass
356
+ class ShatteredDataclass:
357
+ countingVariableAnnotation: ImaAnnotationType
358
+ """Type annotation for the counting variable extracted from the dataclass."""
359
+ countingVariableName: ast.Name
360
+ """AST name node representing the counting variable identifier."""
361
+ field2AnnAssign: dict[ast_Identifier, ast.AnnAssign] = dataclasses.field(default_factory=dict)
362
+ """Maps field names to their corresponding AST call expressions."""
363
+ Z0Z_field2AnnAssign: dict[ast_Identifier, tuple[ast.AnnAssign, str]] = dataclasses.field(default_factory=dict)
364
+ fragments4AssignmentOrParameters: ast.Tuple = dummyTuple
365
+ """AST tuple used as target for assignment to capture returned fragments."""
366
+ ledger: LedgerOfImports = dataclasses.field(default_factory=LedgerOfImports)
367
+ """Import records for the dataclass and its constituent parts."""
368
+ list_argAnnotated4ArgumentsSpecification: list[ast.arg] = dataclasses.field(default_factory=list)
369
+ """Function argument nodes with annotations for parameter specification."""
370
+ list_keyword_field__field4init: list[ast.keyword] = dataclasses.field(default_factory=list)
371
+ """Keyword arguments for dataclass initialization with field=field format."""
372
+ listAnnotations: list[ImaAnnotationType] = dataclasses.field(default_factory=list)
373
+ """Type annotations for each dataclass field."""
374
+ listName4Parameters: list[ast.Name] = dataclasses.field(default_factory=list)
375
+ """Name nodes for each dataclass field used as function parameters."""
376
+ listUnpack: list[ast.AnnAssign] = dataclasses.field(default_factory=list)
377
+ """Annotated assignment statements to extract fields from dataclass."""
378
+ map_stateDOTfield2Name: dict[ast.expr, ast.Name] = dataclasses.field(default_factory=dict)
379
+ """Maps AST expressions to Name nodes for find-replace operations."""
380
+ repack: ast.Assign = dummyAssign
381
+ """AST assignment statement that reconstructs the original dataclass instance."""
382
+ signatureReturnAnnotation: ast.Subscript = dummySubscript
383
+ """tuple-based return type annotation for function definitions."""
@@ -1,57 +1,43 @@
1
- from collections.abc import Callable
1
+ from collections.abc import Callable, Sequence
2
2
  from inspect import getsource as inspect_getsource
3
- from mapFolding.someAssemblyRequired import ast_Identifier, str_nameDOTname
3
+ from mapFolding.someAssemblyRequired import ast_Identifier, str_nameDOTname, 个
4
4
  from os import PathLike
5
5
  from pathlib import Path, PurePath
6
6
  from types import ModuleType
7
- from typing import Any, Literal
7
+ from typing import Any, cast, Generic, TypeGuard
8
8
  import ast
9
9
  import importlib
10
10
  import importlib.util
11
11
 
12
12
  # TODO Identify the logic that narrows the type and can help the user during static type checking.
13
13
 
14
- class NodeTourist(ast.NodeVisitor):
15
- def __init__(self, findThis, doThat): # type: ignore
14
+ class NodeTourist(ast.NodeVisitor, Generic[个]):
15
+ def __init__(self, findThis: Callable[[个], TypeGuard[个] | bool], doThat: Callable[[个], 个 | None]) -> None:
16
16
  self.findThis = findThis
17
17
  self.doThat = doThat
18
- self.nodeCaptured = None
18
+ self.nodeCaptured: 个 | None = None
19
19
 
20
- def visit(self, node): # type: ignore
20
+ def visit(self, node: 个) -> None: # pyright: ignore [reportGeneralTypeIssues]
21
21
  if self.findThis(node):
22
- nodeActionReturn = self.doThat(node) # type: ignore
22
+ nodeActionReturn = self.doThat(node)
23
23
  if nodeActionReturn is not None:
24
- self.nodeCaptured = nodeActionReturn # type: ignore
25
- self.generic_visit(node)
26
-
27
- def captureLastMatch(self, node): # type: ignore
28
- """Capture the last matched node that produces a non-None result.
29
-
30
- This method traverses the entire tree starting at the given node
31
- and returns the last non-None value produced by applying doThat
32
- to a matching node. It will continue traversing after finding a match,
33
- and the value captured can be replaced by later matches.
34
-
35
- Parameters:
36
- node: The AST node to start traversal from
24
+ self.nodeCaptured = nodeActionReturn
25
+ self.generic_visit(cast(ast.AST, node))
37
26
 
38
- Returns:
39
- The result of applying doThat to the last matching node that returned
40
- a non-None value, or None if no match found or all matches returned None
41
- """
27
+ def captureLastMatch(self, node: 个) -> 个 | None: # pyright: ignore [reportGeneralTypeIssues]
42
28
  self.nodeCaptured = None
43
- self.visit(node) # type: ignore
29
+ self.visit(node)
44
30
  return self.nodeCaptured
45
31
 
46
- class NodeChanger(ast.NodeTransformer):
47
- def __init__(self, findThis, doThat): # type: ignore
32
+ class NodeChanger(ast.NodeTransformer, Generic[个]):
33
+ def __init__(self, findThis: Callable[[个], bool], doThat: Callable[[个], Sequence[个] | 个 | None]) -> None:
48
34
  self.findThis = findThis
49
35
  self.doThat = doThat
50
36
 
51
- def visit(self, node): # type: ignore
37
+ def visit(self, node: 个) -> Sequence[个] | 个 | None: # pyright: ignore [reportGeneralTypeIssues]
52
38
  if self.findThis(node):
53
- return self.doThat(node) # type: ignore
54
- return super().visit(node)
39
+ return self.doThat(node)
40
+ return super().visit(cast(ast.AST, node))
55
41
 
56
42
  def importLogicalPath2Callable(logicalPathModule: str_nameDOTname, identifier: ast_Identifier, packageIdentifierIfRelative: ast_Identifier | None = None) -> Callable[..., Any]:
57
43
  moduleImported: ModuleType = importlib.import_module(logicalPathModule, packageIdentifierIfRelative)
@@ -18,9 +18,9 @@ mapFolding/reference/jobsCompleted/[2x19]/[2x19].ll
18
18
 
19
19
  This file demonstrates the low-level optimizations that made this previously
20
20
  intractable calculation possible. The IR reveals how the abstract algorithm was
21
- transformed into efficient machine code through Numba's compilation pipeline.
21
+ transformed into efficient machine code through Numba's compilation assembly-line.
22
22
 
23
- While originally part of a tighter integration with the code generation pipeline,
23
+ While originally part of a tighter integration with the code generation assembly-line,
24
24
  this module now operates as a standalone utility that can be applied to any module
25
25
  containing Numba-compiled functions.
26
26
  """
@@ -0,0 +1,22 @@
1
+ from collections.abc import Callable
2
+ from copy import deepcopy
3
+ from mapFolding.someAssemblyRequired import ast_Identifier, RecipeSynthesizeFlow, Then, be, ifThis, DOT, 又, NodeChanger
4
+ from mapFolding.someAssemblyRequired.transformationTools import makeDictionary4InliningFunction, makeDictionaryFunctionDef
5
+ from typing import cast
6
+ import ast
7
+
8
+ def inlineFunctionDef(astFunctionDef: ast.FunctionDef, dictionary4Inlining: dict[ast_Identifier, ast.FunctionDef]) -> ast.FunctionDef:
9
+
10
+ return astFunctionDef
11
+
12
+ # Test code
13
+ testFlow: RecipeSynthesizeFlow = RecipeSynthesizeFlow()
14
+ dictionary4Inlining: dict[ast_Identifier, ast.FunctionDef] = makeDictionary4InliningFunction(
15
+ testFlow.sourceCallableSequential,
16
+ (dictionaryFunctionDef := makeDictionaryFunctionDef(testFlow.source_astModule)))
17
+
18
+ astFunctionDef = dictionaryFunctionDef[testFlow.sourceCallableSequential]
19
+
20
+ astFunctionDefTransformed = inlineFunctionDef(
21
+ astFunctionDef,
22
+ dictionary4Inlining)
@@ -1,16 +1,15 @@
1
1
  """Synthesize one file to compute `foldsTotal` of `mapShape`."""
2
- from mapFolding.someAssemblyRequired import ast_Identifier, be, ifThis, Make, NodeChanger, NodeTourist, parsePathFilename2astModule, str_nameDOTname, Then, write_astModule, 又
3
- from mapFolding.someAssemblyRequired.ingredientsNumba import decorateCallableWithNumba, ParametersNumba, parametersNumbaDefault
4
- from mapFolding.someAssemblyRequired.synthesizeNumbaFlow import theNumbaFlow
5
- from mapFolding.someAssemblyRequired.transformDataStructures import makeInitializedComputationState, shatter_dataclassesDOTdataclass, ShatteredDataclass
6
- from mapFolding.someAssemblyRequired._toolboxContainers import astModuleToIngredientsFunction, IngredientsFunction, IngredientsModule, LedgerOfImports
7
- from mapFolding.filesystem import getFilenameFoldsTotal, getPathFilenameFoldsTotal, getPathRootJobDEFAULT
8
- from mapFolding.theSSOT import ComputationState, The
9
- from pathlib import Path, PurePosixPath
2
+ from mapFolding.toolboxFilesystem import getPathFilenameFoldsTotal
3
+ from mapFolding.someAssemblyRequired import ast_Identifier, be, ifThis, Make, NodeChanger, Then, IngredientsFunction, IngredientsModule, LedgerOfImports
4
+ from mapFolding.someAssemblyRequired.toolboxNumba import RecipeJob, SpicesJobNumba, decorateCallableWithNumba
5
+ from mapFolding.someAssemblyRequired.transformationTools import astModuleToIngredientsFunction, extractFunctionDef, write_astModule
6
+ from mapFolding.someAssemblyRequired.transformationTools import makeInitializedComputationState
7
+ from mapFolding.theSSOT import The, raiseIfNoneGitHubIssueNumber3
8
+ from mapFolding.oeis import getFoldsTotalKnown
10
9
  from typing import cast
11
10
  from Z0Z_tools import autoDecodingRLE
11
+ from pathlib import PurePosixPath
12
12
  import ast
13
- import dataclasses
14
13
 
15
14
  list_IdentifiersNotUsedAllHARDCODED = ['concurrencyLimit', 'foldsTotal', 'mapShape',]
16
15
  list_IdentifiersNotUsedParallelSequentialHARDCODED = ['indexLeaf']
@@ -22,105 +21,14 @@ list_IdentifiersStaticValuesHARDCODED = ['dimensionsTotal', 'leavesTotal',]
22
21
 
23
22
  list_IdentifiersNotUsedHARDCODED = list_IdentifiersStaticValuesHARDCODED + list_IdentifiersReplacedHARDCODED + list_IdentifiersNotUsedAllHARDCODED + list_IdentifiersNotUsedParallelSequentialHARDCODED + list_IdentifiersNotUsedSequentialHARDCODED
24
23
 
25
- @dataclasses.dataclass
26
- class Z0Z_RecipeJob:
27
- state: ComputationState
28
- # TODO create function to calculate `foldsTotalEstimated`
29
- foldsTotalEstimated: int = 0
30
- useNumbaProgressBar: bool = True
31
- numbaProgressBarIdentifier: ast_Identifier = 'ProgressBarGroupsOfFolds'
32
- shatteredDataclass: ShatteredDataclass = dataclasses.field(default=None, init=True) # type: ignore[assignment, reportAssignmentType]
33
-
34
- # ========================================
35
- # Source
36
- source_astModule = parsePathFilename2astModule(theNumbaFlow.pathFilenameSequential)
37
- sourceCountCallable: ast_Identifier = theNumbaFlow.callableSequential
38
-
39
- sourceLogicalPathModuleDataclass: str_nameDOTname = theNumbaFlow.logicalPathModuleDataclass
40
- sourceDataclassIdentifier: ast_Identifier = theNumbaFlow.dataclassIdentifier
41
- sourceDataclassInstance: ast_Identifier = theNumbaFlow.dataclassInstance
42
-
43
- sourcePathPackage: PurePosixPath | None = theNumbaFlow.pathPackage
44
- sourcePackageIdentifier: ast_Identifier | None = theNumbaFlow.packageIdentifier
45
-
46
- # ========================================
47
- # Filesystem (names of physical objects)
48
- pathPackage: PurePosixPath | None = None
49
- pathModule: PurePosixPath | None = PurePosixPath(getPathRootJobDEFAULT())
50
- """ `pathModule` will override `pathPackage` and `logicalPathRoot`."""
51
- fileExtension: str = theNumbaFlow.fileExtension
52
- pathFilenameFoldsTotal: PurePosixPath = dataclasses.field(default=None, init=True) # type: ignore[assignment, reportAssignmentType]
53
-
54
- # ========================================
55
- # Logical identifiers (as opposed to physical identifiers)
56
- # ========================================
57
- packageIdentifier: ast_Identifier | None = None
58
- logicalPathRoot: str_nameDOTname | None = None
59
- """ `logicalPathRoot` likely corresponds to a physical filesystem directory."""
60
- moduleIdentifier: ast_Identifier = dataclasses.field(default=None, init=True) # type: ignore[assignment, reportAssignmentType]
61
- countCallable: ast_Identifier = sourceCountCallable
62
- dataclassIdentifier: ast_Identifier | None = sourceDataclassIdentifier
63
- dataclassInstance: ast_Identifier | None = sourceDataclassInstance
64
- logicalPathModuleDataclass: str_nameDOTname | None = sourceLogicalPathModuleDataclass
65
-
66
- def _makePathFilename(self,
67
- pathRoot: PurePosixPath | None = None,
68
- logicalPathINFIX: str_nameDOTname | None = None,
69
- filenameStem: str | None = None,
70
- fileExtension: str | None = None,
71
- ) -> PurePosixPath:
72
- if pathRoot is None:
73
- pathRoot = self.pathPackage or PurePosixPath(Path.cwd())
74
- if logicalPathINFIX:
75
- whyIsThisStillAThing: list[str] = logicalPathINFIX.split('.')
76
- pathRoot = pathRoot.joinpath(*whyIsThisStillAThing)
77
- if filenameStem is None:
78
- filenameStem = self.moduleIdentifier
79
- if fileExtension is None:
80
- fileExtension = self.fileExtension
81
- filename: str = filenameStem + fileExtension
82
- return pathRoot.joinpath(filename)
83
-
84
- @property
85
- def pathFilenameModule(self) -> PurePosixPath:
86
- if self.pathModule is None:
87
- return self._makePathFilename()
88
- else:
89
- return self._makePathFilename(pathRoot=self.pathModule, logicalPathINFIX=None)
90
-
91
- def __post_init__(self):
92
- pathFilenameFoldsTotal = PurePosixPath(getPathFilenameFoldsTotal(self.state.mapShape))
93
-
94
- if self.moduleIdentifier is None:
95
- self.moduleIdentifier = pathFilenameFoldsTotal.stem
96
-
97
- if self.pathFilenameFoldsTotal is None:
98
- self.pathFilenameFoldsTotal = pathFilenameFoldsTotal
99
-
100
- if self.shatteredDataclass is None and self.logicalPathModuleDataclass and self.dataclassIdentifier and self.dataclassInstance:
101
- self.shatteredDataclass = shatter_dataclassesDOTdataclass(self.logicalPathModuleDataclass, self.dataclassIdentifier, self.dataclassInstance)
102
-
103
- # ========================================
104
- # Fields you probably don't need =================================
105
- # Dispatcher =================================
106
- sourceDispatcherCallable: ast_Identifier = theNumbaFlow.callableDispatcher
107
- dispatcherCallable: ast_Identifier = sourceDispatcherCallable
108
- # Parallel counting =================================
109
- sourceDataclassInstanceTaskDistribution: ast_Identifier = theNumbaFlow.dataclassInstanceTaskDistribution
110
- sourceConcurrencyManagerNamespace: ast_Identifier = theNumbaFlow.concurrencyManagerNamespace
111
- sourceConcurrencyManagerIdentifier: ast_Identifier = theNumbaFlow.concurrencyManagerIdentifier
112
- dataclassInstanceTaskDistribution: ast_Identifier = sourceDataclassInstanceTaskDistribution
113
- concurrencyManagerNamespace: ast_Identifier = sourceConcurrencyManagerNamespace
114
- concurrencyManagerIdentifier: ast_Identifier = sourceConcurrencyManagerIdentifier
115
-
116
- def addLauncherNumbaProgress(ingredientsModule: IngredientsModule, ingredientsFunction: IngredientsFunction, job: Z0Z_RecipeJob) -> IngredientsModule:
24
+ def addLauncherNumbaProgress(ingredientsModule: IngredientsModule, ingredientsFunction: IngredientsFunction, job: RecipeJob, spices: SpicesJobNumba) -> tuple[IngredientsModule, IngredientsFunction]:
117
25
 
118
26
  linesLaunch: str = f"""
119
27
  if __name__ == '__main__':
120
28
  with ProgressBar(total={job.foldsTotalEstimated}, update_interval=2) as statusUpdate:
121
29
  {job.countCallable}(statusUpdate)
122
30
  foldsTotal = statusUpdate.n * {job.state.leavesTotal}
123
- print('map {job.state.mapShape} =', foldsTotal)
31
+ print('\\nmap {job.state.mapShape} =', foldsTotal)
124
32
  writeStream = open('{job.pathFilenameFoldsTotal.as_posix()}', 'w')
125
33
  writeStream.write(str(foldsTotal))
126
34
  writeStream.close()
@@ -130,19 +38,19 @@ if __name__ == '__main__':
130
38
  ingredientsModule.imports.addImportFrom_asStr('numba_progress', numba_progressPythonClass)
131
39
  ingredientsModule.imports.addImportFrom_asStr('numba_progress', numba_progressNumbaType)
132
40
 
133
- ast_argNumbaProgress = ast.arg(arg=job.numbaProgressBarIdentifier, annotation=ast.Name(id=numba_progressPythonClass, ctx=ast.Load()))
41
+ ast_argNumbaProgress = ast.arg(arg=spices.numbaProgressBarIdentifier, annotation=ast.Name(id=numba_progressPythonClass, ctx=ast.Load()))
134
42
  ingredientsFunction.astFunctionDef.args.args.append(ast_argNumbaProgress)
135
43
 
136
44
  findThis = ifThis.isAugAssign_targetIs(ifThis.isName_Identifier(job.shatteredDataclass.countingVariableName.id))
137
- doThat = Then.replaceWith(Make.Expr(Make.Call(Make.Attribute(Make.Name(job.numbaProgressBarIdentifier),'update'),[Make.Constant(1)])))
138
- countWithProgressBar = NodeChanger(findThis, doThat)
45
+ doThat = Then.replaceWith(Make.Expr(Make.Call(Make.Attribute(Make.Name(spices.numbaProgressBarIdentifier),'update'),[Make.Constant(1)])))
46
+ countWithProgressBar = NodeChanger(findThis, doThat) # type: ignore
139
47
  countWithProgressBar.visit(ingredientsFunction.astFunctionDef)
140
48
 
141
49
  ingredientsModule.appendLauncher(ast.parse(linesLaunch))
142
50
 
143
- return ingredientsModule
51
+ return ingredientsModule, ingredientsFunction
144
52
 
145
- def move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsFunction: IngredientsFunction, job: Z0Z_RecipeJob) -> IngredientsFunction:
53
+ def move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsFunction: IngredientsFunction, job: RecipeJob) -> IngredientsFunction:
146
54
  ingredientsFunction.imports.update(job.shatteredDataclass.ledger)
147
55
 
148
56
  list_IdentifiersNotUsed = list_IdentifiersNotUsedHARDCODED
@@ -158,7 +66,6 @@ def move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsFunction: Ingre
158
66
  case 'scalar':
159
67
  ImaAnnAssign.value.args[0].value = int(job.state.__dict__[ast_arg.arg]) # type: ignore
160
68
  case 'array':
161
- # print(ast.dump(ImaAnnAssign))
162
69
  dataAsStrRLE: str = autoDecodingRLE(job.state.__dict__[ast_arg.arg], addSpaces=True)
163
70
  dataAs_astExpr: ast.expr = cast(ast.Expr, ast.parse(dataAsStrRLE).body[0]).value
164
71
  ImaAnnAssign.value.args = [dataAs_astExpr] # type: ignore
@@ -180,9 +87,11 @@ def move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsFunction: Ingre
180
87
  ast.fix_missing_locations(ingredientsFunction.astFunctionDef)
181
88
  return ingredientsFunction
182
89
 
183
- def makeJobNumba(job: Z0Z_RecipeJob, parametersNumba: ParametersNumba = parametersNumbaDefault):
90
+ def makeJobNumba(job: RecipeJob, spices: SpicesJobNumba):
184
91
  # get the raw ingredients: data and the algorithm
185
- ingredientsCount: IngredientsFunction = astModuleToIngredientsFunction(job.source_astModule, job.countCallable)
92
+ astFunctionDef = extractFunctionDef(job.source_astModule, job.countCallable)
93
+ if not astFunctionDef: raise raiseIfNoneGitHubIssueNumber3
94
+ ingredientsCount: IngredientsFunction = IngredientsFunction(astFunctionDef, LedgerOfImports())
186
95
 
187
96
  # Change the return so you can dynamically determine which variables are not used
188
97
  removeReturnStatement = NodeChanger(be.Return, Then.removeIt)
@@ -200,18 +109,54 @@ def makeJobNumba(job: Z0Z_RecipeJob, parametersNumba: ParametersNumba = paramete
200
109
  for identifier in list_IdentifiersStaticValues:
201
110
  findThis = ifThis.isName_Identifier(identifier)
202
111
  doThat = Then.replaceWith(Make.Constant(int(job.state.__dict__[identifier])))
203
- NodeChanger(findThis, doThat).visit(ingredientsCount.astFunctionDef)
112
+ NodeChanger(findThis, doThat).visit(ingredientsCount.astFunctionDef) # type: ignore
204
113
 
205
114
  # This launcher eliminates the use of one identifier, so run it now and you can dynamically determine which variables are not used
206
115
  ingredientsModule = IngredientsModule()
207
- ingredientsModule = addLauncherNumbaProgress(ingredientsModule, ingredientsCount, job)
208
- parametersNumba['nogil'] = True
116
+ if spices.useNumbaProgressBar:
117
+ ingredientsModule, ingredientsCount = addLauncherNumbaProgress(ingredientsModule, ingredientsCount, job, spices)
118
+ spices.parametersNumba['nogil'] = True
209
119
 
210
120
  ingredientsCount = move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsCount, job)
211
121
 
122
+ Z0Z_Identifier = 'DatatypeLeavesTotal'
123
+ Z0Z_type = 'uint8'
124
+ ingredientsModule.imports.addImportFrom_asStr('numba', Z0Z_type)
125
+ Z0Z_module = 'typing'
126
+ Z0Z_annotation = 'TypeAlias'
127
+ ingredientsModule.imports.addImportFrom_asStr(Z0Z_module, Z0Z_annotation)
128
+ Z0Z_statement = Make.AnnAssign(Make.Name(Z0Z_Identifier, ast.Store()), Make.Name(Z0Z_annotation), Make.Name(Z0Z_type))
129
+ ingredientsModule.appendPrologue(statement=Z0Z_statement)
130
+
131
+ Z0Z_Identifier = 'DatatypeElephino'
132
+ Z0Z_type = 'int16'
133
+ ingredientsModule.imports.addImportFrom_asStr('numba', Z0Z_type)
134
+ Z0Z_module = 'typing'
135
+ Z0Z_annotation = 'TypeAlias'
136
+ ingredientsModule.imports.addImportFrom_asStr(Z0Z_module, Z0Z_annotation)
137
+ Z0Z_statement = Make.AnnAssign(Make.Name(Z0Z_Identifier, ast.Store()), Make.Name(Z0Z_annotation), Make.Name(Z0Z_type))
138
+ ingredientsModule.appendPrologue(statement=Z0Z_statement)
139
+
140
+ ingredientsCount.imports.removeImportFromModule('mapFolding.theSSOT')
141
+ Z0Z_module = 'numpy'
142
+ Z0Z_asname = 'Array1DLeavesTotal'
143
+ ingredientsCount.imports.removeImportFrom(Z0Z_module, None, Z0Z_asname)
144
+ Z0Z_type_name = 'uint8'
145
+ ingredientsCount.imports.addImportFrom_asStr(Z0Z_module, Z0Z_type_name, Z0Z_asname)
146
+ Z0Z_asname = 'Array1DElephino'
147
+ ingredientsCount.imports.removeImportFrom(Z0Z_module, None, Z0Z_asname)
148
+ Z0Z_type_name = 'int16'
149
+ ingredientsCount.imports.addImportFrom_asStr(Z0Z_module, Z0Z_type_name, Z0Z_asname)
150
+ Z0Z_asname = 'Array3D'
151
+ ingredientsCount.imports.removeImportFrom(Z0Z_module, None, Z0Z_asname)
152
+ Z0Z_type_name = 'uint8'
153
+ ingredientsCount.imports.addImportFrom_asStr(Z0Z_module, Z0Z_type_name, Z0Z_asname)
154
+
155
+ from numpy import int16 as Array1DLeavesTotal, int16 as Array1DElephino, int16 as Array3D
156
+
212
157
  ingredientsCount.astFunctionDef.decorator_list = [] # TODO low-priority, handle this more elegantly
213
158
  # TODO when I add the function signature in numba style back to the decorator, the logic needs to handle `ProgressBarType:`
214
- ingredientsCount = decorateCallableWithNumba(ingredientsCount, parametersNumba)
159
+ ingredientsCount = decorateCallableWithNumba(ingredientsCount, spices.parametersNumba)
215
160
 
216
161
  ingredientsModule.appendIngredientsFunction(ingredientsCount)
217
162
 
@@ -243,5 +188,9 @@ def makeJobNumba(job: Z0Z_RecipeJob, parametersNumba: ParametersNumba = paramete
243
188
  if __name__ == '__main__':
244
189
  mapShape = (6,6)
245
190
  state = makeInitializedComputationState(mapShape)
246
- aJob = Z0Z_RecipeJob(state)
247
- makeJobNumba(aJob)
191
+ foldsTotalEstimated = getFoldsTotalKnown(state.mapShape) // state.leavesTotal
192
+ pathModule = PurePosixPath(The.pathPackage, 'jobs')
193
+ pathFilenameFoldsTotal = PurePosixPath(getPathFilenameFoldsTotal(state.mapShape, pathModule))
194
+ aJob = RecipeJob(state, foldsTotalEstimated, pathModule=pathModule, pathFilenameFoldsTotal=pathFilenameFoldsTotal)
195
+ spices = SpicesJobNumba()
196
+ makeJobNumba(aJob, spices)