mapFolding 0.8.3__py3-none-any.whl → 0.8.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mapFolding/__init__.py +2 -2
- mapFolding/basecamp.py +11 -5
- mapFolding/filesystem.py +134 -109
- mapFolding/oeis.py +1 -1
- mapFolding/someAssemblyRequired/__init__.py +37 -18
- mapFolding/someAssemblyRequired/_theTypes.py +35 -0
- mapFolding/someAssemblyRequired/_tool_Make.py +92 -0
- mapFolding/someAssemblyRequired/_tool_Then.py +65 -0
- mapFolding/someAssemblyRequired/_toolboxAntecedents.py +326 -0
- mapFolding/someAssemblyRequired/_toolboxContainers.py +306 -0
- mapFolding/someAssemblyRequired/_toolboxPython.py +76 -0
- mapFolding/someAssemblyRequired/ingredientsNumba.py +17 -24
- mapFolding/someAssemblyRequired/synthesizeNumbaFlow.py +114 -169
- mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +247 -0
- mapFolding/someAssemblyRequired/transformDataStructures.py +167 -100
- mapFolding/someAssemblyRequired/transformationTools.py +63 -685
- mapFolding/syntheticModules/numbaCount_doTheNeedful.py +36 -33
- mapFolding/theDao.py +13 -11
- mapFolding/theSSOT.py +69 -112
- {mapfolding-0.8.3.dist-info → mapfolding-0.8.4.dist-info}/METADATA +2 -1
- mapfolding-0.8.4.dist-info/RECORD +49 -0
- {mapfolding-0.8.3.dist-info → mapfolding-0.8.4.dist-info}/WHEEL +1 -1
- tests/conftest.py +34 -29
- tests/test_computations.py +40 -31
- tests/test_filesystem.py +3 -3
- mapFolding/someAssemblyRequired/synthesizeNumbaJobVESTIGIAL.py +0 -413
- mapfolding-0.8.3.dist-info/RECORD +0 -43
- {mapfolding-0.8.3.dist-info → mapfolding-0.8.4.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.8.3.dist-info → mapfolding-0.8.4.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.8.3.dist-info → mapfolding-0.8.4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
from collections.abc import Callable, Container
|
|
2
|
+
from mapFolding.someAssemblyRequired import ast_expr_Slice, ast_Identifier, astClassHasDOTnameNotName, astClassHasDOTtarget, astClassHasDOTvalue, ImaAnnotationType, typeCertified
|
|
3
|
+
from typing import Any, overload, TypeGuard
|
|
4
|
+
import ast
|
|
5
|
+
|
|
6
|
+
Ima_targetType = ast.AST
|
|
7
|
+
|
|
8
|
+
class 又:
|
|
9
|
+
@staticmethod
|
|
10
|
+
@overload
|
|
11
|
+
def annotation(predicate: Callable[[ImaAnnotationType], ast.AST | ast_Identifier]) -> Callable[[ast.AnnAssign | ast.arg], ast.AST | ast_Identifier]:...
|
|
12
|
+
@staticmethod
|
|
13
|
+
@overload
|
|
14
|
+
def annotation(predicate: Callable[[ImaAnnotationType], TypeGuard[ImaAnnotationType] | bool]) -> Callable[[ast.AnnAssign | ast.arg], TypeGuard[ast.AnnAssign] | TypeGuard[ast.arg] | bool]:...
|
|
15
|
+
@staticmethod
|
|
16
|
+
def annotation(predicate: Callable[[ImaAnnotationType], TypeGuard[ImaAnnotationType] | ast.AST | ast_Identifier | bool]) -> Callable[[ast.AnnAssign | ast.arg], TypeGuard[ast.AnnAssign] | TypeGuard[ast.arg] | ast.AST | ast_Identifier | bool]:
|
|
17
|
+
@overload
|
|
18
|
+
def workhorse(node: ast.AnnAssign | ast.arg) -> ast.AST | ast_Identifier:...
|
|
19
|
+
@overload
|
|
20
|
+
def workhorse(node: ast.AnnAssign | ast.arg) -> TypeGuard[ast.AnnAssign] | TypeGuard[ast.arg] | bool:...
|
|
21
|
+
def workhorse(node: ast.AnnAssign | ast.arg) -> TypeGuard[ast.AnnAssign] | TypeGuard[ast.arg] | ast.AST | ast_Identifier | bool:
|
|
22
|
+
ImaAnnotation = node.annotation
|
|
23
|
+
if ImaAnnotation is None: return False
|
|
24
|
+
assert be.Attribute(ImaAnnotation) or be.Constant(ImaAnnotation) or be.Name(ImaAnnotation) or be.Subscript(ImaAnnotation)
|
|
25
|
+
# assert be.Annotation(ImaAnnotation)
|
|
26
|
+
return predicate(ImaAnnotation)
|
|
27
|
+
return workhorse
|
|
28
|
+
@staticmethod
|
|
29
|
+
@overload
|
|
30
|
+
def arg(predicate: Callable[[ast_Identifier], ast.AST | ast_Identifier]) -> Callable[[ast.arg | ast.keyword], ast.AST | ast_Identifier]:...
|
|
31
|
+
@staticmethod
|
|
32
|
+
@overload
|
|
33
|
+
def arg(predicate: Callable[[ast_Identifier], TypeGuard[ast_Identifier] | bool]) -> Callable[[ast.arg | ast.keyword], TypeGuard[ast.arg] | TypeGuard[ast.keyword] | bool]:...
|
|
34
|
+
@staticmethod
|
|
35
|
+
def arg(predicate: Callable[[ast_Identifier], TypeGuard[ast_Identifier] | ast.AST | ast_Identifier | bool]) -> Callable[[ast.arg | ast.keyword], TypeGuard[ast.arg] | TypeGuard[ast.keyword] | ast.AST | ast_Identifier | bool]:
|
|
36
|
+
@overload
|
|
37
|
+
def workhorse(node: ast.arg | ast.keyword) -> ast.AST | ast_Identifier:...
|
|
38
|
+
@overload
|
|
39
|
+
def workhorse(node: ast.arg | ast.keyword) -> TypeGuard[ast.arg] | TypeGuard[ast.keyword] | bool:...
|
|
40
|
+
def workhorse(node: ast.arg | ast.keyword) -> TypeGuard[ast.arg] | TypeGuard[ast.keyword] | ast.AST | ast_Identifier | bool:
|
|
41
|
+
Ima_arg = node.arg
|
|
42
|
+
if Ima_arg is None: return False
|
|
43
|
+
return predicate(Ima_arg)
|
|
44
|
+
return workhorse
|
|
45
|
+
@staticmethod
|
|
46
|
+
def asname(predicate: Callable[[ast_Identifier | None], TypeGuard[ast_Identifier] | bool]) -> Callable[[ast.alias], TypeGuard[ast.alias] | bool]:
|
|
47
|
+
return lambda node: predicate(node.asname)
|
|
48
|
+
@staticmethod
|
|
49
|
+
def attr(predicate: Callable[[ast_Identifier], TypeGuard[ast_Identifier] | bool]) -> Callable[[ast.Attribute], TypeGuard[ast.Attribute] | bool]:
|
|
50
|
+
return lambda node: predicate(node.attr)
|
|
51
|
+
@staticmethod
|
|
52
|
+
def func(predicate: Callable[[ast.AST], TypeGuard[ast.AST] | bool]) -> Callable[[ast.Call], TypeGuard[ast.Call] | bool]:
|
|
53
|
+
return lambda node: predicate(node.func)
|
|
54
|
+
@staticmethod
|
|
55
|
+
def id(predicate: Callable[[ast_Identifier], TypeGuard[ast_Identifier] | bool]) -> Callable[[ast.Name], TypeGuard[ast.Name] | bool]:
|
|
56
|
+
return lambda node: predicate(node.id)
|
|
57
|
+
@staticmethod
|
|
58
|
+
def module(predicate: Callable[[ast_Identifier | None], TypeGuard[ast_Identifier] | bool]) -> Callable[[ast.ImportFrom], TypeGuard[ast.ImportFrom] | bool]:
|
|
59
|
+
return lambda node: predicate(node.module)
|
|
60
|
+
@staticmethod
|
|
61
|
+
def name(predicate: Callable[[ast_Identifier], TypeGuard[ast_Identifier] | bool]) -> Callable[[astClassHasDOTnameNotName], TypeGuard[astClassHasDOTnameNotName] | bool]:
|
|
62
|
+
return lambda node: predicate(node.name)
|
|
63
|
+
@staticmethod
|
|
64
|
+
def slice(predicate: Callable[[ast_expr_Slice], TypeGuard[ast_expr_Slice] | bool]) -> Callable[[ast.Subscript], TypeGuard[ast.Subscript] | bool]:
|
|
65
|
+
return lambda node: predicate(node.slice)
|
|
66
|
+
@staticmethod
|
|
67
|
+
def target(predicate: Callable[[ast.AST], TypeGuard[ast.AST] | bool]) -> Callable[[astClassHasDOTtarget], TypeGuard[astClassHasDOTtarget] | bool]:
|
|
68
|
+
return lambda node: predicate(node.target)
|
|
69
|
+
@staticmethod
|
|
70
|
+
def value(predicate: Callable[[ast.AST], TypeGuard[ast.AST] | bool]) -> Callable[[astClassHasDOTvalue], TypeGuard[astClassHasDOTvalue] | bool]:
|
|
71
|
+
def workhorse(node: astClassHasDOTvalue) -> TypeGuard[astClassHasDOTvalue] | bool:
|
|
72
|
+
ImaValue = node.value
|
|
73
|
+
if ImaValue is None: return False
|
|
74
|
+
return predicate(ImaValue)
|
|
75
|
+
return workhorse
|
|
76
|
+
|
|
77
|
+
class be:
|
|
78
|
+
@staticmethod
|
|
79
|
+
def _typeCertified(antecedent: type[typeCertified]) -> Callable[[Any | None], TypeGuard[typeCertified]]:
|
|
80
|
+
def workhorse(node: Any | None) -> TypeGuard[typeCertified]:
|
|
81
|
+
return isinstance(node, antecedent)
|
|
82
|
+
return workhorse
|
|
83
|
+
@staticmethod
|
|
84
|
+
def AnnAssign(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.AnnAssign)(node)
|
|
85
|
+
# 'TypeVar "typeCertified" appears only once in generic function signature. Use "object" instead Pylance(reportInvalidTypeVarUse)"' HOW THE FUCK IS THAT INVALID WHEN IT IS WORKING PERFECTLY TO PASS THE TYPE INFORMATION--IN YOUR FUCKING STATIC TYPE CHECKER, PYLANCE!!!! Fuck you, and fuck your pretentious language.
|
|
86
|
+
@staticmethod
|
|
87
|
+
def arg(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.arg)(node)
|
|
88
|
+
|
|
89
|
+
# @staticmethod
|
|
90
|
+
# def Annotation(node: ast.AST) -> TypeGuard[object] | bool:
|
|
91
|
+
# if be.Attribute(node):
|
|
92
|
+
# return be.Attribute(node)
|
|
93
|
+
# elif be.Constant(node):
|
|
94
|
+
# return be.Constant(node)
|
|
95
|
+
# elif be.Name(node):
|
|
96
|
+
# return be.Name(node)
|
|
97
|
+
# elif be.Subscript(node):
|
|
98
|
+
# return be.Subscript(node)
|
|
99
|
+
# else:
|
|
100
|
+
# return False
|
|
101
|
+
# return be.Attribute(node) or be.Constant(node) or be.Name(node) or be.Subscript(node)
|
|
102
|
+
|
|
103
|
+
@staticmethod
|
|
104
|
+
def Assign(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Assign)(node)
|
|
105
|
+
@staticmethod
|
|
106
|
+
def Attribute(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Attribute)(node)
|
|
107
|
+
@staticmethod
|
|
108
|
+
def AugAssign(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.AugAssign)(node)
|
|
109
|
+
@staticmethod
|
|
110
|
+
def BoolOp(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.BoolOp)(node)
|
|
111
|
+
@staticmethod
|
|
112
|
+
def Call(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Call)(node)
|
|
113
|
+
@staticmethod
|
|
114
|
+
def ClassDef(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.ClassDef)(node)
|
|
115
|
+
@staticmethod
|
|
116
|
+
def Compare(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Compare)(node)
|
|
117
|
+
@staticmethod
|
|
118
|
+
def Constant(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Constant)(node)
|
|
119
|
+
@staticmethod
|
|
120
|
+
def Expr(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Expr)(node)
|
|
121
|
+
@staticmethod
|
|
122
|
+
def FunctionDef(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.FunctionDef)(node)
|
|
123
|
+
@staticmethod
|
|
124
|
+
def Import(node: ast.AST) -> TypeGuard[ast.Import]: return be._typeCertified(ast.Import)(node)
|
|
125
|
+
@staticmethod
|
|
126
|
+
def ImportFrom(node: ast.AST) -> TypeGuard[ast.ImportFrom]: return be._typeCertified(ast.ImportFrom)(node)
|
|
127
|
+
@staticmethod
|
|
128
|
+
def keyword(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.keyword)(node)
|
|
129
|
+
@staticmethod
|
|
130
|
+
def Module(node: ast.AST) -> TypeGuard[typeCertified]: return be._typeCertified(ast.Module)(node)
|
|
131
|
+
@staticmethod
|
|
132
|
+
def Name(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Name)(node)
|
|
133
|
+
@staticmethod
|
|
134
|
+
def Return(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Return)(node)
|
|
135
|
+
@staticmethod
|
|
136
|
+
def Starred(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Starred)(node)
|
|
137
|
+
@staticmethod
|
|
138
|
+
def Subscript(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Subscript)(node)
|
|
139
|
+
@staticmethod
|
|
140
|
+
def UnaryOp(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.UnaryOp)(node)
|
|
141
|
+
|
|
142
|
+
class ifThis:
|
|
143
|
+
@staticmethod
|
|
144
|
+
def equals(this: Any) -> Callable[[Any], TypeGuard[Any] | bool]:
|
|
145
|
+
return lambda node: node == this
|
|
146
|
+
@staticmethod
|
|
147
|
+
def isAssignAndTargets0Is(targets0Predicate: Callable[[ast.AST], bool]) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
148
|
+
"""node is Assign and node.targets[0] matches `targets0Predicate`."""
|
|
149
|
+
return lambda node: be.Assign(node) and targets0Predicate(node.targets[0])
|
|
150
|
+
@staticmethod
|
|
151
|
+
def isAssignAndValueIs(valuePredicate: Callable[[ast.AST], bool]) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
152
|
+
"""node is ast.Assign and node.value matches `valuePredicate`.
|
|
153
|
+
Parameters:
|
|
154
|
+
valuePredicate: Function that evaluates the value of the assignment
|
|
155
|
+
Returns:
|
|
156
|
+
predicate: matches assignments with values meeting the criteria
|
|
157
|
+
"""
|
|
158
|
+
return lambda node: be.Assign(node) and 又.value(valuePredicate)(node)
|
|
159
|
+
@staticmethod
|
|
160
|
+
def isFunctionDef_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
161
|
+
return lambda node: be.FunctionDef(node) and 又.name(ifThis._Identifier(identifier))(node)
|
|
162
|
+
@staticmethod
|
|
163
|
+
def isArgument_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
164
|
+
return lambda node: (be.arg(node) or be.keyword(node)) and 又.arg(ifThis._Identifier(identifier))(node)
|
|
165
|
+
@staticmethod
|
|
166
|
+
def is_keyword_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
167
|
+
"""see also `isArgument_Identifier`"""
|
|
168
|
+
return lambda node: be.keyword(node) and 又.arg(ifThis._Identifier(identifier))(node)
|
|
169
|
+
@staticmethod
|
|
170
|
+
def is_arg_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
171
|
+
"""see also `isArgument_Identifier`"""
|
|
172
|
+
return lambda node: be.arg(node) and 又.arg(ifThis._Identifier(identifier))(node)
|
|
173
|
+
@staticmethod
|
|
174
|
+
def isClassDef_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
175
|
+
return lambda node: be.ClassDef(node) and 又.name(ifThis._Identifier(identifier))(node)
|
|
176
|
+
@staticmethod
|
|
177
|
+
def isAssignAndValueIsCall_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
178
|
+
return lambda node: be.Assign(node) and 又.value(ifThis.isCall_Identifier(identifier))(node)
|
|
179
|
+
@staticmethod
|
|
180
|
+
def isAssignAndValueIsCallAttributeNamespace_Identifier(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
181
|
+
return ifThis.isAssignAndValueIs(ifThis.isCallAttributeNamespace_Identifier(namespace, identifier))
|
|
182
|
+
@staticmethod
|
|
183
|
+
def is_keywordAndValueIsConstant(node: ast.AST) -> TypeGuard[object]:
|
|
184
|
+
return be.keyword(node) and 又.value(be.Constant)(node)
|
|
185
|
+
@staticmethod
|
|
186
|
+
def is_keyword_IdentifierEqualsConstantValue(identifier: ast_Identifier, ConstantValue: Any) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
187
|
+
return lambda node: ifThis.is_keyword_Identifier(identifier)(node) and ifThis.is_keywordAndValueIsConstant(node) and 又.value(ifThis.isConstantEquals(ConstantValue))(node)
|
|
188
|
+
"""
|
|
189
|
+
Argument of type "typeCertified@isAnnAssign_targetIs" cannot be assigned to parameter of type "astClassHasDOTtarget"
|
|
190
|
+
Type "typeCertified@isAnnAssign_targetIs" is not assignable to type "astClassHasDOTtarget"
|
|
191
|
+
"object*" is not assignable to "AnnAssign"
|
|
192
|
+
"object*" is not assignable to "AsyncFor"
|
|
193
|
+
"object*" is not assignable to "AugAssign"
|
|
194
|
+
"object*" is not assignable to "comprehension"
|
|
195
|
+
"object*" is not assignable to "For"
|
|
196
|
+
"object*" is not assignable to "NamedExpr"
|
|
197
|
+
"""
|
|
198
|
+
@staticmethod
|
|
199
|
+
def isAnnAssign_targetIs(targetPredicate: Callable[[Ima_targetType], TypeGuard[Ima_targetType] | bool]) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
200
|
+
def workhorse(node: ast.AST) -> TypeGuard[object] | bool:
|
|
201
|
+
return be.AnnAssign(node) and 又.target(targetPredicate)(node)
|
|
202
|
+
return workhorse
|
|
203
|
+
@staticmethod
|
|
204
|
+
def isAnnAssignAndAnnotationIsName(node: ast.AST) -> TypeGuard[object] | bool:
|
|
205
|
+
return be.AnnAssign(node) and 又.annotation(be.Name)(node)
|
|
206
|
+
@staticmethod
|
|
207
|
+
def isAugAssign_targetIs(targetPredicate: Callable[[Ima_targetType], TypeGuard[Ima_targetType] | bool]) -> Callable[[ast.AST], TypeGuard[typeCertified] | bool]:
|
|
208
|
+
def workhorse(node: ast.AST) -> TypeGuard[typeCertified] | bool:
|
|
209
|
+
return be.AugAssign(node) and 又.target(targetPredicate)(node)
|
|
210
|
+
return workhorse
|
|
211
|
+
|
|
212
|
+
@staticmethod
|
|
213
|
+
def isAnyCompare(node: ast.AST) -> TypeGuard[object]:
|
|
214
|
+
return be.Compare(node) or be.BoolOp(node)
|
|
215
|
+
@staticmethod
|
|
216
|
+
def isConstantEquals(value: Any) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
217
|
+
return lambda node: be.Constant(node) and 又.value(ifThis.equals(value))(node)
|
|
218
|
+
@staticmethod
|
|
219
|
+
def isReturnAnyCompare(node: ast.AST) -> TypeGuard[object] | bool:
|
|
220
|
+
return be.Return(node) and 又.value(ifThis.isAnyCompare)(node)
|
|
221
|
+
@staticmethod
|
|
222
|
+
def isReturnUnaryOp(node: ast.AST) -> TypeGuard[object] | bool:
|
|
223
|
+
return be.Return(node) and 又.value(be.UnaryOp)(node)
|
|
224
|
+
|
|
225
|
+
# ================================================================
|
|
226
|
+
# Nested identifier
|
|
227
|
+
@staticmethod
|
|
228
|
+
def _nestedJunction_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
229
|
+
def workhorse(node: ast.AST) -> TypeGuard[object] | bool:
|
|
230
|
+
return ifThis.isName_Identifier(identifier)(node) or ifThis.isAttribute_Identifier(identifier)(node) or ifThis.isSubscript_Identifier(identifier)(node) or ifThis.isStarred_Identifier(identifier)(node)
|
|
231
|
+
return workhorse
|
|
232
|
+
@staticmethod
|
|
233
|
+
def isAttribute_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
234
|
+
"""node is `ast.Attribute` and the top-level `ast.Name` is `identifier`"""
|
|
235
|
+
def workhorse(node: ast.AST) -> TypeGuard[object]:
|
|
236
|
+
return be.Attribute(node) and 又.value(ifThis._nestedJunction_Identifier(identifier))(node)
|
|
237
|
+
return workhorse
|
|
238
|
+
@staticmethod
|
|
239
|
+
def isStarred_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
240
|
+
"""node is `ast.Starred` and the top-level `ast.Name` is `identifier`"""
|
|
241
|
+
def workhorse(node: ast.AST) -> TypeGuard[object]:
|
|
242
|
+
return be.Starred(node) and 又.value(ifThis._nestedJunction_Identifier(identifier))(node)
|
|
243
|
+
return workhorse
|
|
244
|
+
@staticmethod
|
|
245
|
+
def isSubscript_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
246
|
+
"""node is `ast.Subscript` and the top-level `ast.Name` is `identifier`"""
|
|
247
|
+
def workhorse(node: ast.AST) -> TypeGuard[object]:
|
|
248
|
+
return be.Subscript(node) and 又.value(ifThis._nestedJunction_Identifier(identifier))(node)
|
|
249
|
+
return workhorse
|
|
250
|
+
# ================================================================
|
|
251
|
+
|
|
252
|
+
@staticmethod
|
|
253
|
+
def Z0Z_unparseIs(astAST: ast.AST) -> Callable[[ast.AST], bool]:
|
|
254
|
+
def workhorse(node: ast.AST) -> bool: return ast.unparse(node) == ast.unparse(astAST)
|
|
255
|
+
return workhorse
|
|
256
|
+
|
|
257
|
+
# ================================================================
|
|
258
|
+
# NOT used
|
|
259
|
+
# TODO Does this work?
|
|
260
|
+
@staticmethod
|
|
261
|
+
def Z0Z_matchesAtLeast1Descendant(predicate: Callable[[ast.AST], bool]) -> Callable[[ast.AST], bool]:
|
|
262
|
+
"""Create a predicate that returns True if any descendant of the node matches the given predicate."""
|
|
263
|
+
return lambda node: not ifThis.matchesNoDescendant(predicate)(node)
|
|
264
|
+
# ================================================================
|
|
265
|
+
# MORE function inlining
|
|
266
|
+
@staticmethod
|
|
267
|
+
def onlyReturnAnyCompare(astFunctionDef: ast.AST) -> TypeGuard[object]:
|
|
268
|
+
return be.FunctionDef(astFunctionDef) and len(astFunctionDef.body) == 1 and ifThis.isReturnAnyCompare(astFunctionDef.body[0])
|
|
269
|
+
# For function inlining
|
|
270
|
+
@staticmethod
|
|
271
|
+
def onlyReturnUnaryOp(astFunctionDef: ast.AST) -> TypeGuard[object]:
|
|
272
|
+
return be.FunctionDef(astFunctionDef) and len(astFunctionDef.body) == 1 and ifThis.isReturnUnaryOp(astFunctionDef.body[0])
|
|
273
|
+
# ================================================================
|
|
274
|
+
# These are used by other functions
|
|
275
|
+
@staticmethod
|
|
276
|
+
def isCallAttributeNamespace_Identifier(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
277
|
+
return lambda node: be.Call(node) and 又.func(ifThis.isAttributeNamespace_Identifier(namespace, identifier))(node)
|
|
278
|
+
@staticmethod
|
|
279
|
+
def isName_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
280
|
+
return lambda node: be.Name(node) and 又.id(ifThis._Identifier(identifier))(node)
|
|
281
|
+
@staticmethod
|
|
282
|
+
def isCall_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
283
|
+
return lambda node: be.Call(node) and 又.func(ifThis.isName_Identifier(identifier))(node)
|
|
284
|
+
# ================================================================
|
|
285
|
+
@staticmethod
|
|
286
|
+
def matchesMeButNotAnyDescendant(predicate: Callable[[ast.AST], bool]) -> Callable[[ast.AST], bool]:
|
|
287
|
+
"""Create a predicate that returns True if the node matches but none of its descendants match the predicate."""
|
|
288
|
+
return lambda node: predicate(node) and ifThis.matchesNoDescendant(predicate)(node)
|
|
289
|
+
@staticmethod
|
|
290
|
+
def matchesNoDescendant(predicate: Callable[[ast.AST], bool]) -> Callable[[ast.AST], bool]:
|
|
291
|
+
"""Create a predicate that returns True if no descendant of the node matches the given predicate."""
|
|
292
|
+
def workhorse(node: ast.AST) -> bool:
|
|
293
|
+
for descendant in ast.walk(node):
|
|
294
|
+
if descendant is not node and predicate(descendant):
|
|
295
|
+
return False
|
|
296
|
+
return True
|
|
297
|
+
return workhorse
|
|
298
|
+
|
|
299
|
+
@staticmethod
|
|
300
|
+
def CallDoesNotCallItself(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
301
|
+
"""If `namespace` is not applicable to your case, then call with `namespace=""`."""
|
|
302
|
+
return lambda node: ifThis.matchesMeButNotAnyDescendant(ifThis.CallReallyIs(namespace, identifier))(node)
|
|
303
|
+
@staticmethod
|
|
304
|
+
def CallReallyIs(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
305
|
+
return ifThis.isCall_Identifier(identifier) or ifThis.isCallAttributeNamespace_Identifier(namespace, identifier)
|
|
306
|
+
@staticmethod
|
|
307
|
+
def isAttributeNamespace_Identifier(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
308
|
+
return lambda node: ifThis.isAttributeName(node) and 又.value(ifThis.isName_Identifier(namespace))(node) and 又.attr(ifThis._Identifier(identifier))(node)
|
|
309
|
+
@staticmethod
|
|
310
|
+
def _Identifier(identifier: ast_Identifier) -> Callable[[ast_Identifier | None], TypeGuard[ast_Identifier] | bool]:
|
|
311
|
+
return lambda node: node == identifier
|
|
312
|
+
@staticmethod
|
|
313
|
+
def isAttributeName(node: ast.AST) -> TypeGuard[object]:
|
|
314
|
+
""" Displayed as Name.attribute."""
|
|
315
|
+
return be.Attribute(node) and 又.value(be.Name)(node)
|
|
316
|
+
|
|
317
|
+
@staticmethod
|
|
318
|
+
def isCallToName(node: ast.AST) -> TypeGuard[object]:
|
|
319
|
+
return be.Call(node) and 又.func(be.Name)(node)
|
|
320
|
+
@staticmethod
|
|
321
|
+
def ast_IdentifierIn(container: Container[ast_Identifier]) -> Callable[[ast_Identifier], TypeGuard[ast_Identifier] | bool]:
|
|
322
|
+
return lambda node: node in container
|
|
323
|
+
# This bullshit is for the crappy function inliner I made.
|
|
324
|
+
@staticmethod
|
|
325
|
+
def CallDoesNotCallItselfAndNameDOTidIsIn(container: Container[ast_Identifier]) -> Callable[[ast.AST], TypeGuard[object] | bool]:
|
|
326
|
+
return lambda node: ifThis.isCallToName(node) and 又.func(又.id(ifThis.ast_IdentifierIn(container)))(node) and ifThis.CallDoesNotCallItself("", node.func.id)(node)
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Container classes for AST transformations and code synthesis.
|
|
3
|
+
|
|
4
|
+
This module provides container classes used in the AST transformation process
|
|
5
|
+
and code synthesis workflows. It acts as a dependency boundary to prevent
|
|
6
|
+
circular imports while providing reusable data structures.
|
|
7
|
+
"""
|
|
8
|
+
from collections import defaultdict
|
|
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
|
|
12
|
+
from pathlib import Path, PurePosixPath
|
|
13
|
+
from Z0Z_tools import updateExtendPolishDictionaryLists
|
|
14
|
+
import ast
|
|
15
|
+
import dataclasses
|
|
16
|
+
|
|
17
|
+
class LedgerOfImports:
|
|
18
|
+
# TODO When resolving the ledger of imports, remove self-referential imports
|
|
19
|
+
# TODO TypeIgnore :/
|
|
20
|
+
|
|
21
|
+
def __init__(self, startWith: ast.AST | None = None) -> None:
|
|
22
|
+
self.dictionaryImportFrom: dict[str_nameDOTname, list[tuple[ast_Identifier, ast_Identifier | None]]] = defaultdict(list)
|
|
23
|
+
self.listImport: list[str_nameDOTname] = []
|
|
24
|
+
if startWith:
|
|
25
|
+
self.walkThis(startWith)
|
|
26
|
+
|
|
27
|
+
def addAst(self, astImport____: ast.Import | ast.ImportFrom) -> None:
|
|
28
|
+
assert isinstance(astImport____, (ast.Import, ast.ImportFrom)), f"I received {type(astImport____) = }, but I can only accept {ast.Import} and {ast.ImportFrom}."
|
|
29
|
+
if be.Import(astImport____):
|
|
30
|
+
for alias in astImport____.names:
|
|
31
|
+
self.listImport.append(alias.name)
|
|
32
|
+
elif be.ImportFrom(astImport____):
|
|
33
|
+
# TODO fix the mess created by `None` means '.'. I need a `str_nameDOTname` to replace '.'
|
|
34
|
+
if astImport____.module is None:
|
|
35
|
+
astImport____.module = '.'
|
|
36
|
+
for alias in astImport____.names:
|
|
37
|
+
self.dictionaryImportFrom[astImport____.module].append((alias.name, alias.asname))
|
|
38
|
+
|
|
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))
|
|
44
|
+
|
|
45
|
+
def exportListModuleIdentifiers(self) -> list[ast_Identifier]:
|
|
46
|
+
listModuleIdentifiers: list[ast_Identifier] = list(self.dictionaryImportFrom.keys())
|
|
47
|
+
listModuleIdentifiers.extend(self.listImport)
|
|
48
|
+
return sorted(set(listModuleIdentifiers))
|
|
49
|
+
|
|
50
|
+
def makeList_ast(self) -> list[ast.ImportFrom | ast.Import]:
|
|
51
|
+
listImportFrom: list[ast.ImportFrom] = []
|
|
52
|
+
for moduleIdentifier, listOfNameTuples in sorted(self.dictionaryImportFrom.items()):
|
|
53
|
+
listOfNameTuples = sorted(list(set(listOfNameTuples)), key=lambda nameTuple: nameTuple[0])
|
|
54
|
+
list_alias: list[ast.alias] = []
|
|
55
|
+
for name, asname in listOfNameTuples:
|
|
56
|
+
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))]
|
|
59
|
+
return listImportFrom + list_astImport
|
|
60
|
+
|
|
61
|
+
def update(self, *fromLedger: 'LedgerOfImports') -> None:
|
|
62
|
+
"""Update this ledger with imports from one or more other ledgers.
|
|
63
|
+
Parameters:
|
|
64
|
+
*fromLedger: One or more other `LedgerOfImports` objects from which to merge.
|
|
65
|
+
"""
|
|
66
|
+
self.dictionaryImportFrom = updateExtendPolishDictionaryLists(self.dictionaryImportFrom, *(ledger.dictionaryImportFrom for ledger in fromLedger), destroyDuplicates=True, reorderLists=True)
|
|
67
|
+
for ledger in fromLedger:
|
|
68
|
+
self.listImport.extend(ledger.listImport)
|
|
69
|
+
|
|
70
|
+
def walkThis(self, walkThis: ast.AST) -> None:
|
|
71
|
+
for nodeBuffalo in ast.walk(walkThis):
|
|
72
|
+
if isinstance(nodeBuffalo, (ast.Import, ast.ImportFrom)):
|
|
73
|
+
self.addAst(nodeBuffalo)
|
|
74
|
+
|
|
75
|
+
@dataclasses.dataclass
|
|
76
|
+
class IngredientsFunction:
|
|
77
|
+
"""Everything necessary to integrate a function into a module should be here.
|
|
78
|
+
Parameters:
|
|
79
|
+
astFunctionDef: hint `Make.astFunctionDef()`
|
|
80
|
+
"""
|
|
81
|
+
astFunctionDef: ast.FunctionDef
|
|
82
|
+
imports: LedgerOfImports = dataclasses.field(default_factory=LedgerOfImports)
|
|
83
|
+
type_ignores: list[ast.TypeIgnore] = dataclasses.field(default_factory=list)
|
|
84
|
+
|
|
85
|
+
@dataclasses.dataclass
|
|
86
|
+
class IngredientsModule:
|
|
87
|
+
"""Everything necessary to create one _logical_ `ast.Module` should be here.
|
|
88
|
+
Extrinsic qualities should _probably_ be handled externally.
|
|
89
|
+
|
|
90
|
+
Parameters:
|
|
91
|
+
ingredientsFunction (None): One or more `IngredientsFunction` that will appended to `listIngredientsFunctions`.
|
|
92
|
+
"""
|
|
93
|
+
ingredientsFunction: dataclasses.InitVar[Sequence[IngredientsFunction] | IngredientsFunction | None] = None
|
|
94
|
+
|
|
95
|
+
# init var with an existing module? method to deconstruct an existing module?
|
|
96
|
+
|
|
97
|
+
# `body` attribute of `ast.Module`
|
|
98
|
+
"""NOTE
|
|
99
|
+
- Bare statements in `prologue` and `epilogue` are not 'protected' by `if __name__ == '__main__':` so they will be executed merely by loading the module.
|
|
100
|
+
- The dataclass has methods for modifying `prologue`, `epilogue`, and `launcher`.
|
|
101
|
+
- 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.
|
|
102
|
+
"""
|
|
103
|
+
imports: LedgerOfImports = dataclasses.field(default_factory=LedgerOfImports)
|
|
104
|
+
"""Modify this field using the methods in `LedgerOfImports`."""
|
|
105
|
+
prologue: ast.Module = Make.Module([],[])
|
|
106
|
+
"""Statements after the imports and before the functions in listIngredientsFunctions."""
|
|
107
|
+
listIngredientsFunctions: list[IngredientsFunction] = dataclasses.field(default_factory=list)
|
|
108
|
+
epilogue: ast.Module = Make.Module([],[])
|
|
109
|
+
"""Statements after the functions in listIngredientsFunctions and before `launcher`."""
|
|
110
|
+
launcher: ast.Module = Make.Module([],[])
|
|
111
|
+
"""`if __name__ == '__main__':`"""
|
|
112
|
+
|
|
113
|
+
# `ast.TypeIgnore` statements to supplement those in other fields; `type_ignores` is a parameter for `ast.Module` constructor
|
|
114
|
+
supplemental_type_ignores: list[ast.TypeIgnore] = dataclasses.field(default_factory=list)
|
|
115
|
+
|
|
116
|
+
def __post_init__(self, ingredientsFunction: Sequence[IngredientsFunction] | IngredientsFunction | None = None) -> None:
|
|
117
|
+
if ingredientsFunction is not None:
|
|
118
|
+
if isinstance(ingredientsFunction, IngredientsFunction):
|
|
119
|
+
self.appendIngredientsFunction(ingredientsFunction)
|
|
120
|
+
else:
|
|
121
|
+
self.appendIngredientsFunction(*ingredientsFunction)
|
|
122
|
+
|
|
123
|
+
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:
|
|
124
|
+
"""Append one or more statements to `prologue`."""
|
|
125
|
+
list_body: list[ast.stmt] = []
|
|
126
|
+
listTypeIgnore: list[ast.TypeIgnore] = []
|
|
127
|
+
if astModule is not None and be.Module(astModule):
|
|
128
|
+
list_body.extend(astModule.body)
|
|
129
|
+
listTypeIgnore.extend(astModule.type_ignores)
|
|
130
|
+
if type_ignores is not None:
|
|
131
|
+
listTypeIgnore.extend(type_ignores)
|
|
132
|
+
if statement is not None:
|
|
133
|
+
if isinstance(statement, Sequence):
|
|
134
|
+
list_body.extend(statement)
|
|
135
|
+
else:
|
|
136
|
+
list_body.append(statement)
|
|
137
|
+
self_astModule.body.extend(list_body)
|
|
138
|
+
self_astModule.type_ignores.extend(listTypeIgnore)
|
|
139
|
+
ast.fix_missing_locations(self_astModule)
|
|
140
|
+
|
|
141
|
+
def appendPrologue(self, astModule: ast.Module | None = None, statement: Sequence[ast.stmt] | ast.stmt | None = None, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
|
|
142
|
+
"""Append one or more statements to `prologue`."""
|
|
143
|
+
self._append_astModule(self.prologue, astModule, statement, type_ignores)
|
|
144
|
+
|
|
145
|
+
def appendEpilogue(self, astModule: ast.Module | None = None, statement: Sequence[ast.stmt] | ast.stmt | None = None, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
|
|
146
|
+
"""Append one or more statements to `epilogue`."""
|
|
147
|
+
self._append_astModule(self.epilogue, astModule, statement, type_ignores)
|
|
148
|
+
|
|
149
|
+
def appendLauncher(self, astModule: ast.Module | None = None, statement: Sequence[ast.stmt] | ast.stmt | None = None, type_ignores: list[ast.TypeIgnore] | None = None) -> None:
|
|
150
|
+
"""Append one or more statements to `launcher`."""
|
|
151
|
+
self._append_astModule(self.launcher, astModule, statement, type_ignores)
|
|
152
|
+
|
|
153
|
+
def appendIngredientsFunction(self, *ingredientsFunction: IngredientsFunction) -> None:
|
|
154
|
+
"""Append one or more `IngredientsFunction`."""
|
|
155
|
+
for allegedIngredientsFunction in ingredientsFunction:
|
|
156
|
+
if isinstance(allegedIngredientsFunction, IngredientsFunction):
|
|
157
|
+
self.listIngredientsFunctions.append(allegedIngredientsFunction)
|
|
158
|
+
else:
|
|
159
|
+
raise ValueError(f"I received `{type(allegedIngredientsFunction) = }`, but I can only accept `{IngredientsFunction}`.")
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def list_astImportImportFrom(self) -> list[ast.Import | ast.ImportFrom]:
|
|
163
|
+
"""List of `ast.Import` and `ast.ImportFrom` statements."""
|
|
164
|
+
sherpaLedger = LedgerOfImports()
|
|
165
|
+
listLedgers: list[LedgerOfImports] = [self.imports]
|
|
166
|
+
for ingredientsFunction in self.listIngredientsFunctions:
|
|
167
|
+
listLedgers.append(ingredientsFunction.imports)
|
|
168
|
+
sherpaLedger.update(*listLedgers)
|
|
169
|
+
return sherpaLedger.makeList_ast()
|
|
170
|
+
|
|
171
|
+
@property
|
|
172
|
+
def body(self) -> list[ast.stmt]:
|
|
173
|
+
list_stmt: list[ast.stmt] = []
|
|
174
|
+
list_stmt.extend(self.list_astImportImportFrom)
|
|
175
|
+
list_stmt.extend(self.prologue.body)
|
|
176
|
+
for ingredientsFunction in self.listIngredientsFunctions:
|
|
177
|
+
list_stmt.append(ingredientsFunction.astFunctionDef)
|
|
178
|
+
list_stmt.extend(self.epilogue.body)
|
|
179
|
+
list_stmt.extend(self.launcher.body)
|
|
180
|
+
# TODO `launcher`, if it exists, must start with `if __name__ == '__main__':` and be indented
|
|
181
|
+
return list_stmt
|
|
182
|
+
|
|
183
|
+
@property
|
|
184
|
+
def type_ignores(self) -> list[ast.TypeIgnore]:
|
|
185
|
+
listTypeIgnore: list[ast.TypeIgnore] = self.supplemental_type_ignores
|
|
186
|
+
# listTypeIgnore.extend(self.imports.makeListAst())
|
|
187
|
+
listTypeIgnore.extend(self.prologue.type_ignores)
|
|
188
|
+
for ingredientsFunction in self.listIngredientsFunctions:
|
|
189
|
+
listTypeIgnore.extend(ingredientsFunction.type_ignores)
|
|
190
|
+
listTypeIgnore.extend(self.epilogue.type_ignores)
|
|
191
|
+
listTypeIgnore.extend(self.launcher.type_ignores)
|
|
192
|
+
return listTypeIgnore
|
|
193
|
+
|
|
194
|
+
@dataclasses.dataclass
|
|
195
|
+
class RecipeSynthesizeFlow:
|
|
196
|
+
"""Settings for synthesizing flow."""
|
|
197
|
+
# ========================================
|
|
198
|
+
# Source
|
|
199
|
+
# ========================================
|
|
200
|
+
source_astModule = parseLogicalPath2astModule(The.logicalPathModuleSourceAlgorithm)
|
|
201
|
+
|
|
202
|
+
# Figure out dynamic flow control to synthesized modules https://github.com/hunterhogan/mapFolding/issues/4
|
|
203
|
+
sourceCallableDispatcher: ast_Identifier = The.sourceCallableDispatcher
|
|
204
|
+
sourceCallableInitialize: ast_Identifier = The.sourceCallableInitialize
|
|
205
|
+
sourceCallableParallel: ast_Identifier = The.sourceCallableParallel
|
|
206
|
+
sourceCallableSequential: ast_Identifier = The.sourceCallableSequential
|
|
207
|
+
|
|
208
|
+
sourceDataclassIdentifier: ast_Identifier = The.dataclassIdentifier
|
|
209
|
+
sourceDataclassInstance: ast_Identifier = The.dataclassInstance
|
|
210
|
+
sourceDataclassInstanceTaskDistribution: ast_Identifier = The.dataclassInstanceTaskDistribution
|
|
211
|
+
sourceLogicalPathModuleDataclass: str_nameDOTname = The.logicalPathModuleDataclass
|
|
212
|
+
|
|
213
|
+
sourceConcurrencyManagerNamespace = The.sourceConcurrencyManagerNamespace
|
|
214
|
+
sourceConcurrencyManagerIdentifier = The.sourceConcurrencyManagerIdentifier
|
|
215
|
+
|
|
216
|
+
# ========================================
|
|
217
|
+
# Logical identifiers (as opposed to physical identifiers)
|
|
218
|
+
# ========================================
|
|
219
|
+
# Package ================================
|
|
220
|
+
packageIdentifier: ast_Identifier | None = The.packageName
|
|
221
|
+
|
|
222
|
+
# Qualified logical path ================================
|
|
223
|
+
logicalPathModuleDataclass: str_nameDOTname = sourceLogicalPathModuleDataclass
|
|
224
|
+
logicalPathFlowRoot: ast_Identifier | None = 'syntheticModules'
|
|
225
|
+
""" `logicalPathFlowRoot` likely corresponds to a physical filesystem directory."""
|
|
226
|
+
|
|
227
|
+
# Module ================================
|
|
228
|
+
moduleDispatcher: ast_Identifier = 'numbaCount_doTheNeedful'
|
|
229
|
+
moduleInitialize: ast_Identifier = moduleDispatcher
|
|
230
|
+
moduleParallel: ast_Identifier = moduleDispatcher
|
|
231
|
+
moduleSequential: ast_Identifier = moduleDispatcher
|
|
232
|
+
|
|
233
|
+
# Function ================================
|
|
234
|
+
callableDispatcher: ast_Identifier = sourceCallableDispatcher
|
|
235
|
+
callableInitialize: ast_Identifier = sourceCallableInitialize
|
|
236
|
+
callableParallel: ast_Identifier = sourceCallableParallel
|
|
237
|
+
callableSequential: ast_Identifier = sourceCallableSequential
|
|
238
|
+
concurrencyManagerNamespace: ast_Identifier = sourceConcurrencyManagerNamespace
|
|
239
|
+
concurrencyManagerIdentifier: ast_Identifier = sourceConcurrencyManagerIdentifier
|
|
240
|
+
dataclassIdentifier: ast_Identifier = sourceDataclassIdentifier
|
|
241
|
+
|
|
242
|
+
# Variable ================================
|
|
243
|
+
dataclassInstance: ast_Identifier = sourceDataclassInstance
|
|
244
|
+
dataclassInstanceTaskDistribution: ast_Identifier = sourceDataclassInstanceTaskDistribution
|
|
245
|
+
|
|
246
|
+
# ========================================
|
|
247
|
+
# Computed
|
|
248
|
+
# ========================================
|
|
249
|
+
"""
|
|
250
|
+
theFormatStrModuleSynthetic = "{packageFlow}Count"
|
|
251
|
+
theFormatStrModuleForCallableSynthetic = theFormatStrModuleSynthetic + "_{callableTarget}"
|
|
252
|
+
theModuleDispatcherSynthetic: ast_Identifier = theFormatStrModuleForCallableSynthetic.format(packageFlow=packageFlowSynthetic, callableTarget=The.sourceCallableDispatcher)
|
|
253
|
+
theLogicalPathModuleDispatcherSynthetic: str = '.'.join([The.packageName, The.moduleOfSyntheticModules, theModuleDispatcherSynthetic])
|
|
254
|
+
|
|
255
|
+
"""
|
|
256
|
+
# logicalPathModuleDispatcher: str = '.'.join([Z0Z_flowLogicalPathRoot, moduleDispatcher])
|
|
257
|
+
# ========================================
|
|
258
|
+
# Filesystem (names of physical objects)
|
|
259
|
+
# ========================================
|
|
260
|
+
pathPackage: PurePosixPath | None = PurePosixPath(The.pathPackage)
|
|
261
|
+
fileExtension: str = The.fileExtension
|
|
262
|
+
|
|
263
|
+
def _makePathFilename(self, filenameStem: str,
|
|
264
|
+
pathRoot: PurePosixPath | None = None,
|
|
265
|
+
logicalPathINFIX: str_nameDOTname | None = None,
|
|
266
|
+
fileExtension: str | None = None,
|
|
267
|
+
) -> PurePosixPath:
|
|
268
|
+
"""filenameStem: (hint: the name of the logical module)"""
|
|
269
|
+
if pathRoot is None:
|
|
270
|
+
pathRoot = self.pathPackage or PurePosixPath(Path.cwd())
|
|
271
|
+
if logicalPathINFIX:
|
|
272
|
+
whyIsThisStillAThing: list[str] = logicalPathINFIX.split('.')
|
|
273
|
+
pathRoot = pathRoot.joinpath(*whyIsThisStillAThing)
|
|
274
|
+
if fileExtension is None:
|
|
275
|
+
fileExtension = self.fileExtension
|
|
276
|
+
filename: str = filenameStem + fileExtension
|
|
277
|
+
return pathRoot.joinpath(filename)
|
|
278
|
+
|
|
279
|
+
@property
|
|
280
|
+
def pathFilenameDispatcher(self) -> PurePosixPath:
|
|
281
|
+
return self._makePathFilename(filenameStem=self.moduleDispatcher, logicalPathINFIX=self.logicalPathFlowRoot)
|
|
282
|
+
@property
|
|
283
|
+
def pathFilenameInitialize(self) -> PurePosixPath:
|
|
284
|
+
return self._makePathFilename(filenameStem=self.moduleInitialize, logicalPathINFIX=self.logicalPathFlowRoot)
|
|
285
|
+
@property
|
|
286
|
+
def pathFilenameParallel(self) -> PurePosixPath:
|
|
287
|
+
return self._makePathFilename(filenameStem=self.moduleParallel, logicalPathINFIX=self.logicalPathFlowRoot)
|
|
288
|
+
@property
|
|
289
|
+
def pathFilenameSequential(self) -> PurePosixPath:
|
|
290
|
+
return self._makePathFilename(filenameStem=self.moduleSequential, logicalPathINFIX=self.logicalPathFlowRoot)
|
|
291
|
+
|
|
292
|
+
def __post_init__(self) -> None:
|
|
293
|
+
if ((self.concurrencyManagerIdentifier is not None and self.concurrencyManagerIdentifier != self.sourceConcurrencyManagerIdentifier) # `submit` # type: ignore
|
|
294
|
+
or ((self.concurrencyManagerIdentifier is None) != (self.concurrencyManagerNamespace is None))): # type: ignore
|
|
295
|
+
import warnings
|
|
296
|
+
warnings.warn(f"If your synthesized module is weird, check `{self.concurrencyManagerIdentifier=}` and `{self.concurrencyManagerNamespace=}`. (ChildProcessError? 'Yeah! Children shouldn't be processing stuff, man.')", category=ChildProcessError, stacklevel=2) # pyright: ignore[reportCallIssue, reportArgumentType] Y'all Pynatics need to be less shrill and focus on making code that doesn't need 8000 error categories.
|
|
297
|
+
|
|
298
|
+
# self.logicalPathModuleDispatcher!=logicalPathModuleDispatcherHARDCODED or
|
|
299
|
+
if self.callableDispatcher!=callableDispatcherHARDCODED:
|
|
300
|
+
print(f"fyi: `{self.callableDispatcher=}` but\n\t`{callableDispatcherHARDCODED=}`.")
|
|
301
|
+
|
|
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))
|