mapFolding 0.10.0__tar.gz → 0.11.0__tar.gz

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 (72) hide show
  1. {mapfolding-0.10.0 → mapfolding-0.11.0}/PKG-INFO +2 -1
  2. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/__init__.py +29 -27
  3. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/someAssemblyRequired/Z0Z_makeSomeModules.py +4 -6
  4. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/someAssemblyRequired/__init__.py +15 -24
  5. mapfolding-0.11.0/mapFolding/someAssemblyRequired/_toolIfThis.py +53 -0
  6. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/someAssemblyRequired/_toolboxContainers.py +12 -284
  7. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/someAssemblyRequired/makeJobTheorem2Numba.py +6 -6
  8. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +5 -5
  9. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/someAssemblyRequired/transformationTools.py +5 -178
  10. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding.egg-info/PKG-INFO +2 -1
  11. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding.egg-info/SOURCES.txt +0 -12
  12. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding.egg-info/requires.txt +1 -0
  13. {mapfolding-0.10.0 → mapfolding-0.11.0}/pyproject.toml +2 -1
  14. mapfolding-0.10.0/mapFolding/someAssemblyRequired/_astTypes.py +0 -117
  15. mapfolding-0.10.0/mapFolding/someAssemblyRequired/_theTypes.py +0 -34
  16. mapfolding-0.10.0/mapFolding/someAssemblyRequired/_toolBe.py +0 -524
  17. mapfolding-0.10.0/mapFolding/someAssemblyRequired/_toolDOT.py +0 -493
  18. mapfolding-0.10.0/mapFolding/someAssemblyRequired/_toolGrab.py +0 -653
  19. mapfolding-0.10.0/mapFolding/someAssemblyRequired/_toolIfThis.py +0 -193
  20. mapfolding-0.10.0/mapFolding/someAssemblyRequired/_toolMake.py +0 -339
  21. mapfolding-0.10.0/mapFolding/someAssemblyRequired/_toolThen.py +0 -63
  22. mapfolding-0.10.0/mapFolding/someAssemblyRequired/_toolboxAST.py +0 -57
  23. mapfolding-0.10.0/mapFolding/someAssemblyRequired/_toolboxPython.py +0 -188
  24. mapfolding-0.10.0/mapFolding/toolFactory/astFactory.py +0 -493
  25. mapfolding-0.10.0/mapFolding/toolFactory/astFactory_annex.py +0 -63
  26. mapfolding-0.10.0/mapFolding/toolFactory/astFactory_docstrings.py +0 -63
  27. {mapfolding-0.10.0 → mapfolding-0.11.0}/LICENSE +0 -0
  28. {mapfolding-0.10.0 → mapfolding-0.11.0}/README.md +0 -0
  29. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/basecamp.py +0 -0
  30. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/beDRY.py +0 -0
  31. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/daoOfMapFolding.py +0 -0
  32. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/dataBaskets.py +0 -0
  33. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/datatypes.py +0 -0
  34. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/oeis.py +0 -0
  35. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/py.typed +0 -0
  36. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/reference/__init__.py +0 -0
  37. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/reference/flattened.py +0 -0
  38. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/reference/hunterNumba.py +0 -0
  39. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/reference/irvineJavaPort.py +0 -0
  40. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/reference/jaxCount.py +0 -0
  41. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/reference/jobsCompleted/[2x19]/p2x19.py +0 -0
  42. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/reference/jobsCompleted/__init__.py +0 -0
  43. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/reference/jobsCompleted/p2x19/p2x19.py +0 -0
  44. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/reference/lunnonNumpy.py +0 -0
  45. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/reference/lunnonWhile.py +0 -0
  46. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/reference/rotatedEntryPoint.py +0 -0
  47. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/reference/total_countPlus1vsPlusN.py +0 -0
  48. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/someAssemblyRequired/RecipeJob.py +0 -0
  49. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/someAssemblyRequired/getLLVMforNoReason.py +0 -0
  50. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/someAssemblyRequired/toolboxNumba.py +0 -0
  51. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/syntheticModules/__init__.py +0 -0
  52. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/syntheticModules/daoOfMapFolding.py +0 -0
  53. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/syntheticModules/dataPacking.py +0 -0
  54. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/syntheticModules/initializeCount.py +0 -0
  55. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/syntheticModules/numbaCount.py +0 -0
  56. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/syntheticModules/theorem2.py +0 -0
  57. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/syntheticModules/theorem2Numba.py +0 -0
  58. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/syntheticModules/theorem2Trimmed.py +0 -0
  59. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/theDao.py +0 -0
  60. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/theSSOT.py +0 -0
  61. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding/toolboxFilesystem.py +0 -0
  62. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding.egg-info/dependency_links.txt +0 -0
  63. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding.egg-info/entry_points.txt +0 -0
  64. {mapfolding-0.10.0 → mapfolding-0.11.0}/mapFolding.egg-info/top_level.txt +0 -0
  65. {mapfolding-0.10.0 → mapfolding-0.11.0}/setup.cfg +0 -0
  66. {mapfolding-0.10.0 → mapfolding-0.11.0}/tests/__init__.py +0 -0
  67. {mapfolding-0.10.0 → mapfolding-0.11.0}/tests/conftest.py +0 -0
  68. {mapfolding-0.10.0 → mapfolding-0.11.0}/tests/test_computations.py +0 -0
  69. {mapfolding-0.10.0 → mapfolding-0.11.0}/tests/test_filesystem.py +0 -0
  70. {mapfolding-0.10.0 → mapfolding-0.11.0}/tests/test_oeis.py +0 -0
  71. {mapfolding-0.10.0 → mapfolding-0.11.0}/tests/test_other.py +0 -0
  72. {mapfolding-0.10.0 → mapfolding-0.11.0}/tests/test_tasks.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mapFolding
3
- Version: 0.10.0
3
+ Version: 0.11.0
4
4
  Summary: Map folding algorithm with code transformation framework for optimizing numerical computations
5
5
  Author-email: Hunter Hogan <HunterHogan@pm.me>
6
6
  License: CC-BY-NC-4.0
@@ -31,6 +31,7 @@ Classifier: Typing :: Typed
31
31
  Requires-Python: >=3.10
32
32
  Description-Content-Type: text/markdown
33
33
  License-File: LICENSE
34
+ Requires-Dist: astToolkit
34
35
  Requires-Dist: autoflake
35
36
  Requires-Dist: cytoolz
36
37
  Requires-Dist: more_itertools
@@ -47,38 +47,39 @@ foundation for exploring advanced code transformation techniques.
47
47
  from typing import Any, TypeAlias
48
48
  import sys
49
49
 
50
- stuPyd: TypeAlias = Any
51
-
52
- if sys.version_info >= (3, 12):
53
- from ast import (
54
- ParamSpec as astDOTParamSpec,
55
- type_param as astDOTtype_param,
56
- TypeAlias as astDOTTypeAlias,
57
- TypeVar as astDOTTypeVar,
58
- TypeVarTuple as astDOTTypeVarTuple,
59
- )
60
- else:
61
- astDOTParamSpec: TypeAlias = stuPyd
62
- astDOTtype_param: TypeAlias = stuPyd
63
- astDOTTypeAlias: TypeAlias = stuPyd
64
- astDOTTypeVar: TypeAlias = stuPyd
65
- astDOTTypeVarTuple: TypeAlias = stuPyd
50
+ yourPythonIsOld: TypeAlias = Any
51
+ # ruff: noqa: E402
52
+
53
+ # if sys.version_info >= (3, 12):
54
+ # from ast import (
55
+ # ParamSpec as astDOTParamSpec,
56
+ # type_param as astDOTtype_param,
57
+ # TypeAlias as astDOTTypeAlias,
58
+ # TypeVar as astDOTTypeVar,
59
+ # TypeVarTuple as astDOTTypeVarTuple,
60
+ # )
61
+ # else:
62
+ # astDOTParamSpec: TypeAlias = yourPythonIsOld
63
+ # astDOTtype_param: TypeAlias = yourPythonIsOld
64
+ # astDOTTypeAlias: TypeAlias = yourPythonIsOld
65
+ # astDOTTypeVar: TypeAlias = yourPythonIsOld
66
+ # astDOTTypeVarTuple: TypeAlias = yourPythonIsOld
66
67
 
67
68
  if sys.version_info >= (3, 11):
68
- from ast import TryStar as astDOTTryStar
69
+ # from ast import TryStar as astDOTTryStar
69
70
  from typing import TypedDict as TypedDict
70
71
  from typing import NotRequired as NotRequired
71
72
  else:
72
- astDOTTryStar: TypeAlias = stuPyd
73
+ astDOTTryStar: TypeAlias = yourPythonIsOld
73
74
  try:
74
75
  from typing_extensions import TypedDict as TypedDict
75
76
  from typing_extensions import NotRequired as NotRequired
76
77
  except Exception:
77
- TypedDict = dict[stuPyd, stuPyd]
78
+ TypedDict = dict[yourPythonIsOld, yourPythonIsOld]
78
79
  from collections.abc import Iterable
79
80
  NotRequired: TypeAlias = Iterable
80
81
 
81
- from mapFolding.datatypes import ( # noqa: E402
82
+ from mapFolding.datatypes import (
82
83
  Array1DElephino as Array1DElephino,
83
84
  Array1DFoldsTotal as Array1DFoldsTotal,
84
85
  Array1DLeavesTotal as Array1DLeavesTotal,
@@ -92,18 +93,18 @@ from mapFolding.datatypes import ( # noqa: E402
92
93
  NumPyLeavesTotal as NumPyLeavesTotal,
93
94
  )
94
95
 
95
- from mapFolding.theSSOT import ( # noqa: E402
96
+ from mapFolding.theSSOT import (
96
97
  ComputationState as ComputationState,
97
98
  raiseIfNoneGitHubIssueNumber3 as raiseIfNoneGitHubIssueNumber3,
98
99
  The as The,
99
100
  )
100
101
 
101
- from mapFolding.theDao import ( # noqa: E402
102
+ from mapFolding.theDao import (
102
103
  countInitialize as countInitialize,
103
104
  doTheNeedful as doTheNeedful,
104
105
  )
105
106
 
106
- from mapFolding.beDRY import ( # noqa: E402
107
+ from mapFolding.beDRY import (
107
108
  getLeavesTotal as getLeavesTotal,
108
109
  getTaskDivisions as getTaskDivisions,
109
110
  outfitCountFolds as outfitCountFolds,
@@ -111,17 +112,18 @@ from mapFolding.beDRY import ( # noqa: E402
111
112
  validateListDimensions as validateListDimensions,
112
113
  )
113
114
 
114
- from mapFolding.toolboxFilesystem import ( # noqa: E402
115
+ from mapFolding.toolboxFilesystem import (
115
116
  getPathFilenameFoldsTotal as getPathFilenameFoldsTotal,
116
117
  getPathRootJobDEFAULT as getPathRootJobDEFAULT,
117
118
  saveFoldsTotal as saveFoldsTotal,
118
119
  saveFoldsTotalFAILearly as saveFoldsTotalFAILearly,
119
- writeStringToHere as writeStringToHere,
120
120
  )
121
121
 
122
- from mapFolding.basecamp import countFolds as countFolds # noqa: E402
122
+ from Z0Z_tools import writeStringToHere as writeStringToHere
123
+
124
+ from mapFolding.basecamp import countFolds as countFolds
123
125
 
124
- from mapFolding.oeis import ( # noqa: E402
126
+ from mapFolding.oeis import (
125
127
  clearOEIScache as clearOEIScache,
126
128
  getFoldsTotalKnown as getFoldsTotalKnown,
127
129
  getOEISids as getOEISids,
@@ -26,7 +26,7 @@ from mapFolding.someAssemblyRequired.transformationTools import (
26
26
  shatter_dataclassesDOTdataclass,
27
27
  unpackDataclassCallFunctionRepackDataclass,
28
28
  write_astModule,
29
- )
29
+ )
30
30
  from pathlib import PurePath
31
31
  import ast
32
32
 
@@ -58,10 +58,7 @@ def makeInitializeGroupsOfFolds() -> None:
58
58
  theCountingIdentifier = theCountingIdentifierHARDCODED
59
59
 
60
60
  findThis = IfThis.isWhileAttributeNamespace_IdentifierGreaterThan0(dataclassInstanceIdentifier, 'leaf1ndex')
61
- doThat = Grab.testAttribute(Grab.andDoAllOf([
62
- Grab.opsAttribute(Then.replaceWith([ast.Eq()])), # type: ignore
63
- Grab.leftAttribute(Grab.attrAttribute(Then.replaceWith(theCountingIdentifier))) # type: ignore
64
- ]))
61
+ doThat = Grab.testAttribute(Grab.andDoAllOf([ Grab.opsAttribute(Then.replaceWith([ast.Eq()])), Grab.leftAttribute(Grab.attrAttribute(Then.replaceWith(theCountingIdentifier))) ])) # type: ignore
65
62
  NodeChanger(findThis, doThat).visit(countInitializeIngredients.astFunctionDef.body[0])
66
63
 
67
64
  ingredientsModule = IngredientsModule(countInitializeIngredients)
@@ -301,7 +298,8 @@ def makeUnRePackDataclass(astImportFrom: ast.ImportFrom) -> None:
301
298
  doTheNeedful.imports.addAst(astImportFrom)
302
299
  targetCallableIdentifier = astImportFrom.names[0].name
303
300
  doTheNeedful = unpackDataclassCallFunctionRepackDataclass(doTheNeedful, targetCallableIdentifier, shatteredDataclass)
304
- targetFunctionDef = extractFunctionDef(parseLogicalPath2astModule(astImportFrom.module), targetCallableIdentifier) # type: ignore
301
+ if astImportFrom.module is None: raise raiseIfNoneGitHubIssueNumber3
302
+ targetFunctionDef = extractFunctionDef(parseLogicalPath2astModule(astImportFrom.module), targetCallableIdentifier)
305
303
  if targetFunctionDef is None: raise raiseIfNoneGitHubIssueNumber3
306
304
  astTuple: ast.Tuple | None = NodeTourist(Be.Return, Then.extractIt(DOT.value)).captureLastMatch(targetFunctionDef)
307
305
  if astTuple is None: raise raiseIfNoneGitHubIssueNumber3
@@ -44,45 +44,36 @@ optimizations - while maintaining the ability to verify correctness at each tran
44
44
  test suite.
45
45
  """
46
46
 
47
- from mapFolding.someAssemblyRequired._theTypes import (
47
+ from astToolkit import (
48
48
  ast_expr_Slice as ast_expr_Slice,
49
49
  ast_Identifier as ast_Identifier,
50
+ astModuleToIngredientsFunction as astModuleToIngredientsFunction,
51
+ Be as Be,
52
+ DOT as DOT,
53
+ extractClassDef as extractClassDef,
54
+ extractFunctionDef as extractFunctionDef,
55
+ Grab as Grab,
50
56
  ImaCallToName as ImaCallToName,
51
- NodeORattribute as NodeORattribute,
52
- str_nameDOTname as str_nameDOTname,
53
- 个 as 个,
54
- )
55
-
56
- from mapFolding.someAssemblyRequired._astTypes import * # noqa: F403
57
-
58
- from mapFolding.someAssemblyRequired._toolboxPython import (
59
57
  importLogicalPath2Callable as importLogicalPath2Callable,
60
58
  importPathFilename2Callable as importPathFilename2Callable,
59
+ IngredientsFunction as IngredientsFunction,
60
+ IngredientsModule as IngredientsModule,
61
+ LedgerOfImports as LedgerOfImports,
62
+ Make as Make,
61
63
  NodeChanger as NodeChanger,
64
+ NodeORattribute as NodeORattribute,
62
65
  NodeTourist as NodeTourist,
63
66
  parseLogicalPath2astModule as parseLogicalPath2astModule,
64
67
  parsePathFilename2astModule as parsePathFilename2astModule,
68
+ str_nameDOTname as str_nameDOTname,
69
+ Then as Then,
70
+ 个 as 个,
65
71
  )
66
72
 
67
- from mapFolding.someAssemblyRequired._toolBe import Be as Be
68
- from mapFolding.someAssemblyRequired._toolDOT import DOT as DOT
69
- from mapFolding.someAssemblyRequired._toolGrab import Grab as Grab
70
- from mapFolding.someAssemblyRequired._toolMake import Make as Make
71
-
72
73
  from mapFolding.someAssemblyRequired._toolIfThis import IfThis as IfThis
73
- from mapFolding.someAssemblyRequired._toolThen import Then as Then
74
74
 
75
75
  from mapFolding.someAssemblyRequired._toolboxContainers import (
76
76
  DeReConstructField2ast as DeReConstructField2ast,
77
- IngredientsFunction as IngredientsFunction,
78
- IngredientsModule as IngredientsModule,
79
- LedgerOfImports as LedgerOfImports,
80
77
  RecipeSynthesizeFlow as RecipeSynthesizeFlow,
81
78
  ShatteredDataclass as ShatteredDataclass,
82
79
  )
83
-
84
- from mapFolding.someAssemblyRequired._toolboxAST import (
85
- astModuleToIngredientsFunction as astModuleToIngredientsFunction,
86
- extractClassDef as extractClassDef,
87
- extractFunctionDef as extractFunctionDef,
88
- )
@@ -0,0 +1,53 @@
1
+ """
2
+ AST Node Predicate and Access Utilities for Pattern Matching and Traversal
3
+
4
+ This module provides utilities for accessing and matching AST nodes in a consistent way. It contains three primary
5
+ classes:
6
+
7
+ 1. DOT: Provides consistent accessor methods for AST node attributes across different node types, simplifying the access
8
+ to node properties.
9
+
10
+ 2. be: Offers type-guard functions that verify AST node types, enabling safe type narrowing for static type checking and
11
+ improving code safety.
12
+
13
+ 3. ifThis: Contains predicate functions for matching AST nodes based on various criteria, enabling precise targeting of
14
+ nodes for analysis or transformation.
15
+
16
+ These utilities form the foundation of the pattern-matching component in the AST manipulation framework, working in
17
+ conjunction with the NodeChanger and NodeTourist classes to enable precise and targeted code transformations. Together,
18
+ they implement a declarative approach to AST manipulation that separates node identification (ifThis), type verification
19
+ (be), and data access (DOT).
20
+ """
21
+
22
+ from astToolkit import IfThis as astToolkit_IfThis
23
+ from collections.abc import Callable
24
+ from mapFolding.someAssemblyRequired import ast_Identifier, Be
25
+ from typing import TypeGuard
26
+ import ast
27
+
28
+ class IfThis(astToolkit_IfThis):
29
+ """
30
+ Provide predicate functions for matching and filtering AST nodes based on various criteria.
31
+
32
+ The ifThis class contains static methods that generate predicate functions used to test whether AST nodes match
33
+ specific criteria. These predicates can be used with NodeChanger and NodeTourist to identify and process specific
34
+ patterns in the AST.
35
+
36
+ The class provides predicates for matching various node types, attributes, identifiers, and structural patterns,
37
+ enabling precise targeting of AST elements for analysis or transformation.
38
+ """
39
+ @staticmethod
40
+ def isAttributeNamespace_IdentifierGreaterThan0(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.Compare] | bool]:
41
+ return lambda node: (Be.Compare(node)
42
+ and IfThis.isAttributeNamespace_Identifier(namespace, identifier)(node.left)
43
+ and Be.Gt(node.ops[0])
44
+ and IfThis.isConstant_value(0)(node.comparators[0]))
45
+ @staticmethod
46
+ def isIfAttributeNamespace_IdentifierGreaterThan0(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.If] | bool]:
47
+ return lambda node: (Be.If(node)
48
+ and IfThis.isAttributeNamespace_IdentifierGreaterThan0(namespace, identifier)(node.test))
49
+
50
+ @staticmethod
51
+ def isWhileAttributeNamespace_IdentifierGreaterThan0(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.While] | bool]:
52
+ return lambda node: (Be.While(node)
53
+ and IfThis.isAttributeNamespace_IdentifierGreaterThan0(namespace, identifier)(node.test))
@@ -18,294 +18,16 @@ The containers work in conjunction with transformation tools that manipulate the
18
18
  specific optimizations and transformations.
19
19
  """
20
20
 
21
- from collections import defaultdict
22
- from collections.abc import Callable, Sequence
21
+ from astToolkit import IngredientsFunction as IngredientsFunction, IngredientsModule as IngredientsModule, LedgerOfImports as LedgerOfImports
22
+ from collections.abc import Callable
23
23
  from copy import deepcopy
24
- from typing import Any
25
24
  from mapFolding.someAssemblyRequired import ast_Identifier, DOT, IfThis, Make, NodeTourist, parseLogicalPath2astModule, str_nameDOTname, Then
26
25
  from mapFolding.theSSOT import raiseIfNoneGitHubIssueNumber3, The
27
26
  from pathlib import Path, PurePosixPath
28
- from Z0Z_tools import updateExtendPolishDictionaryLists
27
+ from typing import Any, cast
29
28
  import ast
30
29
  import dataclasses
31
30
 
32
- class LedgerOfImports:
33
- """
34
- Track and manage import statements for programmatically generated code.
35
-
36
- LedgerOfImports acts as a registry for import statements, maintaining a clean separation between the logical
37
- structure of imports and their textual representation. It enables:
38
-
39
- 1. Tracking regular imports and import-from statements.
40
- 2. Adding imports programmatically during code transformation.
41
- 3. Merging imports from multiple sources.
42
- 4. Removing unnecessary or conflicting imports.
43
- 5. Generating optimized AST import nodes for the final code.
44
-
45
- This class forms the foundation of dependency management in generated code, ensuring that all required libraries are
46
- available without duplication or conflict.
47
- """
48
- # TODO When resolving the ledger of imports, remove self-referential imports
49
-
50
- def __init__(self, startWith: ast.AST | None = None, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
51
- self.dictionaryImportFrom: dict[str_nameDOTname, list[tuple[ast_Identifier, ast_Identifier | None]]] = defaultdict(list)
52
- self.listImport: list[str_nameDOTname] = []
53
- self.type_ignores = [] if type_ignores is None else list(type_ignores)
54
- if startWith:
55
- self.walkThis(startWith)
56
-
57
- def addAst(self, astImport____: ast.Import | ast.ImportFrom, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
58
- match astImport____:
59
- case ast.Import():
60
- for alias in astImport____.names:
61
- self.listImport.append(alias.name)
62
- case ast.ImportFrom():
63
- # TODO fix the mess created by `None` means '.'. I need a `str_nameDOTname` to replace '.'
64
- if astImport____.module is None:
65
- astImport____.module = '.'
66
- for alias in astImport____.names:
67
- self.dictionaryImportFrom[astImport____.module].append((alias.name, alias.asname))
68
- case _:
69
- raise ValueError(f"I received {type(astImport____) = }, but I can only accept {ast.Import} and {ast.ImportFrom}.")
70
- if type_ignores:
71
- self.type_ignores.extend(type_ignores)
72
-
73
- def addImport_asStr(self, moduleWithLogicalPath: str_nameDOTname, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
74
- self.listImport.append(moduleWithLogicalPath)
75
- if type_ignores:
76
- self.type_ignores.extend(type_ignores)
77
-
78
- def addImportFrom_asStr(self, moduleWithLogicalPath: str_nameDOTname, name: ast_Identifier, asname: ast_Identifier | None = None, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
79
- self.dictionaryImportFrom[moduleWithLogicalPath].append((name, asname))
80
- if type_ignores:
81
- self.type_ignores.extend(type_ignores)
82
-
83
- def removeImportFromModule(self, moduleWithLogicalPath: str_nameDOTname) -> None:
84
- """Remove all imports from a specific module."""
85
- self.removeImportFrom(moduleWithLogicalPath, None, None)
86
-
87
- def removeImportFrom(self, moduleWithLogicalPath: str_nameDOTname, name: ast_Identifier | None, asname: ast_Identifier | None = None) -> None:
88
- """
89
- name, asname Action
90
- None, None : remove all matches for the module
91
- ast_Identifier, ast_Identifier : remove exact matches
92
- ast_Identifier, None : remove exact matches
93
- None, ast_Identifier : remove all matches for asname and if entry_asname is None remove name == ast_Identifier
94
- """
95
- if moduleWithLogicalPath in self.dictionaryImportFrom:
96
- if name is None and asname is None:
97
- # Remove all entries for the module
98
- self.dictionaryImportFrom.pop(moduleWithLogicalPath)
99
- else:
100
- if name is None:
101
- self.dictionaryImportFrom[moduleWithLogicalPath] = [(entry_name, entry_asname) for entry_name, entry_asname in self.dictionaryImportFrom[moduleWithLogicalPath]
102
- if not (entry_asname == asname) and not (entry_asname is None and entry_name == asname)]
103
- else:
104
- self.dictionaryImportFrom[moduleWithLogicalPath] = [(entry_name, entry_asname) for entry_name, entry_asname in self.dictionaryImportFrom[moduleWithLogicalPath]
105
- if not (entry_name == name and entry_asname == asname)]
106
- if not self.dictionaryImportFrom[moduleWithLogicalPath]:
107
- self.dictionaryImportFrom.pop(moduleWithLogicalPath)
108
-
109
- def exportListModuleIdentifiers(self) -> list[ast_Identifier]:
110
- listModuleIdentifiers: list[ast_Identifier] = list(self.dictionaryImportFrom.keys())
111
- listModuleIdentifiers.extend(self.listImport)
112
- return sorted(set(listModuleIdentifiers))
113
-
114
- def makeList_ast(self) -> list[ast.ImportFrom | ast.Import]:
115
- listImportFrom: list[ast.ImportFrom] = []
116
- for moduleWithLogicalPath, listOfNameTuples in sorted(self.dictionaryImportFrom.items()):
117
- listOfNameTuples = sorted(list(set(listOfNameTuples)), key=lambda nameTuple: nameTuple[0])
118
- list_alias: list[ast.alias] = []
119
- for name, asname in listOfNameTuples:
120
- list_alias.append(Make.alias(name, asname))
121
- if list_alias:
122
- listImportFrom.append(Make.ImportFrom(moduleWithLogicalPath, list_alias))
123
- list_astImport: list[ast.Import] = [Make.Import(moduleWithLogicalPath) for moduleWithLogicalPath in sorted(set(self.listImport))]
124
- return listImportFrom + list_astImport
125
-
126
- def update(self, *fromLedger: 'LedgerOfImports') -> None:
127
- """Update this ledger with imports from one or more other ledgers.
128
- Parameters:
129
- *fromLedger: One or more other `LedgerOfImports` objects from which to merge.
130
- """
131
- updatedDictionary = updateExtendPolishDictionaryLists(self.dictionaryImportFrom, *(ledger.dictionaryImportFrom for ledger in fromLedger), destroyDuplicates=True, reorderLists=True)
132
- self.dictionaryImportFrom = defaultdict(list, updatedDictionary)
133
- for ledger in fromLedger:
134
- self.listImport.extend(ledger.listImport)
135
- self.type_ignores.extend(ledger.type_ignores)
136
-
137
- def walkThis(self, walkThis: ast.AST, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
138
- for nodeBuffalo in ast.walk(walkThis):
139
- if isinstance(nodeBuffalo, (ast.Import, ast.ImportFrom)):
140
- self.addAst(nodeBuffalo)
141
- if type_ignores:
142
- self.type_ignores.extend(type_ignores)
143
-
144
- # Consolidate settings classes through inheritance https://github.com/hunterhogan/mapFolding/issues/15
145
- @dataclasses.dataclass
146
- class IngredientsFunction:
147
- """
148
- Package a function definition with its import dependencies for code generation.
149
-
150
- IngredientsFunction encapsulates an AST function definition along with all the imports required for that function to
151
- operate correctly. This creates a modular, portable unit that can be:
152
-
153
- 1. Transformed independently (e.g., by applying Numba decorators).
154
- 2. Transplanted between modules while maintaining dependencies.
155
- 3. Combined with other functions to form complete modules.
156
- 4. Analyzed for optimization opportunities.
157
-
158
- This class forms the primary unit of function manipulation in the code generation system, enabling targeted
159
- transformations while preserving function dependencies.
160
-
161
- Parameters:
162
- astFunctionDef: The AST representation of the function definition
163
- imports: Import statements needed by the function
164
- type_ignores: Type ignore comments associated with the function
165
- """
166
- astFunctionDef: ast.FunctionDef
167
- imports: LedgerOfImports = dataclasses.field(default_factory=LedgerOfImports)
168
- type_ignores: list[ast.TypeIgnore] = dataclasses.field(default_factory=list)
169
-
170
- # Consolidate settings classes through inheritance https://github.com/hunterhogan/mapFolding/issues/15
171
- @dataclasses.dataclass
172
- class IngredientsModule:
173
- """
174
- Assemble a complete Python module from its constituent AST components.
175
-
176
- IngredientsModule provides a structured container for all elements needed to generate a complete Python module,
177
- including:
178
-
179
- 1. Import statements aggregated from all module components.
180
- 2. Prologue code that runs before function definitions.
181
- 3. Function definitions with their dependencies.
182
- 4. Epilogue code that runs after function definitions.
183
- 5. Entry point code executed when the module runs as a script.
184
- 6. Type ignores and other annotations.
185
-
186
- This class enables programmatic assembly of Python modules with a clear separation between different structural
187
- elements, while maintaining the proper ordering and relationships between components.
188
-
189
- The modular design allows transformations to be applied to specific parts of a module while preserving the overall
190
- structure.
191
-
192
- Parameters:
193
- ingredientsFunction (None): One or more `IngredientsFunction` that will appended to `listIngredientsFunctions`.
194
- """
195
- ingredientsFunction: dataclasses.InitVar[Sequence[IngredientsFunction] | IngredientsFunction | None] = None
196
-
197
- # init var with an existing module? method to deconstruct an existing module?
198
-
199
- # `body` attribute of `ast.Module`
200
- """NOTE
201
- - Bare statements in `prologue` and `epilogue` are not 'protected' by `if __name__ == '__main__':` so they will be executed merely by loading the module.
202
- - The dataclass has methods for modifying `prologue`, `epilogue`, and `launcher`.
203
- - However, `prologue`, `epilogue`, and `launcher` are `ast.Module` (as opposed to `list[ast.stmt]`), so that you may use tools such as `ast.walk` and `ast.NodeVisitor` on the fields.
204
- """
205
- imports: LedgerOfImports = dataclasses.field(default_factory=LedgerOfImports)
206
- """Modify this field using the methods in `LedgerOfImports`."""
207
- prologue: ast.Module = Make.Module([],[])
208
- """Statements after the imports and before the functions in listIngredientsFunctions."""
209
- listIngredientsFunctions: list[IngredientsFunction] = dataclasses.field(default_factory=list)
210
- epilogue: ast.Module = Make.Module([],[])
211
- """Statements after the functions in listIngredientsFunctions and before `launcher`."""
212
- launcher: ast.Module = Make.Module([],[])
213
- """`if __name__ == '__main__':`"""
214
-
215
- # `ast.TypeIgnore` statements to supplement those in other fields; `type_ignores` is a parameter for `ast.Module` constructor
216
- supplemental_type_ignores: list[ast.TypeIgnore] = dataclasses.field(default_factory=list)
217
-
218
- def __post_init__(self, ingredientsFunction: Sequence[IngredientsFunction] | IngredientsFunction | None = None) -> None:
219
- if ingredientsFunction is not None:
220
- if isinstance(ingredientsFunction, IngredientsFunction):
221
- self.appendIngredientsFunction(ingredientsFunction)
222
- else:
223
- self.appendIngredientsFunction(*ingredientsFunction)
224
-
225
- def _append_astModule(self, self_astModule: ast.Module, astModule: ast.Module | None, statement: Sequence[ast.stmt] | ast.stmt | None, type_ignores: list[ast.TypeIgnore] | None) -> None:
226
- """Append one or more statements to `prologue`."""
227
- list_body: list[ast.stmt] = []
228
- listTypeIgnore: list[ast.TypeIgnore] = []
229
- if astModule is not None and isinstance(astModule, ast.Module): # type: ignore
230
- list_body.extend(astModule.body)
231
- listTypeIgnore.extend(astModule.type_ignores)
232
- if type_ignores is not None:
233
- listTypeIgnore.extend(type_ignores)
234
- if statement is not None:
235
- if isinstance(statement, Sequence):
236
- list_body.extend(statement)
237
- else:
238
- list_body.append(statement)
239
- self_astModule.body.extend(list_body)
240
- self_astModule.type_ignores.extend(listTypeIgnore)
241
- ast.fix_missing_locations(self_astModule)
242
-
243
- def appendPrologue(self, astModule: ast.Module | None = None, statement: Sequence[ast.stmt] | ast.stmt | None = None, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
244
- """Append one or more statements to `prologue`."""
245
- self._append_astModule(self.prologue, astModule, statement, type_ignores)
246
-
247
- def appendEpilogue(self, astModule: ast.Module | None = None, statement: Sequence[ast.stmt] | ast.stmt | None = None, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
248
- """Append one or more statements to `epilogue`."""
249
- self._append_astModule(self.epilogue, astModule, statement, type_ignores)
250
-
251
- def appendLauncher(self, astModule: ast.Module | None = None, statement: Sequence[ast.stmt] | ast.stmt | None = None, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
252
- """Append one or more statements to `launcher`."""
253
- self._append_astModule(self.launcher, astModule, statement, type_ignores)
254
-
255
- def appendIngredientsFunction(self, *ingredientsFunction: IngredientsFunction) -> None:
256
- """Append one or more `IngredientsFunction`."""
257
- for allegedIngredientsFunction in ingredientsFunction:
258
- self.listIngredientsFunctions.append(allegedIngredientsFunction)
259
-
260
- def removeImportFromModule(self, moduleWithLogicalPath: str_nameDOTname) -> None:
261
- self.removeImportFrom(moduleWithLogicalPath, None, None)
262
- """Remove all imports from a specific module."""
263
-
264
- def removeImportFrom(self, moduleWithLogicalPath: str_nameDOTname, name: ast_Identifier | None, asname: ast_Identifier | None = None) -> None:
265
- """
266
- This method modifies all `LedgerOfImports` in this `IngredientsModule` and all `IngredientsFunction` in `listIngredientsFunctions`.
267
- It is not a "blacklist", so the `import from` could be added after this modification.
268
- """
269
- self.imports.removeImportFrom(moduleWithLogicalPath, name, asname)
270
- for ingredientsFunction in self.listIngredientsFunctions:
271
- ingredientsFunction.imports.removeImportFrom(moduleWithLogicalPath, name, asname)
272
-
273
- def _consolidatedLedger(self) -> LedgerOfImports:
274
- """Consolidate all ledgers of imports."""
275
- sherpaLedger = LedgerOfImports()
276
- listLedgers: list[LedgerOfImports] = [self.imports]
277
- for ingredientsFunction in self.listIngredientsFunctions:
278
- listLedgers.append(ingredientsFunction.imports)
279
- sherpaLedger.update(*listLedgers)
280
- return sherpaLedger
281
-
282
- @property
283
- def list_astImportImportFrom(self) -> list[ast.Import | ast.ImportFrom]:
284
- return self._consolidatedLedger().makeList_ast()
285
-
286
- @property
287
- def body(self) -> list[ast.stmt]:
288
- list_stmt: list[ast.stmt] = []
289
- list_stmt.extend(self.list_astImportImportFrom)
290
- list_stmt.extend(self.prologue.body)
291
- for ingredientsFunction in self.listIngredientsFunctions:
292
- list_stmt.append(ingredientsFunction.astFunctionDef)
293
- list_stmt.extend(self.epilogue.body)
294
- list_stmt.extend(self.launcher.body)
295
- # TODO `launcher`, if it exists, must start with `if __name__ == '__main__':` and be indented
296
- return list_stmt
297
-
298
- @property
299
- def type_ignores(self) -> list[ast.TypeIgnore]:
300
- listTypeIgnore: list[ast.TypeIgnore] = self.supplemental_type_ignores
301
- listTypeIgnore.extend(self._consolidatedLedger().type_ignores)
302
- listTypeIgnore.extend(self.prologue.type_ignores)
303
- for ingredientsFunction in self.listIngredientsFunctions:
304
- listTypeIgnore.extend(ingredientsFunction.type_ignores)
305
- listTypeIgnore.extend(self.epilogue.type_ignores)
306
- listTypeIgnore.extend(self.launcher.type_ignores)
307
- return listTypeIgnore
308
-
309
31
  # Consolidate settings classes through inheritance https://github.com/hunterhogan/mapFolding/issues/15
310
32
  @dataclasses.dataclass
311
33
  class RecipeSynthesizeFlow:
@@ -531,7 +253,13 @@ class DeReConstructField2ast:
531
253
  self.ast_keyword_field__field = Make.keyword(self.name, self.astName)
532
254
  self.ast_nameDOTname = Make.Attribute(Make.Name(dataclassesDOTdataclassInstance_Identifier), self.name)
533
255
 
534
- sherpa = NodeTourist(IfThis.isAnnAssign_targetIs(IfThis.isName_Identifier(self.name)), Then.extractIt(DOT.annotation)).captureLastMatch(dataclassClassDef)
256
+ findThis = IfThis.isAnnAssign_targetIs(IfThis.isName_Identifier(self.name))
257
+
258
+ sherpa = NodeTourist(
259
+ findThis=findThis
260
+ , doThat=Then.extractIt(DOT.annotation)
261
+ ).captureLastMatch(dataclassClassDef)
262
+
535
263
  if sherpa is None: raise raiseIfNoneGitHubIssueNumber3
536
264
  else: self.astAnnotation = sherpa
537
265
 
@@ -544,7 +272,7 @@ class DeReConstructField2ast:
544
272
  self.ledger.addImportFrom_asStr(moduleWithLogicalPath, annotationType)
545
273
  self.ledger.addImportFrom_asStr(moduleWithLogicalPath, 'dtype')
546
274
  axesSubscript = Make.Subscript(Make.Name('tuple'), Make.Name('uint8'))
547
- dtype_asnameName: ast.Name = self.astAnnotation # type: ignore
275
+ dtype_asnameName: ast.Name = cast(ast.Name, self.astAnnotation)
548
276
  if dtype_asnameName.id == 'Array3D':
549
277
  axesSubscript = Make.Subscript(Make.Name('tuple'), Make.Tuple([Make.Name('uint8'), Make.Name('uint8'), Make.Name('uint8')]))
550
278
  ast_expr = Make.Subscript(Make.Name(annotationType), Make.Tuple([axesSubscript, Make.Subscript(Make.Name('dtype'), dtype_asnameName)]))
@@ -561,7 +289,7 @@ class DeReConstructField2ast:
561
289
  elif isinstance(self.astAnnotation, ast.Subscript):
562
290
  elementConstructor: ast_Identifier = self.metadata['elementConstructor']
563
291
  self.ledger.addImportFrom_asStr(dataclassesDOTdataclassLogicalPathModule, elementConstructor)
564
- takeTheTuple: ast.Tuple = deepcopy(self.astAnnotation.slice) # type: ignore
292
+ takeTheTuple = deepcopy(self.astAnnotation.slice)
565
293
  self.astAnnAssignConstructor = Make.AnnAssign(self.astName, self.astAnnotation, takeTheTuple)
566
294
  self.Z0Z_hack = (self.astAnnAssignConstructor, elementConstructor)
567
295
  if isinstance(self.astAnnotation, ast.Name):
@@ -15,7 +15,7 @@ from mapFolding.someAssemblyRequired import (
15
15
  )
16
16
  from mapFolding.someAssemblyRequired.RecipeJob import RecipeJobTheorem2Numba
17
17
  from mapFolding.someAssemblyRequired.toolboxNumba import parametersNumbaLight, SpicesJobNumba, decorateCallableWithNumba
18
- from mapFolding.someAssemblyRequired.transformationTools import dictionaryEstimates, write_astModule, makeInitializedComputationState
18
+ from mapFolding.someAssemblyRequired.transformationTools import write_astModule
19
19
  from mapFolding.syntheticModules.initializeCount import initializeGroupsOfFolds
20
20
  from mapFolding.dataBaskets import MapFoldingState
21
21
  from pathlib import PurePosixPath
@@ -77,7 +77,7 @@ if __name__ == '__main__':
77
77
  ast_argNumbaProgress = ast.arg(arg=spices.numbaProgressBarIdentifier, annotation=ast.Name(id=numba_progressPythonClass, ctx=ast.Load()))
78
78
  ingredientsFunction.astFunctionDef.args.args.append(ast_argNumbaProgress)
79
79
 
80
- findThis = IfThis.isAugAssign_targetIs(IfThis.isName_Identifier(job.shatteredDataclass.countingVariableName.id))
80
+ findThis = IfThis.isAugAssignAndTargetIs(IfThis.isName_Identifier(job.shatteredDataclass.countingVariableName.id))
81
81
  doThat = Then.replaceWith(Make.Expr(Make.Call(Make.Attribute(Make.Name(spices.numbaProgressBarIdentifier),'update'),[Make.Constant(1)])))
82
82
  countWithProgressBar = NodeChanger(findThis, doThat)
83
83
  countWithProgressBar.visit(ingredientsFunction.astFunctionDef)
@@ -131,19 +131,19 @@ def move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsFunction: Ingre
131
131
  ImaAnnAssign, elementConstructor = job.shatteredDataclass.Z0Z_field2AnnAssign[ast_arg.arg]
132
132
  match elementConstructor:
133
133
  case 'scalar':
134
- ImaAnnAssign.value.args[0].value = int(job.state.__dict__[ast_arg.arg]) # type: ignore
134
+ cast(ast.Constant, cast(ast.Call, ImaAnnAssign.value).args[0]).value = int(job.state.__dict__[ast_arg.arg])
135
135
  case 'array':
136
136
  dataAsStrRLE: str = autoDecodingRLE(job.state.__dict__[ast_arg.arg], True)
137
137
  dataAs_astExpr: ast.expr = cast(ast.Expr, ast.parse(dataAsStrRLE).body[0]).value
138
- ImaAnnAssign.value.args = [dataAs_astExpr] # type: ignore
138
+ cast(ast.Call, ImaAnnAssign.value).args = [dataAs_astExpr]
139
139
  case _:
140
140
  list_exprDOTannotation: list[ast.expr] = []
141
141
  list_exprDOTvalue: list[ast.expr] = []
142
142
  for dimension in job.state.mapShape:
143
143
  list_exprDOTannotation.append(Make.Name(elementConstructor))
144
144
  list_exprDOTvalue.append(Make.Call(Make.Name(elementConstructor), [Make.Constant(dimension)]))
145
- ImaAnnAssign.annotation.slice.elts = list_exprDOTannotation # type: ignore
146
- ImaAnnAssign.value.elts = list_exprDOTvalue # type: ignore
145
+ cast(ast.Tuple, cast(ast.Subscript, cast(ast.AnnAssign, ImaAnnAssign).annotation).slice).elts = list_exprDOTannotation
146
+ cast(ast.Tuple, ImaAnnAssign.value).elts = list_exprDOTvalue
147
147
 
148
148
  ingredientsFunction.astFunctionDef.body.insert(0, ImaAnnAssign)
149
149