mapFolding 0.4.1__py3-none-any.whl → 0.4.3__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.
@@ -9,10 +9,11 @@ def insertArrayIn_body(FunctionDefTarget: ast.FunctionDef, identifier: str, arra
9
9
  # NOTE hack
10
10
  constructorName = constructorName.replace('ndarray', 'array')
11
11
  argData_dtype: numpy.dtype = arrayTarget.dtype
12
- argData_dtypeName = arrayTarget.dtype.name
12
+ datatypeName = argData_dtype.name
13
+ dtypeAsName = f"{moduleConstructor}_{datatypeName}"
13
14
 
14
15
  allImports.addImportFromStr(moduleConstructor, constructorName)
15
- allImports.addImportFromStr(moduleConstructor, argData_dtypeName)
16
+ allImports.addImportFromStr(moduleConstructor, datatypeName, dtypeAsName)
16
17
 
17
18
  def insertAssign(assignee: str, arraySlice: numpy.ndarray) -> None:
18
19
  nonlocal FunctionDefTarget
@@ -20,7 +21,7 @@ def insertArrayIn_body(FunctionDefTarget: ast.FunctionDef, identifier: str, arra
20
21
  astStatement = cast(ast.Expr, ast.parse(onlyDataRLE).body[0])
21
22
  dataAst = astStatement.value
22
23
 
23
- arrayCall = Then.make_astCall(name=constructorName, args=[dataAst], list_astKeywords=[ast.keyword(arg='dtype', value=ast.Name(id=argData_dtypeName, ctx=ast.Load()))])
24
+ arrayCall = Then.make_astCall(name=constructorName, args=[dataAst], list_astKeywords=[ast.keyword(arg='dtype', value=ast.Name(id=dtypeAsName, ctx=ast.Load()))])
24
25
 
25
26
  assignment = ast.Assign(targets=[ast.Name(id=assignee, ctx=ast.Store())], value=arrayCall)#NOTE
26
27
  FunctionDefTarget.body.insert(0, assignment)
@@ -33,7 +34,8 @@ def insertArrayIn_body(FunctionDefTarget: ast.FunctionDef, identifier: str, arra
33
34
 
34
35
  return FunctionDefTarget, allImports
35
36
 
36
- def findAndReplaceArrayIn_body(FunctionDefTarget: ast.FunctionDef, identifier: str, arrayTarget: numpy.ndarray, allImports: UniversalImportTracker) -> Tuple[ast.FunctionDef, UniversalImportTracker]:
37
+ def findAndReplaceTrackArrayIn_body(FunctionDefTarget: ast.FunctionDef, identifier: str , arrayTarget: numpy.ndarray , allImports: UniversalImportTracker) -> Tuple[ast.FunctionDef, UniversalImportTracker]:
38
+
37
39
  arrayType = type(arrayTarget)
38
40
  moduleConstructor = arrayType.__module__
39
41
  constructorName = arrayType.__name__
@@ -41,47 +43,41 @@ def findAndReplaceArrayIn_body(FunctionDefTarget: ast.FunctionDef, identifier: s
41
43
  constructorName = constructorName.replace('ndarray', 'array')
42
44
  allImports.addImportFromStr(moduleConstructor, constructorName)
43
45
 
44
- for stmt in FunctionDefTarget.body.copy():
45
- if isinstance(stmt, ast.Assign):
46
- if isinstance(stmt.targets[0], ast.Name) and isinstance(stmt.value, ast.Subscript):
47
- astAssignee: ast.Name = stmt.targets[0]
48
- argData_dtypeName = hackSSOTdatatype(astAssignee.id)
49
- allImports.addImportFromStr(moduleConstructor, argData_dtypeName)
50
- astSubscript: ast.Subscript = stmt.value
51
- if isinstance(astSubscript.value, ast.Name) and astSubscript.value.id == identifier and isinstance(astSubscript.slice, ast.Attribute):
52
- indexAs_astAttribute: ast.Attribute = astSubscript.slice
53
- indexAsStr = ast.unparse(indexAs_astAttribute)
54
- arraySlice = arrayTarget[eval(indexAsStr)]
46
+ for statement in FunctionDefTarget.body.copy():
47
+ if ifThis.isUnpackingAnArray(identifier)(statement):
48
+ datatypeName = hackSSOTdatatype(statement.targets[0].id) # type: ignore
49
+ dtypeAsName = f"{moduleConstructor}_{datatypeName}"
50
+ indexAsStr = ast.unparse(statement.value.slice) # type: ignore
51
+ arraySlice = arrayTarget[eval(indexAsStr)]
55
52
 
56
- onlyDataRLE = autoDecodingRLE(arraySlice, addSpaces=True)
57
- astStatement = cast(ast.Expr, ast.parse(onlyDataRLE).body[0])
58
- dataAst = astStatement.value
53
+ onlyDataRLE = autoDecodingRLE(arraySlice, addSpaces=True)
54
+ astStatement = cast(ast.Expr, ast.parse(onlyDataRLE).body[0])
55
+ dataAst = astStatement.value
59
56
 
60
- arrayCall = Then.make_astCall(name=constructorName, args=[dataAst], list_astKeywords=[ast.keyword(arg='dtype', value=ast.Name(id=argData_dtypeName, ctx=ast.Load()))])
57
+ arrayCall = Then.make_astCall(name=constructorName, args=[dataAst], list_astKeywords=[ast.keyword(arg='dtype', value=ast.Name(id=dtypeAsName, ctx=ast.Load()))])
61
58
 
62
- assignment = ast.Assign(targets=[astAssignee], value=arrayCall)
63
- FunctionDefTarget.body.insert(0, assignment)
64
- FunctionDefTarget.body.remove(stmt)
59
+ assignment = ast.Assign(targets=[statement.targets[0]], value=arrayCall) # type: ignore
60
+ FunctionDefTarget.body.insert(0, assignment)
61
+ FunctionDefTarget.body.remove(statement)
62
+ allImports.addImportFromStr(moduleConstructor, datatypeName, dtypeAsName)
65
63
  return FunctionDefTarget, allImports
66
64
 
67
65
  def findAndReplaceArraySubscriptIn_body(FunctionDefTarget: ast.FunctionDef, identifier: str, arrayTarget: numpy.ndarray, Z0Z_listChaff: List[str], allImports: UniversalImportTracker) -> Tuple[ast.FunctionDef, UniversalImportTracker]:
68
66
  moduleConstructor = Z0Z_getDatatypeModuleScalar()
69
- for stmt in FunctionDefTarget.body.copy():
70
- if isinstance(stmt, ast.Assign):
71
- if isinstance(stmt.targets[0], ast.Name) and isinstance(stmt.value, ast.Subscript):
72
- astAssignee: ast.Name = stmt.targets[0]
73
- argData_dtypeName = hackSSOTdatatype(astAssignee.id)
74
- allImports.addImportFromStr(moduleConstructor, argData_dtypeName)
75
- astSubscript: ast.Subscript = stmt.value
76
- if isinstance(astSubscript.value, ast.Name) and astSubscript.value.id == identifier and isinstance(astSubscript.slice, ast.Attribute):
77
- indexAs_astAttribute: ast.Attribute = astSubscript.slice
78
- indexAsStr = ast.unparse(indexAs_astAttribute)
79
- argDataSlice: int = arrayTarget[eval(indexAsStr)].item()
80
- astCall = ast.Call(func=ast.Name(id=argData_dtypeName, ctx=ast.Load()), args=[ast.Constant(value=argDataSlice)], keywords=[])
81
- assignment = ast.Assign(targets=[astAssignee], value=astCall)
82
- if astAssignee.id not in Z0Z_listChaff:
83
- FunctionDefTarget.body.insert(0, assignment)
84
- FunctionDefTarget.body.remove(stmt)
67
+ for statement in FunctionDefTarget.body.copy():
68
+ if ifThis.isUnpackingAnArray(identifier)(statement):
69
+ astSubscript: ast.Subscript = statement.value # type: ignore
70
+ astAssignee: ast.Name = statement.targets[0] # type: ignore
71
+ argData_dtypeName = hackSSOTdatatype(astAssignee.id)
72
+ allImports.addImportFromStr(moduleConstructor, argData_dtypeName)
73
+ indexAs_astAttribute: ast.Attribute = astSubscript.slice # type: ignore
74
+ indexAsStr = ast.unparse(indexAs_astAttribute)
75
+ argDataSlice: int = arrayTarget[eval(indexAsStr)].item()
76
+ astCall = ast.Call(func=ast.Name(id=argData_dtypeName, ctx=ast.Load()), args=[ast.Constant(value=argDataSlice)], keywords=[])
77
+ assignment = ast.Assign(targets=[astAssignee], value=astCall)
78
+ if astAssignee.id not in Z0Z_listChaff:
79
+ FunctionDefTarget.body.insert(0, assignment)
80
+ FunctionDefTarget.body.remove(statement)
85
81
  return FunctionDefTarget, allImports
86
82
 
87
83
  def removeAssignTargetFrom_body(FunctionDefTarget: ast.FunctionDef, identifier: str) -> ast.FunctionDef:
@@ -136,13 +132,10 @@ def findThingyReplaceWithConstantIn_body(FunctionDefTarget: ast.FunctionDef, obj
136
132
  return newFunction
137
133
 
138
134
  def findAstNameReplaceWithConstantIn_body(FunctionDefTarget: ast.FunctionDef, name: str, value: int) -> ast.FunctionDef:
139
- def findName(node: ast.AST) -> bool:
140
- return isinstance(node, ast.Name) and node.id == name
141
-
142
135
  def replaceWithConstant(node: ast.AST) -> ast.AST:
143
136
  return ast.copy_location(ast.Constant(value=value), node)
144
137
 
145
- return cast(ast.FunctionDef, NodeReplacer(findName, replaceWithConstant).visit(FunctionDefTarget))
138
+ return cast(ast.FunctionDef, NodeReplacer(ifThis.nameIs(name), replaceWithConstant).visit(FunctionDefTarget))
146
139
 
147
140
  def insertReturnStatementIn_body(FunctionDefTarget: ast.FunctionDef, arrayTarget: numpy.ndarray, allImports: UniversalImportTracker) -> Tuple[ast.FunctionDef, UniversalImportTracker]:
148
141
  """Add multiplication and return statement to function, properly constructing AST nodes."""
@@ -155,6 +148,8 @@ def insertReturnStatementIn_body(FunctionDefTarget: ast.FunctionDef, arrayTarget
155
148
 
156
149
  returnStatement = ast.Return(value=multiplyOperation)
157
150
 
151
+ datatype = hackSSOTdatatype(Z0Z_identifierCountFolds)
152
+ FunctionDefTarget.returns = ast.Name(id=datatype, ctx=ast.Load())
158
153
  datatypeModuleScalar = Z0Z_getDatatypeModuleScalar()
159
154
  allImports.addImportFromStr(datatypeModuleScalar, datatype)
160
155
 
@@ -240,9 +235,7 @@ if __name__ == '__main__':
240
235
  """
241
236
  return ast.parse(linesLaunch)
242
237
 
243
- def makeAstModuleForOneCallable(pythonSource: str, callableTarget: str, parametersNumba: Optional[ParametersNumba]=None, inlineCallables: Optional[bool]=False , unpackArrays: Optional[bool]=False , allImports: Optional[UniversalImportTracker]=None ) -> str:
244
- astModule: ast.Module = ast.parse(pythonSource, type_comments=True)
245
-
238
+ def makeFunctionDef(astModule: ast.Module, callableTarget: str, parametersNumba: Optional[ParametersNumba]=None, inlineCallables: Optional[bool]=False, unpackArrays: Optional[bool]=False, allImports: Optional[UniversalImportTracker]=None) -> Tuple[ast.FunctionDef, UniversalImportTracker]:
246
239
  if allImports is None:
247
240
  allImports = UniversalImportTracker()
248
241
  for statement in astModule.body:
@@ -252,6 +245,8 @@ def makeAstModuleForOneCallable(pythonSource: str, callableTarget: str, paramete
252
245
  if inlineCallables:
253
246
  dictionaryFunctionDef = {statement.name: statement for statement in astModule.body if isinstance(statement, ast.FunctionDef)}
254
247
  callableInlinerWorkhorse = RecursiveInliner(dictionaryFunctionDef)
248
+ # NOTE the inliner assumes each function is not called more than once
249
+ # TODO change the inliner to handle multiple calls to the same function
255
250
  FunctionDefTarget = callableInlinerWorkhorse.inlineFunctionBody(callableTarget)
256
251
  else:
257
252
  FunctionDefTarget = next((node for node in astModule.body if isinstance(node, ast.FunctionDef) and node.name == callableTarget), None)
@@ -269,9 +264,7 @@ def makeAstModuleForOneCallable(pythonSource: str, callableTarget: str, paramete
269
264
  FunctionDefTarget = cast(ast.FunctionDef, unpacker.visit(FunctionDefTarget))
270
265
  ast.fix_missing_locations(FunctionDefTarget)
271
266
 
272
- astModule = ast.Module(body=cast(List[ast.stmt], allImports.makeListAst() + [FunctionDefTarget]), type_ignores=[])
273
- ast.fix_missing_locations(astModule)
274
- return ast.unparse(astModule)
267
+ return FunctionDefTarget, allImports
275
268
 
276
269
  def decorateCallableWithNumba(FunctionDefTarget: ast.FunctionDef, allImports: UniversalImportTracker, parametersNumba: Optional[ParametersNumba]=None) -> Tuple[ast.FunctionDef, UniversalImportTracker]:
277
270
  def Z0Z_UnhandledDecorators(astCallable: ast.FunctionDef) -> ast.FunctionDef:
@@ -1,7 +1,7 @@
1
1
  from mapFolding import (
2
2
  computationState,
3
3
  EnumIndices,
4
- formatModuleNameDEFAULT,
4
+ formatFilenameModuleDEFAULT,
5
5
  FREAKOUT,
6
6
  getAlgorithmDispatcher,
7
7
  getAlgorithmSource,
@@ -36,7 +36,7 @@ from numpy import integer
36
36
  from numpy.typing import NDArray
37
37
  from types import ModuleType
38
38
  from typing import Any, Callable, cast, Dict, List, Optional, Sequence, Set, Tuple, Type, Union
39
- from Z0Z_tools import autoDecodingRLE
39
+ from Z0Z_tools import autoDecodingRLE, updateExtendPolishDictionaryLists
40
40
  import ast
41
41
  import autoflake
42
42
  import collections
@@ -49,9 +49,41 @@ import numpy
49
49
  import os
50
50
  import pathlib
51
51
  import python_minifier
52
+ import warnings
52
53
 
53
54
  youOughtaKnow = collections.namedtuple('youOughtaKnow', ['callableSynthesized', 'pathFilenameForMe', 'astForCompetentProgrammers'])
54
55
 
56
+ # idk how to use this
57
+ class ASTBodyTransformer:
58
+ """
59
+ A helper class to apply multiple transformations on an AST FunctionDef's body.
60
+ This abstraction eliminates the need to write repetitive loops for removals,
61
+ replacements, or insertions.
62
+ """
63
+ def __init__(self, functionDefinition: ast.FunctionDef) -> None:
64
+ self.functionDefinition = functionDefinition
65
+
66
+ def replaceIn_body(self, predicate: Callable[[ast.stmt], bool], replacementBuilder: Callable[[ast.stmt], Optional[ast.stmt]]) -> None:
67
+ newBody: List[ast.stmt] = []
68
+ for statement in self.functionDefinition.body:
69
+ if predicate(statement):
70
+ replacementStatement = replacementBuilder(statement)
71
+ if replacementStatement is not None:
72
+ newBody.append(replacementStatement)
73
+ else:
74
+ newBody.append(statement)
75
+ self.functionDefinition.body = newBody
76
+
77
+ def atIndexInsert(self, index: int, statement: ast.stmt) -> None:
78
+ self.functionDefinition.body.insert(index, statement)
79
+
80
+ def removeAllOf(self, predicate: Callable[[ast.stmt], bool]) -> None:
81
+ self.replaceIn_body(predicate, lambda stmt: None)
82
+
83
+ def Z0Z_apply(self) -> ast.FunctionDef:
84
+ ast.fix_missing_locations(self.functionDefinition)
85
+ return self.functionDefinition
86
+
55
87
  # Generic
56
88
  class ifThis:
57
89
  """Generic AST node predicate builder."""
@@ -71,10 +103,27 @@ class ifThis:
71
103
  def isCallWithName(callableName: str) -> Callable[[ast.AST], bool]:
72
104
  return lambda node: (isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and node.func.id == callableName)
73
105
 
106
+ @staticmethod
107
+ def isAssignTarget(identifier: str):
108
+ return lambda node: (isinstance(node, ast.Assign)
109
+ and node.targets
110
+ and isinstance(node.targets[0], ast.Name)
111
+ and node.targets[0].id == identifier)
112
+
74
113
  @staticmethod
75
114
  def anyOf(*predicates: Callable[[ast.AST], bool]) -> Callable[[ast.AST], bool]:
76
115
  return lambda node: any(pred(node) for pred in predicates)
77
116
 
117
+ @staticmethod
118
+ def isUnpackingAnArray(identifier:str):
119
+ return lambda node: (isinstance(node, ast.Assign)
120
+ and isinstance(node.targets[0], ast.Name)
121
+ and isinstance(node.value, ast.Subscript)
122
+ and isinstance(node.value.value, ast.Name)
123
+ and node.value.value.id == identifier
124
+ and isinstance(node.value.slice, ast.Attribute)
125
+ )
126
+
78
127
  class Then:
79
128
  """Generic actions."""
80
129
  @staticmethod
@@ -103,9 +152,8 @@ class NodeReplacer(ast.NodeTransformer):
103
152
  None from the replacement builder indicates that the node should be removed.
104
153
 
105
154
  Attributes:
106
- findMe (Callable[[ast.AST], bool]): A function that determines whether a node should be replaced.
107
- nodeReplacementBuilder (Callable[[ast.AST], Optional[ast.AST]]): A function that returns a new node
108
- or None to remove the node.
155
+ findMe: A function that determines whether a node should be replaced.
156
+ nodeReplacementBuilder: A function that returns a new node or None to remove the node.
109
157
 
110
158
  Methods:
111
159
  visit(node: ast.AST) -> Optional[ast.AST]:
@@ -142,19 +190,42 @@ class UniversalImportTracker:
142
190
  self.setImport.add(alias.name)
143
191
  elif isinstance(astImport_, ast.ImportFrom):
144
192
  if astImport_.module is not None:
145
- self.dictionaryImportFrom[astImport_.module].update(alias.name for alias in astImport_.names)
193
+ self.dictionaryImportFrom[astImport_.module].update((alias.name, alias.asname) for alias in astImport_.names)
146
194
 
147
- def addImportFromStr(self, module: str, name: str) -> None:
148
- self.dictionaryImportFrom[module].add(name)
195
+ def addImportStr(self, module: str) -> None:
196
+ self.setImport.add(module)
149
197
 
150
- def addImportStr(self, name: str) -> None:
151
- self.setImport.add(name)
198
+ def addImportFromStr(self, module: str, name: str, asname: Optional[str] = None) -> None:
199
+ self.dictionaryImportFrom[module].add((name, asname))
152
200
 
153
201
  def makeListAst(self) -> List[Union[ast.ImportFrom, ast.Import]]:
154
- listAstImportFrom = [ast.ImportFrom(module=module, names=[ast.alias(name=name, asname=None)], level=0) for module, names in self.dictionaryImportFrom.items() for name in names]
155
- listAstImport = [ast.Import(names=[ast.alias(name=name, asname=None)]) for name in self.setImport]
202
+ listAstImportFrom = []
203
+ for module, setOfNameTuples in sorted(self.dictionaryImportFrom.items()):
204
+ listAliases = []
205
+ for name, asname in setOfNameTuples:
206
+ listAliases.append(ast.alias(name=name, asname=asname))
207
+ listAstImportFrom.append(ast.ImportFrom(module=module, names=listAliases, level=0))
208
+
209
+ listAstImport = [ast.Import(names=[ast.alias(name=name, asname=None)]) for name in sorted(self.setImport)]
156
210
  return listAstImportFrom + listAstImport
157
211
 
212
+ def update(self, *fromTracker: 'UniversalImportTracker') -> None:
213
+ """
214
+ Update this tracker with imports from one or more other trackers.
215
+
216
+ Parameters:
217
+ *fromTracker: One or more UniversalImportTracker objects to merge from.
218
+ """
219
+ # Merge all import-from dictionaries
220
+ dictionaryMerged = updateExtendPolishDictionaryLists(self.dictionaryImportFrom, *(tracker.dictionaryImportFrom for tracker in fromTracker), destroyDuplicates=True, reorderLists=True)
221
+
222
+ # Convert lists back to sets for each module's imports
223
+ self.dictionaryImportFrom = {module: set(listNames) for module, listNames in dictionaryMerged.items()}
224
+
225
+ # Update direct imports
226
+ for tracker in fromTracker:
227
+ self.setImport.update(tracker.setImport)
228
+
158
229
  # Intricate and specialized
159
230
  class RecursiveInliner(ast.NodeTransformer):
160
231
  """
@@ -64,6 +64,7 @@ def writeJobNumba(mapShape: Sequence[int]
64
64
  pythonSource = inspect.getsource(algorithmSource)
65
65
  astModule = ast.parse(pythonSource)
66
66
  setFunctionDef = {statement for statement in astModule.body if isinstance(statement, ast.FunctionDef)}
67
+
67
68
  if not callableTarget:
68
69
  if len(setFunctionDef) == 1:
69
70
  FunctionDefTarget = setFunctionDef.pop()
@@ -71,7 +72,8 @@ def writeJobNumba(mapShape: Sequence[int]
71
72
  else:
72
73
  raise ValueError(f"I did not receive a `callableTarget` and {algorithmSource.__name__=} has more than one callable: {setFunctionDef}. Please select one.")
73
74
  else:
74
- FunctionDefTarget = setFunctionDef.pop() if callableTarget in {statement.name for statement in setFunctionDef} else None
75
+ listFunctionDefTarget = [statement for statement in setFunctionDef if statement.name == callableTarget]
76
+ FunctionDefTarget = listFunctionDefTarget[0] if listFunctionDefTarget else None
75
77
  if not FunctionDefTarget: raise ValueError(f"I received `{callableTarget=}` and {algorithmSource.__name__=}, but I could not find that function in that source.")
76
78
 
77
79
  # NOTE `allImports` is a complementary container to `FunctionDefTarget`; the `FunctionDefTarget` cannot track its own imports very well.
@@ -86,13 +88,15 @@ def writeJobNumba(mapShape: Sequence[int]
86
88
  case 'my':
87
89
  FunctionDefTarget, allImports = findAndReplaceArraySubscriptIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], ['taskIndex', 'dimensionsTotal'], allImports)
88
90
  case 'track':
89
- FunctionDefTarget, allImports = findAndReplaceArrayIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], allImports)
91
+ FunctionDefTarget, allImports = findAndReplaceTrackArrayIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], allImports)
90
92
  case 'connectionGraph':
91
93
  FunctionDefTarget, allImports = insertArrayIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], allImports)
92
94
  case 'gapsWhere':
93
95
  FunctionDefTarget, allImports = insertArrayIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], allImports)
94
96
  case 'foldGroups':
95
97
  FunctionDefTarget = removeAssignTargetFrom_body(FunctionDefTarget, pirateScowl.arg)
98
+ # FunctionDefTarget, allImports = insertArrayIn_body(FunctionDefTarget, pirateScowl.arg, stateJob[pirateScowl.arg], allImports)
99
+ # continue
96
100
  FunctionDefTarget.args.args.remove(pirateScowl)
97
101
 
98
102
  # NOTE replace identifiers with static values with their values
@@ -110,8 +114,6 @@ def writeJobNumba(mapShape: Sequence[int]
110
114
  FunctionDefTarget, allImports = insertReturnStatementIn_body(FunctionDefTarget, stateJob['foldGroups'], allImports)
111
115
 
112
116
  # NOTE add the perfect decorator
113
- datatype = hackSSOTdatatype(Z0Z_identifierCountFolds)
114
- FunctionDefTarget.returns = ast.Name(id=datatype, ctx=ast.Load())
115
117
  FunctionDefTarget, allImports = decorateCallableWithNumba(FunctionDefTarget, allImports, parametersNumba)
116
118
  if thisIsNumbaDotJit(FunctionDefTarget.decorator_list[0]):
117
119
  astCall = cast(ast.Call, FunctionDefTarget.decorator_list[0])
@@ -124,21 +126,7 @@ def writeJobNumba(mapShape: Sequence[int]
124
126
  ast.fix_missing_locations(astModule)
125
127
  pythonSource = ast.unparse(astModule)
126
128
  pythonSource = autoflake.fix_code(pythonSource, ['mapFolding', 'numba', 'numpy'])
127
- pythonSource = python_minifier.minify(pythonSource, remove_annotations = False,
128
- remove_pass = False,
129
- remove_literal_statements = False,
130
- combine_imports = True,
131
- hoist_literals = False,
132
- rename_locals = False,
133
- rename_globals = False,
134
- remove_object_base = False,
135
- convert_posargs_to_args = False,
136
- preserve_shebang = True,
137
- remove_asserts = False,
138
- remove_debug = False,
139
- remove_explicit_return_none = False,
140
- remove_builtin_exception_brackets = False,
141
- constant_folding = False)
129
+ # pythonSource = python_minifier.minify(pythonSource, remove_annotations = False, remove_pass = False, remove_literal_statements = False, combine_imports = True, hoist_literals = False, rename_locals = False, rename_globals = False, remove_object_base = False, convert_posargs_to_args = False, preserve_shebang = True, remove_asserts = False, remove_debug = False, remove_explicit_return_none = False, remove_builtin_exception_brackets = False, constant_folding = False)
142
130
 
143
131
  # NOTE put on disk
144
132
  if pathFilenameWriteJob is None:
@@ -155,17 +143,18 @@ def writeJobNumba(mapShape: Sequence[int]
155
143
 
156
144
  if __name__ == '__main__':
157
145
  mapShape = [5,5]
158
- from mapFolding.syntheticModules import numba_countSequential
159
- algorithmSource: ModuleType = numba_countSequential
146
+ from mapFolding.syntheticModules import numbaCount
147
+ algorithmSource: ModuleType = numbaCount
160
148
 
161
- callableTarget = None
149
+ callableTarget = 'countSequential'
162
150
 
163
151
  parametersNumba = parametersNumbaDEFAULT
152
+ parametersNumba['boundscheck'] = True
164
153
 
165
154
  pathFilenameWriteJob = None
166
155
 
167
156
  setDatatypeFoldsTotal('int64', sourGrapes=True)
168
- setDatatypeElephino('uint8', sourGrapes=True)
157
+ setDatatypeElephino('int16', sourGrapes=True)
169
158
  setDatatypeLeavesTotal('uint8', sourGrapes=True)
170
159
  Z0Z_setDatatypeModuleScalar('numba')
171
160
  Z0Z_setDecoratorCallable('jit')
@@ -4,42 +4,82 @@ everything I am doing. I would rather benefit from humanity's
4
4
  collective wisdom."""
5
5
  from mapFolding.someAssemblyRequired.synthesizeNumba import *
6
6
 
7
- def makeFlowNumbaOptimized(listCallablesInline: List[str], callableDispatcher: Optional[bool] = False, algorithmSource: Optional[ModuleType] = None, relativePathWrite: Optional[pathlib.Path] = None, formatFilenameWrite: Optional[str] = None) -> List[youOughtaKnow]:
8
- if relativePathWrite and relativePathWrite.is_absolute():
9
- raise ValueError("The path to write the module must be relative to the root of the package.")
10
- if not algorithmSource:
11
- algorithmSource = getAlgorithmSource()
7
+ def getFunctionDef(algorithmSource: ModuleType, *arguments, **keywordArguments) -> Tuple[ast.FunctionDef, UniversalImportTracker]:
8
+ pythonSource = inspect.getsource(algorithmSource)
9
+ astModule: ast.Module = ast.parse(pythonSource, type_comments=True)
10
+ FunctionDefTarget, allImports = makeFunctionDef(astModule, *arguments, **keywordArguments)
11
+ return FunctionDefTarget, allImports
12
12
 
13
- listStuffYouOughtaKnow: List[youOughtaKnow] = []
13
+ def makePythonSource(listFunctionDefs: List[ast.FunctionDef], listAstImports: List[ast.Import|ast.ImportFrom], additional_imports: List[str]) -> str:
14
+ astModule = ast.Module(body=cast(List[ast.stmt], listAstImports + listFunctionDefs), type_ignores=[])
15
+ ast.fix_missing_locations(astModule)
16
+ pythonSource = ast.unparse(astModule)
17
+ if not pythonSource: raise FREAKOUT
18
+ pythonSource = autoflake.fix_code(pythonSource, additional_imports)
19
+ return pythonSource
20
+
21
+ def writePythonAsModule(pythonSource: str, listCallableSynthesized: List[str], relativePathWrite: Optional[pathlib.Path], filenameWrite: Optional[str], formatFilenameWrite: Optional[str]) -> List[youOughtaKnow]:
22
+ pathFilename = None
23
+ if not relativePathWrite:
24
+ pathWrite = getPathSyntheticModules()
25
+ else:
26
+ pathWrite = getPathPackage() / relativePathWrite
14
27
 
15
- def doThisStuff(callableTarget: str, parametersNumba: Optional[ParametersNumba], inlineCallables: bool, unpackArrays: bool, allImports: Optional[UniversalImportTracker], relativePathWrite: Optional[pathlib.Path], formatFilenameWrite: Optional[str]) -> youOughtaKnow:
16
- pythonSource = inspect.getsource(algorithmSource)
17
- pythonSource = makeAstModuleForOneCallable(pythonSource, callableTarget, parametersNumba, inlineCallables, unpackArrays, allImports)
18
- if not pythonSource: raise FREAKOUT
19
- pythonSource = autoflake.fix_code(pythonSource, ['mapFolding', 'numba', 'numpy'])
28
+ if not formatFilenameWrite:
29
+ formatFilenameWrite = formatFilenameModuleDEFAULT
20
30
 
21
- if not relativePathWrite:
22
- pathWrite = getPathSyntheticModules()
31
+ if not filenameWrite:
32
+ if len(listCallableSynthesized) == 1:
33
+ callableTarget = listCallableSynthesized[0]
23
34
  else:
24
- pathWrite = getPathPackage() / relativePathWrite
25
- if not formatFilenameWrite:
26
- formatFilenameWrite = formatModuleNameDEFAULT + '.py'
27
- pathFilename = pathWrite / formatFilenameWrite.format(callableTarget=callableTarget)
35
+ callableTarget = 'count'
36
+ filenameWrite = formatFilenameWrite.format(callableTarget=callableTarget)
37
+ else:
38
+ if not filenameWrite.endswith('.py'):
39
+ warnings.warn(f"Filename {filenameWrite=} does not end with '.py'.")
28
40
 
29
- pathFilename.write_text(pythonSource)
41
+ pathFilename = pathWrite / filenameWrite
30
42
 
31
- howIsThisStillAThing = getPathPackage().parent
32
- dumbassPythonNamespace = pathFilename.relative_to(howIsThisStillAThing).with_suffix('').parts
33
- ImaModule = '.'.join(dumbassPythonNamespace)
43
+ pathFilename.write_text(pythonSource)
44
+
45
+ howIsThisStillAThing = getPathPackage().parent
46
+ dumbassPythonNamespace = pathFilename.relative_to(howIsThisStillAThing).with_suffix('').parts
47
+ ImaModule = '.'.join(dumbassPythonNamespace)
48
+
49
+ listStuffYouOughtaKnow: List[youOughtaKnow] = []
50
+
51
+ for callableTarget in listCallableSynthesized:
34
52
  astImportFrom = ast.ImportFrom(module=ImaModule, names=[ast.alias(name=callableTarget, asname=None)], level=0)
53
+ stuff = youOughtaKnow(callableSynthesized=callableTarget, pathFilenameForMe=pathFilename, astForCompetentProgrammers=astImportFrom)
54
+ listStuffYouOughtaKnow.append(stuff)
35
55
 
36
- return youOughtaKnow(callableSynthesized=callableTarget, pathFilenameForMe=pathFilename, astForCompetentProgrammers=astImportFrom)
56
+ return listStuffYouOughtaKnow
37
57
 
58
+ def makeFlowNumbaOptimized(listCallablesInline: List[str]
59
+ , callableDispatcher: Optional[bool] = False
60
+ , algorithmSource: Optional[ModuleType] = None
61
+ , relativePathWrite: Optional[pathlib.Path] = None
62
+ , filenameModuleWrite: Optional[str] = None
63
+ , formatFilenameWrite: Optional[str] = None
64
+ ) -> List[youOughtaKnow]:
65
+ if relativePathWrite and relativePathWrite.is_absolute():
66
+ raise ValueError("The path to write the module must be relative to the root of the package.")
67
+ if not algorithmSource:
68
+ algorithmSource = getAlgorithmSource()
69
+
70
+ Z0Z_filenameModuleWrite = 'numbaCount.py'
71
+
72
+ listStuffYouOughtaKnow: List[youOughtaKnow] = []
73
+ additional_imports = ['mapFolding', 'numba', 'numpy']
74
+
75
+ listFunctionDefs: List[ast.FunctionDef] = []
76
+ allImportsModule = UniversalImportTracker()
38
77
  for callableTarget in listCallablesInline:
39
78
  parametersNumba = None
40
79
  inlineCallables = True
41
80
  unpackArrays = False
42
81
  allImports = None
82
+ filenameWrite = None
43
83
  match callableTarget:
44
84
  case 'countParallel':
45
85
  parametersNumba = parametersNumbaSuperJitParallel
@@ -48,7 +88,17 @@ def makeFlowNumbaOptimized(listCallablesInline: List[str], callableDispatcher: O
48
88
  unpackArrays = True
49
89
  case 'countInitialize':
50
90
  parametersNumba = parametersNumbaDEFAULT
51
- listStuffYouOughtaKnow.append(doThisStuff(callableTarget, parametersNumba, inlineCallables, unpackArrays, allImports, relativePathWrite, formatFilenameWrite))
91
+ FunctionDefTarget, allImports = getFunctionDef(algorithmSource, callableTarget, parametersNumba, inlineCallables, unpackArrays, allImports)
92
+ listFunctionDefs.append(FunctionDefTarget)
93
+ allImportsModule.update(allImports)
94
+
95
+ listAstImports = allImportsModule.makeListAst()
96
+ pythonSource = makePythonSource(listFunctionDefs, listAstImports, additional_imports)
97
+
98
+ filenameWrite = filenameModuleWrite or Z0Z_filenameModuleWrite
99
+
100
+ listStuff = writePythonAsModule(pythonSource, listCallablesInline, relativePathWrite, filenameWrite, formatFilenameWrite)
101
+ listStuffYouOughtaKnow.extend(listStuff)
52
102
 
53
103
  if callableDispatcher:
54
104
  callableTarget = getAlgorithmDispatcher().__name__
@@ -56,22 +106,24 @@ def makeFlowNumbaOptimized(listCallablesInline: List[str], callableDispatcher: O
56
106
  inlineCallables = False
57
107
  unpackArrays = False
58
108
  allImports = UniversalImportTracker()
109
+ filenameWrite = None
59
110
  for stuff in listStuffYouOughtaKnow:
60
111
  statement = stuff.astForCompetentProgrammers
61
112
  if isinstance(statement, (ast.Import, ast.ImportFrom)):
62
113
  allImports.addAst(statement)
114
+ FunctionDefTarget, allImports = getFunctionDef(algorithmSource, callableTarget, parametersNumba, inlineCallables, unpackArrays, allImports)
115
+ listAstImports = allImports.makeListAst()
116
+
117
+ pythonSource = makePythonSource([FunctionDefTarget], listAstImports, additional_imports)
63
118
 
64
- listStuffYouOughtaKnow.append(doThisStuff(callableTarget, parametersNumba, inlineCallables, unpackArrays, allImports, relativePathWrite, formatFilenameWrite))
119
+ listStuff = writePythonAsModule(pythonSource, [callableTarget], relativePathWrite, filenameWrite, formatFilenameWrite)
120
+ listStuffYouOughtaKnow.extend(listStuff)
65
121
 
66
122
  return listStuffYouOughtaKnow
67
123
 
68
124
  if __name__ == '__main__':
69
- setDatatypeModule('numpy', sourGrapes=True)
70
- setDatatypeFoldsTotal('int64', sourGrapes=True)
71
- setDatatypeElephino('uint8', sourGrapes=True)
72
- setDatatypeLeavesTotal('uint8', sourGrapes=True)
73
- Z0Z_setDatatypeModuleScalar('numba')
74
- Z0Z_setDecoratorCallable('jit')
125
+ # Z0Z_setDatatypeModuleScalar('numba')
126
+ # Z0Z_setDecoratorCallable('jit')
75
127
  listCallablesInline: List[str] = ['countInitialize', 'countParallel', 'countSequential']
76
128
  callableDispatcher = True
77
129
  makeFlowNumbaOptimized(listCallablesInline, callableDispatcher)