mapFolding 0.3.10__py3-none-any.whl → 0.3.12__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: mapFolding
3
- Version: 0.3.10
3
+ Version: 0.3.12
4
4
  Summary: Count distinct ways to fold a map (or a strip of stamps)
5
5
  Author-email: Hunter Hogan <HunterHogan@pm.me>
6
6
  License: CC-BY-NC-4.0
@@ -26,6 +26,7 @@ Requires-Dist: numba
26
26
  Requires-Dist: numpy
27
27
  Requires-Dist: Z0Z_tools
28
28
  Provides-Extra: testing
29
+ Requires-Dist: autoflake; extra == "testing"
29
30
  Requires-Dist: more_itertools; extra == "testing"
30
31
  Requires-Dist: mypy; extra == "testing"
31
32
  Requires-Dist: pytest-cov; extra == "testing"
@@ -35,6 +36,7 @@ Requires-Dist: pytest-xdist; extra == "testing"
35
36
  Requires-Dist: pytest; extra == "testing"
36
37
  Requires-Dist: python_minifier; extra == "testing"
37
38
  Requires-Dist: types-setuptools; extra == "testing"
39
+ Requires-Dist: updateCitation; extra == "testing"
38
40
 
39
41
  # Algorithm(s) for counting distinct ways to fold a map (or a strip of stamps)
40
42
 
@@ -1,10 +1,10 @@
1
- mapFolding/__init__.py,sha256=-6hIljicU0Ql3yWpw8prpLGSQGUCHsNrSuf7zDNs_Ko,1169
1
+ mapFolding/__init__.py,sha256=XYw6cd3gQLFxoMuSSHwScp9-uFUU5B22Edy2pHNULJ8,1384
2
2
  mapFolding/basecamp.py,sha256=DISWQIzAF7o7WPUn2QZxMu3Ruwc0zkVPgceeUTUcfqo,3988
3
3
  mapFolding/beDRY.py,sha256=Gsj7NEBztbPoKszPibhW6pO9xwjAIPgaW411A_Quwz8,18654
4
4
  mapFolding/oeis.py,sha256=2kFIAnBu0Bs4rHceXqs1RyyEBM6A_5fR5562B4ShxVg,12311
5
- mapFolding/theDao.py,sha256=0ySeHdmNXA1X3aKs7tdJ1cQes_rWf9Vp0tdC1zSXf6U,13669
6
- mapFolding/theSSOT.py,sha256=vtqhR1E6wwqVKtGKBY0UBAGRYu6x3gtPBloBzzuZi6M,9826
7
- mapFolding/theSSOTnumba.py,sha256=ex_NnkGd3GWUQVrtWxKzsNmiSm2e091uhVmiZn0aPew,5568
5
+ mapFolding/theDao.py,sha256=qzZgXqI68NeKevMNZSFTnar4NsyploGTl-_Wwo8P-2s,14274
6
+ mapFolding/theSSOT.py,sha256=hl6VUR3P7e6JF3L4rHI_icnmNR1gJJUAI2rCvlQmCDs,10577
7
+ mapFolding/theSSOTnumba.py,sha256=SXPa9Qkr0IUFBb3k5__088IAS0imWHG8Aui2S27XbuE,5689
8
8
  mapFolding/reference/flattened.py,sha256=6blZ2Y9G8mu1F3gV8SKndPE398t2VVFlsgKlyeJ765A,16538
9
9
  mapFolding/reference/hunterNumba.py,sha256=HWndRgsajOf76rbb2LDNEZ6itsdYbyV-k3wgOFjeR6c,7104
10
10
  mapFolding/reference/irvineJavaPort.py,sha256=Sj-63Z-OsGuDoEBXuxyjRrNmmyl0d7Yz_XuY7I47Oyg,4250
@@ -14,16 +14,16 @@ mapFolding/reference/lunnanNumpy.py,sha256=HqDgSwTOZA-G0oophOEfc4zs25Mv4yw2aoF1v
14
14
  mapFolding/reference/lunnanWhile.py,sha256=7NY2IKO5XBgol0aWWF_Fi-7oTL9pvu_z6lB0TF1uVHk,4063
15
15
  mapFolding/reference/rotatedEntryPoint.py,sha256=z0QyDQtnMvXNj5ntWzzJUQUMFm1-xHGLVhtYzwmczUI,11530
16
16
  mapFolding/reference/total_countPlus1vsPlusN.py,sha256=usenM8Yn_G1dqlPl7NKKkcnbohBZVZBXTQRm2S3_EDA,8106
17
- mapFolding/someAssemblyRequired/__init__.py,sha256=O-r-Oy7HK8RtIhXjBo99BPn7kOY-zDo4r1X_B3CYscI,121
17
+ mapFolding/someAssemblyRequired/__init__.py,sha256=3JnAKXfaYPtmxV_4AnZ6KpCosT_0GFV5Nw7K8sz4-Uo,34
18
18
  mapFolding/someAssemblyRequired/getLLVMforNoReason.py,sha256=FtJzw2pZS3A4NimWdZsegXaU-vKeCw8m67kcfb5wvGM,894
19
- mapFolding/someAssemblyRequired/makeJob.py,sha256=j62UMwwGV3CtF0j6ByyCxOuRNDCtv3MqVGUEtBSsAfk,2589
20
- mapFolding/someAssemblyRequired/synthesizeJobNumba.py,sha256=fwWjayhHyef9UxpjGDpLKoCvkvwtVMITKczlEedUXpE,19358
19
+ mapFolding/someAssemblyRequired/makeJob.py,sha256=2RtRAHBMDAiOsJpnj1-J1Yso3beQu5hk8bUfgE367Zs,2592
21
20
  mapFolding/someAssemblyRequired/synthesizeModuleJAX.py,sha256=TU8lgoMr77pctvvmlfbT-XstQk4j6Jo8JcIuvAiCuMU,1316
22
- mapFolding/someAssemblyRequired/synthesizeModulesNumba.py,sha256=hg6FOJbaJcsiWrqv6sTqkxaXYkR_TKPyLS8sJGqRQB0,26460
23
- mapFolding/syntheticModules/numba_countInitialize.py,sha256=d_aptX7pbgLxiXJnr-t0W6znDXqX77r8clfKQOTZfBw,4210
24
- mapFolding/syntheticModules/numba_countParallel.py,sha256=W1157Xd8xwLXpRK82OMgL7AyFu0jh70_dHhrZ0mtYIs,5416
25
- mapFolding/syntheticModules/numba_countSequential.py,sha256=Se4FNea9XOEfTVRJkNNdJHpsKu0CcLJGKmqUHvMqmrU,3593
26
- mapFolding/syntheticModules/numba_doTheNeedful.py,sha256=DyfNpKHWSUD6vqL3gcv80eLvKeibtUm8aa-Zu_weuqE,2521
21
+ mapFolding/someAssemblyRequired/synthesizeNumba.py,sha256=6wQnKLj2hbj-z4enypYoDpS6LcrE6lMDYUQ8eXquv_o,33476
22
+ mapFolding/someAssemblyRequired/synthesizeNumbaHardcoding.py,sha256=aOATx1_cUcd7pb6YhdDe9ydL0QB6538NoFgyPKXzYpg,9994
23
+ mapFolding/syntheticModules/numba_countInitialize.py,sha256=Cpk3HETqlQhyX431RzmvBSgKOx7nX9ZC4iCyBYHldMA,4274
24
+ mapFolding/syntheticModules/numba_countParallel.py,sha256=5qrYl8InirBjzQKQh9eny7ajCU-pHk-oZS11alOxhJs,5517
25
+ mapFolding/syntheticModules/numba_countSequential.py,sha256=oMJ9W_ob9sIE-7xfFkFCjG83MeylJJCjmL3_xWHMUdk,3732
26
+ mapFolding/syntheticModules/numba_doTheNeedful.py,sha256=xbKeYWACpbVMNitWPQeTr8l-YY6Y228Lu_JRDjsAPfE,1369
27
27
  tests/__init__.py,sha256=eg9smg-6VblOr0kisM40CpGnuDtU2JgEEWGDTFVOlW8,57
28
28
  tests/conftest.py,sha256=tGRYkHfwVKGoMklBSQiTD8cTu-QL1wUSZd-52Xlnm50,7676
29
29
  tests/conftest_tmpRegistry.py,sha256=0XpGe7s2aJcjdEAqKs10vceW0_JAaK-Rp1UoPaL-BIo,2450
@@ -32,9 +32,9 @@ tests/test_oeis.py,sha256=F89HJ27y54NXcR2wMeBS4ea6R7EaEqpF_GkcU-BrsK4,5694
32
32
  tests/test_other.py,sha256=UpS0_WUfWA3wONuZwip5AMmzNmmBwYD7reQDZ9ziL_o,12224
33
33
  tests/test_tasks.py,sha256=ap_tKjHUN95vjzKo3xzBAQ3kMbdMJ_XXbOv9YIBJ5pY,2826
34
34
  tests/test_types.py,sha256=HklNCGThFiqQ89AOMkE7YkcfAPiZE32DpD3GMDUPQVc,177
35
- mapFolding-0.3.10.dist-info/LICENSE,sha256=NxH5Y8BdC-gNU-WSMwim3uMbID2iNDXJz7fHtuTdXhk,19346
36
- mapFolding-0.3.10.dist-info/METADATA,sha256=GYvtSr3qWSvPYIrPAlZuQZmUIxIVt0vkPYIn-X7WOnc,7690
37
- mapFolding-0.3.10.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
38
- mapFolding-0.3.10.dist-info/entry_points.txt,sha256=F3OUeZR1XDTpoH7k3wXuRb3KF_kXTTeYhu5AGK1SiOQ,146
39
- mapFolding-0.3.10.dist-info/top_level.txt,sha256=1gP2vFaqPwHujGwb3UjtMlLEGN-943VSYFR7V4gDqW8,17
40
- mapFolding-0.3.10.dist-info/RECORD,,
35
+ mapFolding-0.3.12.dist-info/LICENSE,sha256=NxH5Y8BdC-gNU-WSMwim3uMbID2iNDXJz7fHtuTdXhk,19346
36
+ mapFolding-0.3.12.dist-info/METADATA,sha256=y4-lXqgLwjgfGI3mlRHcNsaz3VjiGAsF3RpIFNLcj7g,7785
37
+ mapFolding-0.3.12.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
38
+ mapFolding-0.3.12.dist-info/entry_points.txt,sha256=F3OUeZR1XDTpoH7k3wXuRb3KF_kXTTeYhu5AGK1SiOQ,146
39
+ mapFolding-0.3.12.dist-info/top_level.txt,sha256=1gP2vFaqPwHujGwb3UjtMlLEGN-943VSYFR7V4gDqW8,17
40
+ mapFolding-0.3.12.dist-info/RECORD,,
@@ -1,383 +0,0 @@
1
- """
2
- It's rough, but it works. Actually, the modules it produces are lightening fast.
3
-
4
- Specific issues:
5
- - When trying to run the synthesized file, `ModuleNotFoundError: No module named '<dynamic>'` unless I first re-save the file in the IDE.
6
- - ast interprets the signature as `def countSequential() -> None:` even though there is a return statement.
7
- - Similarly, but possibly my fault, `decorateCallableWithNumba` doesn't add the return type to the signature.
8
-
9
- General issues:
10
- - an ironic dearth of abstract functionality in this module based on ast.
11
- - I don't have much experience with ast.
12
- - ast is one of the few cases that absolutely benefits from an OOP paradigm, and I am comically inept at OOP.
13
- - (almost) Everything prefixed with `Z0Z_` is something I want to substantially improve.
14
- - convergence with other synthesize modules and functions would be good.
15
- - while management of datatypes seems to be pretty good, managing pathFilenames could be better.
16
- - as of this writing, there are zero direct tests for `someAssemblyRequired`.
17
- """
18
- from mapFolding import indexMy, indexTrack, ParametersNumba, parametersNumbaDEFAULT, getFilenameFoldsTotal, getPathJobRootDEFAULT, getPathFilenameFoldsTotal
19
- from mapFolding import setDatatypeElephino, setDatatypeFoldsTotal, setDatatypeLeavesTotal, setDatatypeModule, hackSSOTdatatype, computationState
20
- from mapFolding.someAssemblyRequired import makeStateJob, decorateCallableWithNumba, Z0Z_UnhandledDecorators
21
- from typing import Optional, Callable, List, Sequence, cast, Dict, Set, Any, Union
22
- from Z0Z_tools import updateExtendPolishDictionaryLists
23
- import ast
24
- import collections
25
- import importlib
26
- import importlib.util
27
- import inspect
28
- import more_itertools
29
- import numpy
30
- import os
31
- import pathlib
32
- import python_minifier
33
-
34
- dictionaryImportFrom: Dict[str, List[str]] = collections.defaultdict(list)
35
- datatypeModuleScalar = 'numba'
36
-
37
- def makeStrRLEcompacted(arrayTarget: numpy.ndarray, identifierName: Optional[str]=None) -> str:
38
- """Converts a NumPy array into a compressed string representation using run-length encoding (RLE).
39
-
40
- This function takes a NumPy array and converts it into an optimized string representation by:
41
- 1. Compressing consecutive sequences of numbers into range objects
42
- 2. Minimizing repeated zeros using array multiplication syntax
43
- 3. Converting the result into a valid Python array initialization statement
44
-
45
- Parameters:
46
- arrayTarget (numpy.ndarray): The input NumPy array to be converted
47
- identifierName (str): The variable name to use in the output string
48
-
49
- Returns:
50
- str: A string containing Python code that recreates the input array in compressed form.
51
- Format: "{identifierName} = numpy.array({compressed_data}, dtype=numpy.{dtype})"
52
-
53
- Example:
54
- >>> arr = numpy.array([[0,0,0,1,2,3,4,0,0]])
55
- >>> print(makeStrRLEcompacted(arr, "myArray"))
56
- "myArray = numpy.array([[0]*3,*range(1,5),[0]*2], dtype=numpy.int64)"
57
- """
58
-
59
- def compressRangesNDArrayNoFlatten(arraySlice):
60
- if isinstance(arraySlice, numpy.ndarray) and arraySlice.ndim > 1:
61
- return [compressRangesNDArrayNoFlatten(arraySlice[index]) for index in range(arraySlice.shape[0])]
62
- elif isinstance(arraySlice, numpy.ndarray) and arraySlice.ndim == 1:
63
- listWithRanges = []
64
- for group in more_itertools.consecutive_groups(arraySlice.tolist()):
65
- ImaSerious = list(group)
66
- if len(ImaSerious) <= 4:
67
- listWithRanges += ImaSerious
68
- else:
69
- ImaRange = [range(ImaSerious[0], ImaSerious[-1] + 1)]
70
- listWithRanges += ImaRange
71
- return listWithRanges
72
- return arraySlice
73
-
74
- arrayAsNestedLists = compressRangesNDArrayNoFlatten(arrayTarget)
75
-
76
- stringMinimized = python_minifier.minify(str(arrayAsNestedLists))
77
- commaZeroMaximum = arrayTarget.shape[-1] - 1
78
- stringMinimized = stringMinimized.replace('[0' + ',0'*commaZeroMaximum + ']', '[0]*'+str(commaZeroMaximum+1))
79
- for countZeros in range(commaZeroMaximum, 2, -1):
80
- stringMinimized = stringMinimized.replace(',0'*countZeros + ']', ']+[0]*'+str(countZeros))
81
-
82
- stringMinimized = stringMinimized.replace('range', '*range')
83
-
84
- if identifierName:
85
- return f"{identifierName} = array({stringMinimized}, dtype={arrayTarget.dtype})"
86
- return stringMinimized
87
-
88
- def makeImports() -> List[List[ast.ImportFrom]]:
89
- global dictionaryImportFrom
90
- dictionaryImportFrom = updateExtendPolishDictionaryLists(dictionaryImportFrom, destroyDuplicates=True)
91
-
92
- def parseAlias(aliasString: str):
93
- parts = aliasString.split(" as ")
94
- if len(parts) == 2:
95
- return ast.alias(name=parts[0].strip(), asname=parts[1].strip())
96
- return ast.alias(name=aliasString.strip(), asname=None)
97
-
98
- importStatements = [[
99
- ast.ImportFrom(module=module, names=[ast.alias(name=identifierName, asname=None)
100
- for identifierName in listIdentifiers], level=0)
101
- for module, listIdentifiers in dictionaryImportFrom.items()]
102
- ]
103
-
104
- return importStatements
105
-
106
- def evaluateArrayIn_body(node: ast.FunctionDef, astArg: ast.arg, argData: numpy.ndarray) -> ast.FunctionDef:
107
- global dictionaryImportFrom
108
- arrayType = type(argData)
109
- moduleConstructor = arrayType.__module__
110
- constructorName = arrayType.__name__
111
- # NOTE hack
112
- constructorName = constructorName.replace('ndarray', 'array')
113
- dictionaryImportFrom[moduleConstructor].append(constructorName)
114
-
115
- for stmt in node.body.copy():
116
- if isinstance(stmt, ast.Assign):
117
- if isinstance(stmt.targets[0], ast.Name) and isinstance(stmt.value, ast.Subscript):
118
- astAssignee: ast.Name = stmt.targets[0]
119
- argData_dtypeName = hackSSOTdatatype(astAssignee.id)
120
- dictionaryImportFrom[moduleConstructor].append(argData_dtypeName)
121
- astSubscript: ast.Subscript = stmt.value
122
- if isinstance(astSubscript.value, ast.Name) and astSubscript.value.id == astArg.arg and isinstance(astSubscript.slice, ast.Attribute):
123
- indexAs_astAttribute: ast.Attribute = astSubscript.slice
124
- indexAsStr = ast.unparse(indexAs_astAttribute)
125
- argDataSlice = argData[eval(indexAsStr)]
126
-
127
- onlyDataRLE = makeStrRLEcompacted(argDataSlice)
128
- astStatement = cast(ast.Expr, ast.parse(onlyDataRLE).body[0])
129
- dataAst = astStatement.value
130
-
131
- arrayCall = ast.Call(
132
- func=ast.Name(id=constructorName, ctx=ast.Load()) , args=[dataAst]
133
- , keywords=[ast.keyword(arg='dtype', value=ast.Name(id=argData_dtypeName, ctx=ast.Load()) ) ] )
134
-
135
- assignment = ast.Assign( targets=[astAssignee], value=arrayCall )
136
- node.body.insert(0, assignment)
137
- node.body.remove(stmt)
138
-
139
- node.args.args.remove(astArg)
140
- return node
141
-
142
- def evaluate_argIn_body(node: ast.FunctionDef, astArg: ast.arg, argData: numpy.ndarray, Z0Z_listChaff: List[str]) -> ast.FunctionDef:
143
- global dictionaryImportFrom
144
- moduleConstructor = datatypeModuleScalar
145
- for stmt in node.body.copy():
146
- if isinstance(stmt, ast.Assign):
147
- if isinstance(stmt.targets[0], ast.Name) and isinstance(stmt.value, ast.Subscript):
148
- astAssignee: ast.Name = stmt.targets[0]
149
- argData_dtypeName = hackSSOTdatatype(astAssignee.id)
150
- dictionaryImportFrom[moduleConstructor].append(argData_dtypeName)
151
- astSubscript: ast.Subscript = stmt.value
152
- if isinstance(astSubscript.value, ast.Name) and astSubscript.value.id == astArg.arg and isinstance(astSubscript.slice, ast.Attribute):
153
- indexAs_astAttribute: ast.Attribute = astSubscript.slice
154
- indexAsStr = ast.unparse(indexAs_astAttribute)
155
- argDataSlice: int = argData[eval(indexAsStr)].item()
156
- astCall = ast.Call(func=ast.Name(id=argData_dtypeName, ctx=ast.Load()) , args=[ast.Constant(value=argDataSlice)], keywords=[])
157
- assignment = ast.Assign(targets=[astAssignee], value=astCall)
158
- if astAssignee.id not in Z0Z_listChaff:
159
- node.body.insert(0, assignment)
160
- node.body.remove(stmt)
161
- node.args.args.remove(astArg)
162
- return node
163
-
164
- def evaluateAnnAssignIn_body(node: ast.FunctionDef) -> ast.FunctionDef:
165
- global dictionaryImportFrom
166
- moduleConstructor = datatypeModuleScalar
167
- for stmt in node.body.copy():
168
- if isinstance(stmt, ast.AnnAssign):
169
- if isinstance(stmt.target, ast.Name) and isinstance(stmt.value, ast.Constant):
170
- astAssignee: ast.Name = stmt.target
171
- argData_dtypeName = hackSSOTdatatype(astAssignee.id)
172
- dictionaryImportFrom[moduleConstructor].append(argData_dtypeName)
173
- astCall = ast.Call(func=ast.Name(id=argData_dtypeName, ctx=ast.Load()) , args=[stmt.value], keywords=[])
174
- assignment = ast.Assign(targets=[astAssignee], value=astCall)
175
- node.body.insert(0, assignment)
176
- node.body.remove(stmt)
177
- return node
178
-
179
- def move_argTo_body(node: ast.FunctionDef, astArg: ast.arg, argData: numpy.ndarray) -> ast.FunctionDef:
180
- arrayType = type(argData)
181
- moduleConstructor = arrayType.__module__
182
- constructorName = arrayType.__name__
183
- # NOTE hack
184
- constructorName = constructorName.replace('ndarray', 'array')
185
- argData_dtype: numpy.dtype = argData.dtype
186
- argData_dtypeName = argData.dtype.name
187
-
188
- global dictionaryImportFrom
189
- dictionaryImportFrom[moduleConstructor].append(constructorName)
190
- dictionaryImportFrom[moduleConstructor].append(argData_dtypeName)
191
-
192
- onlyDataRLE = makeStrRLEcompacted(argData)
193
- astStatement = cast(ast.Expr, ast.parse(onlyDataRLE).body[0])
194
- dataAst = astStatement.value
195
-
196
- arrayCall = ast.Call(
197
- func=ast.Name(id=constructorName, ctx=ast.Load())
198
- , args=[dataAst]
199
- , keywords=[ast.keyword(arg='dtype' , value=ast.Name(id=argData_dtypeName , ctx=ast.Load()) ) ] )
200
-
201
- assignment = ast.Assign( targets=[ast.Name(id=astArg.arg, ctx=ast.Store())], value=arrayCall )
202
- node.body.insert(0, assignment)
203
- node.args.args.remove(astArg)
204
-
205
- return node
206
-
207
- def makeDecorator(FunctionDefTarget: ast.FunctionDef, parametersNumba: Optional[ParametersNumba]=None) -> ast.FunctionDef:
208
- if parametersNumba is None:
209
- parametersNumbaExtracted: Dict[str, Any] = {}
210
- for decoratorItem in FunctionDefTarget.decorator_list.copy():
211
- if isinstance(decoratorItem, ast.Call) and isinstance(decoratorItem.func, ast.Attribute):
212
- if getattr(decoratorItem.func.value, "id", None) == "numba" and decoratorItem.func.attr == "jit":
213
- FunctionDefTarget.decorator_list.remove(decoratorItem)
214
- for keywordItem in decoratorItem.keywords:
215
- if isinstance(keywordItem.value, ast.Constant) and keywordItem.arg is not None:
216
- parametersNumbaExtracted[keywordItem.arg] = keywordItem.value.value
217
- if parametersNumbaExtracted:
218
- parametersNumba = ParametersNumba(parametersNumbaExtracted) # type: ignore
219
- else:
220
- # TODO code duplication
221
- for decoratorItem in FunctionDefTarget.decorator_list.copy():
222
- if isinstance(decoratorItem, ast.Call) and isinstance(decoratorItem.func, ast.Attribute):
223
- if getattr(decoratorItem.func.value, "id", None) == "numba" and decoratorItem.func.attr == "jit":
224
- FunctionDefTarget.decorator_list.remove(decoratorItem)
225
- FunctionDefTarget = Z0Z_UnhandledDecorators(FunctionDefTarget)
226
- global dictionaryImportFrom
227
- dictionaryImportFrom['numba'].append('jit')
228
- FunctionDefTarget = decorateCallableWithNumba(FunctionDefTarget, parametersNumba)
229
- # make sure the decorator is rendered as `@jit` and not `@numba.jit`
230
- for decoratorItem in FunctionDefTarget.decorator_list:
231
- if isinstance(decoratorItem, ast.Call) and isinstance(decoratorItem.func, ast.Attribute) and decoratorItem.func.attr == "jit":
232
- decoratorItem.func = ast.Name(id="jit", ctx=ast.Load())
233
- return FunctionDefTarget
234
-
235
- def makeLauncher(identifierCallable: str) -> ast.Module:
236
- linesLaunch = f"""
237
- if __name__ == '__main__':
238
- import time
239
- timeStart = time.perf_counter()
240
- {identifierCallable}()
241
- print(time.perf_counter() - timeStart)
242
- """
243
- astLaunch = ast.parse(linesLaunch)
244
- return astLaunch
245
-
246
- def make_writeFoldsTotal(stateJob: computationState, pathFilenameFoldsTotal: pathlib.Path) -> ast.Module:
247
- global dictionaryImportFrom
248
- dictionaryImportFrom['numba'].append("objmode")
249
- linesWriteFoldsTotal = f"""
250
- groupsOfFolds *= {str(stateJob['foldGroups'][-1])}
251
- print(groupsOfFolds)
252
- with objmode():
253
- open('{pathFilenameFoldsTotal.as_posix()}', 'w').write(str(groupsOfFolds))
254
- return groupsOfFolds
255
- """
256
- return ast.parse(linesWriteFoldsTotal)
257
-
258
- def removeIdentifierFrom_body(node: ast.FunctionDef, astArg: ast.arg) -> ast.FunctionDef:
259
- for stmt in node.body.copy():
260
- if isinstance(stmt, ast.Assign):
261
- if isinstance(stmt.targets[0], ast.Subscript) and isinstance(stmt.targets[0].value, ast.Name):
262
- if stmt.targets[0].value.id == astArg.arg:
263
- node.body.remove(stmt)
264
- node.args.args.remove(astArg)
265
- return node
266
-
267
- def astObjectToAstConstant(astFunction: ast.FunctionDef, object: str, value: int) -> ast.FunctionDef:
268
- """
269
- Replaces nodes in astFunction matching the AST of the string `object`
270
- with a constant node holding the provided value.
271
- """
272
- targetExpression = ast.parse(object, mode='eval').body
273
- targetDump = ast.dump(targetExpression, annotate_fields=False)
274
-
275
- class ReplaceObjectWithConstant(ast.NodeTransformer):
276
- def __init__(self, targetDump: str, constantValue: int) -> None:
277
- self.targetDump = targetDump
278
- self.constantValue = constantValue
279
-
280
- def generic_visit(self, node: ast.AST) -> ast.AST:
281
- currentDump = ast.dump(node, annotate_fields=False)
282
- if currentDump == self.targetDump:
283
- return ast.copy_location(ast.Constant(value=self.constantValue), node)
284
- return super().generic_visit(node)
285
-
286
- transformer = ReplaceObjectWithConstant(targetDump, value)
287
- newFunction = transformer.visit(astFunction)
288
- ast.fix_missing_locations(newFunction)
289
- return newFunction
290
-
291
- def astNameToAstConstant(astFunction: ast.FunctionDef, name: str, value: int) -> ast.FunctionDef:
292
- class ReplaceNameWithConstant(ast.NodeTransformer):
293
- def visit_Name(self, node: ast.Name) -> ast.AST:
294
- if node.id == name:
295
- return ast.copy_location(ast.Constant(value=value), node)
296
- return node
297
- return ReplaceNameWithConstant().visit(astFunction)
298
-
299
- def writeJobNumba(listDimensions: Sequence[int], callableSource: Callable, parametersNumba: Optional[ParametersNumba]=None, pathFilenameWriteJob: Optional[Union[str, os.PathLike[str]]] = None) -> pathlib.Path:
300
- stateJob = makeStateJob(listDimensions, writeJob=False)
301
- codeSource = inspect.getsource(callableSource)
302
- astSource = ast.parse(codeSource)
303
-
304
- pathFilenameFoldsTotal = getPathFilenameFoldsTotal(stateJob['mapShape'])
305
-
306
- FunctionDefTarget = next((node for node in astSource.body if isinstance(node, ast.FunctionDef) and node.name == callableSource.__name__), None)
307
-
308
- if not FunctionDefTarget:
309
- raise ValueError(f"Could not find function {callableSource.__name__} in source code")
310
-
311
- Z0Z_listArgsTarget = ['connectionGraph', 'gapsWhere']
312
- Z0Z_listArraysEvaluate = ['track']
313
- Z0Z_listArgsEvaluate = ['my']
314
- Z0Z_listChaff = ['taskIndex', 'dimensionsTotal']
315
- Z0Z_listArgsRemove = ['foldGroups']
316
- for astArgument in FunctionDefTarget.args.args.copy():
317
- if astArgument.arg in Z0Z_listArgsTarget:
318
- FunctionDefTarget = move_argTo_body(FunctionDefTarget, astArgument, stateJob[astArgument.arg])
319
- elif astArgument.arg in Z0Z_listArraysEvaluate:
320
- FunctionDefTarget = evaluateArrayIn_body(FunctionDefTarget, astArgument, stateJob[astArgument.arg])
321
- elif astArgument.arg in Z0Z_listArgsEvaluate:
322
- FunctionDefTarget = evaluate_argIn_body(FunctionDefTarget, astArgument, stateJob[astArgument.arg], Z0Z_listChaff)
323
- elif astArgument.arg in Z0Z_listArgsRemove:
324
- FunctionDefTarget = removeIdentifierFrom_body(FunctionDefTarget, astArgument)
325
-
326
- FunctionDefTarget = evaluateAnnAssignIn_body(FunctionDefTarget)
327
- FunctionDefTarget = astNameToAstConstant(FunctionDefTarget, 'dimensionsTotal', int(stateJob['my'][indexMy.dimensionsTotal]))
328
- FunctionDefTarget = astObjectToAstConstant(FunctionDefTarget, 'foldGroups[-1]', int(stateJob['foldGroups'][-1]))
329
-
330
- global identifierCallableLaunch
331
- identifierCallableLaunch = FunctionDefTarget.name
332
-
333
- FunctionDefTarget = makeDecorator(FunctionDefTarget, parametersNumba)
334
-
335
- astWriteFoldsTotal = make_writeFoldsTotal(stateJob, pathFilenameFoldsTotal)
336
- FunctionDefTarget.body += astWriteFoldsTotal.body
337
-
338
- astLauncher = makeLauncher(FunctionDefTarget.name)
339
-
340
- astImports = makeImports()
341
-
342
- astModule = ast.Module(
343
- body=cast(List[ast.stmt]
344
- , astImports
345
- + [FunctionDefTarget]
346
- + [astLauncher])
347
- , type_ignores=[]
348
- )
349
- ast.fix_missing_locations(astModule)
350
-
351
- codeSource = ast.unparse(astModule)
352
-
353
- if pathFilenameWriteJob is None:
354
- filename = getFilenameFoldsTotal(stateJob['mapShape'])
355
- pathRoot = getPathJobRootDEFAULT()
356
- pathFilenameWriteJob = pathlib.Path(pathRoot, pathlib.Path(filename).stem, pathlib.Path(filename).with_suffix('.py'))
357
- else:
358
- pathFilenameWriteJob = pathlib.Path(pathFilenameWriteJob)
359
- pathFilenameWriteJob.parent.mkdir(parents=True, exist_ok=True)
360
-
361
- pathFilenameWriteJob.write_text(codeSource)
362
- return pathFilenameWriteJob
363
-
364
- if __name__ == '__main__':
365
- listDimensions = [2,15]
366
- setDatatypeFoldsTotal('int64', sourGrapes=True)
367
- setDatatypeElephino('uint8', sourGrapes=True)
368
- setDatatypeLeavesTotal('uint8', sourGrapes=True)
369
- from mapFolding.syntheticModules.numba_countSequential import countSequential
370
- callableSource = countSequential
371
- pathFilenameModule = writeJobNumba(listDimensions, callableSource, parametersNumbaDEFAULT)
372
-
373
- # Induce numba.jit compilation
374
- # TODO Inducing compilation might be causing the `ModuleNotFoundError: No module named '<dynamic>'` error
375
-
376
- # moduleSpec = importlib.util.spec_from_file_location(pathFilenameModule.stem, pathFilenameModule)
377
- # if moduleSpec is None: raise ImportError(f"Could not load module specification from {pathFilenameModule}")
378
- # module = importlib.util.module_from_spec(moduleSpec)
379
- # if moduleSpec.loader is None: raise ImportError(f"Could not load module from {moduleSpec}")
380
- # moduleSpec.loader.exec_module(module)
381
-
382
- # from mapFolding.someAssemblyRequired.getLLVMforNoReason import writeModuleLLVM
383
- # pathFilenameLLVM = writeModuleLLVM(pathFilenameModule, identifierCallableLaunch)