mapFolding 0.3.10__py3-none-any.whl → 0.3.11__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,533 +0,0 @@
1
- from mapFolding import (
2
- EnumIndices,
3
- getAlgorithmSource,
4
- getPathPackage,
5
- getPathSyntheticModules,
6
- hackSSOTdatatype,
7
- hackSSOTdtype,
8
- indexMy,
9
- indexTrack,
10
- moduleOfSyntheticModules,
11
- myPackageNameIs,
12
- ParametersNumba,
13
- parametersNumbaSuperJit,
14
- parametersNumbaFailEarly,
15
- parametersNumbaSuperJitParallel,
16
- parametersNumbaDEFAULT,
17
- setDatatypeElephino,
18
- setDatatypeFoldsTotal,
19
- setDatatypeLeavesTotal,
20
- setDatatypeModule,
21
- )
22
- from typing import cast, Dict, List, Optional, Sequence, Set, Tuple, Type, Union
23
- from types import ModuleType
24
- from collections import namedtuple
25
- import ast
26
- import inspect
27
- import numba
28
- import numpy
29
- import pathlib
30
-
31
- youOughtaKnow = namedtuple('youOughtaKnow', ['callableSynthesized', 'pathFilenameForMe', 'astForCompetentProgrammers'])
32
-
33
- """TODO
34
- Convert types
35
- e.g. `groupsOfFolds: int = 0` to `groupsOfFolds = numba.types.{datatypeLarge}(0)`
36
- This isn't necessary for Numba, but I may the infrastructure for other compilers or paradigms."""
37
-
38
- def Z0Z_UnhandledDecorators(astCallable: ast.FunctionDef) -> ast.FunctionDef:
39
- # TODO: more explicit handling of decorators. I'm able to ignore this because I know `algorithmSource` doesn't have any decorators.
40
- for decoratorItem in astCallable.decorator_list.copy():
41
- import warnings
42
- astCallable.decorator_list.remove(decoratorItem)
43
- warnings.warn(f"Removed decorator {ast.unparse(decoratorItem)} from {astCallable.name}")
44
- return astCallable
45
-
46
- class RecursiveInliner(ast.NodeTransformer):
47
- """
48
- Class RecursiveInliner:
49
- A custom AST NodeTransformer designed to recursively inline function calls from a given dictionary
50
- of function definitions into the AST. Once a particular function has been inlined, it is marked
51
- as completed to avoid repeated inlining. This transformation modifies the AST in-place by substituting
52
- eligible function calls with the body of their corresponding function.
53
- Attributes:
54
- dictionaryFunctions (Dict[str, ast.FunctionDef]):
55
- A mapping of function name to its AST definition, used as a source for inlining.
56
- callablesCompleted (Set[str]):
57
- A set to track function names that have already been inlined to prevent multiple expansions.
58
- Methods:
59
- inlineFunctionBody(callableTargetName: str) -> Optional[ast.FunctionDef]:
60
- Retrieves the AST definition for a given function name from dictionaryFunctions
61
- and recursively inlines any function calls within it. Returns the function definition
62
- that was inlined or None if the function was already processed.
63
- visit_Call(callNode: ast.Call) -> ast.AST:
64
- Inspects calls within the AST. If a function call matches one in dictionaryFunctions,
65
- it is replaced by the inlined body. If the last statement in the inlined body is a return
66
- or an expression, that value or expression is substituted; otherwise, a constant is returned.
67
- visit_Expr(node: ast.Expr) -> Union[ast.AST, List[ast.AST]]:
68
- Handles expression nodes in the AST. If the expression is a function call from
69
- dictionaryFunctions, its statements are expanded in place, effectively inlining
70
- the called function's statements into the surrounding context.
71
- """
72
- def __init__(self, dictionaryFunctions: Dict[str, ast.FunctionDef]):
73
- self.dictionaryFunctions = dictionaryFunctions
74
- self.callablesCompleted: Set[str] = set()
75
-
76
- def inlineFunctionBody(self, callableTargetName: str) -> Optional[ast.FunctionDef]:
77
- if (callableTargetName in self.callablesCompleted):
78
- return None
79
-
80
- self.callablesCompleted.add(callableTargetName)
81
- inlineDefinition = self.dictionaryFunctions[callableTargetName]
82
- for astNode in ast.walk(inlineDefinition):
83
- self.visit(astNode)
84
- return inlineDefinition
85
-
86
- def visit_Call(self, node: ast.Call) -> ast.AST:
87
- callNodeVisited = self.generic_visit(node)
88
- if (isinstance(callNodeVisited, ast.Call) and isinstance(callNodeVisited.func, ast.Name) and callNodeVisited.func.id in self.dictionaryFunctions):
89
- inlineDefinition = self.inlineFunctionBody(callNodeVisited.func.id)
90
- if (inlineDefinition and inlineDefinition.body):
91
- statementTerminating = inlineDefinition.body[-1]
92
- if (isinstance(statementTerminating, ast.Return) and statementTerminating.value is not None):
93
- return self.visit(statementTerminating.value)
94
- elif (isinstance(statementTerminating, ast.Expr) and statementTerminating.value is not None):
95
- return self.visit(statementTerminating.value)
96
- return ast.Constant(value=None)
97
- return callNodeVisited
98
-
99
- def visit_Expr(self, node: ast.Expr) -> Union[ast.AST, List[ast.AST]]:
100
- if (isinstance(node.value, ast.Call)):
101
- if (isinstance(node.value.func, ast.Name) and node.value.func.id in self.dictionaryFunctions):
102
- inlineDefinition = self.inlineFunctionBody(node.value.func.id)
103
- if (inlineDefinition):
104
- return [self.visit(stmt) for stmt in inlineDefinition.body]
105
- return self.generic_visit(node)
106
-
107
- def decorateCallableWithNumba(astCallable: ast.FunctionDef, parametersNumba: Optional[ParametersNumba]=None) -> ast.FunctionDef:
108
- """
109
- Decorates an AST function definition with Numba JIT compilation parameters.
110
-
111
- This function processes an AST FunctionDef node and adds Numba-specific decorators
112
- for JIT compilation. It handles array parameter typing and compilation options.
113
-
114
- Parameters
115
- ----------
116
-
117
- astCallable : ast.FunctionDef
118
- The AST node representing the function to be decorated with Numba JIT.
119
- parallel : bool, optional
120
- Whether to enable parallel execution in Numba compilation.
121
- Default is False.
122
-
123
- Returns
124
- -------
125
-
126
- ast.FunctionDef
127
- The modified AST function definition node with added Numba decorators.
128
-
129
- Notes
130
- -----
131
- The function performs the following main tasks:
132
- 1. Processes function parameters to create Numba-compatible type signatures
133
- 2. Constructs appropriate Numba compilation parameters
134
- 3. Creates and attaches a @numba.jit decorator to the function
135
- Special handling is included for the 'countInitialize' function, which receives
136
- empty compilation parameters.
137
- The function relies on external parameters:
138
- - parametersNumbaDEFAULT: Default Numba compilation parameters
139
- - ParametersNumba: Class/type for handling Numba parameters
140
- - hackSSOTdatatype: Function for determining default datatypes
141
- """
142
- def makeNumbaParameterSignatureElement(signatureElement: ast.arg):
143
- """
144
- Converts an AST function parameter signature element into a Numba-compatible type annotation.
145
-
146
- This function processes parameter annotations for array types, handling both shape and datatype
147
- specifications. It supports multi-dimensional arrays through tuple-based shape definitions and
148
- various numeric datatypes.
149
-
150
- Parameters
151
- ----------
152
- signatureElement : ast.arg
153
- The AST argument node containing the parameter's name and type annotation.
154
- Expected annotation format: Type[shape_tuple, dtype]
155
- where shape_tuple can be either a single dimension or a tuple of dimensions,
156
- and dtype specifies the data type.
157
-
158
- Returns
159
- -------
160
- ast.Subscript
161
- A Numba-compatible type annotation as an AST node, representing an array type
162
- with the specified shape and datatype.
163
-
164
- Notes
165
- -----
166
- The function handles two main cases for shape specifications:
167
- 1. Multi-dimensional arrays with tuple-based shapes
168
- 2. Single-dimension arrays with simple slice notation
169
- The datatype can be either explicitly specified in the annotation or determined
170
- through a fallback mechanism using hackSSOTdatatype().
171
- """
172
- if isinstance(signatureElement.annotation, ast.Subscript) and isinstance(signatureElement.annotation.slice, ast.Tuple):
173
- annotationShape = signatureElement.annotation.slice.elts[0]
174
- if isinstance(annotationShape, ast.Subscript) and isinstance(annotationShape.slice, ast.Tuple):
175
- shapeAsListSlices: Sequence[ast.expr] = [ast.Slice() for axis in range(len(annotationShape.slice.elts))]
176
- shapeAsListSlices[-1] = ast.Slice(step=ast.Constant(value=1))
177
- shapeAST = ast.Tuple(elts=list(shapeAsListSlices), ctx=ast.Load())
178
- else:
179
- shapeAST = ast.Slice(step=ast.Constant(value=1))
180
-
181
- annotationDtype = signatureElement.annotation.slice.elts[1]
182
- if (isinstance(annotationDtype, ast.Subscript) and isinstance(annotationDtype.slice, ast.Attribute)):
183
- datatypeAST = annotationDtype.slice.attr
184
- else:
185
- datatypeAST = None
186
-
187
- ndarrayName = signatureElement.arg
188
- Z0Z_hacky_dtype = hackSSOTdatatype(ndarrayName)
189
- datatype_attr = datatypeAST or Z0Z_hacky_dtype
190
-
191
- datatypeNumba = ast.Attribute(value=ast.Name(id='numba', ctx=ast.Load()), attr=datatype_attr, ctx=ast.Load())
192
-
193
- return ast.Subscript(value=datatypeNumba, slice=shapeAST, ctx=ast.Load())
194
-
195
- astCallable = Z0Z_UnhandledDecorators(astCallable)
196
-
197
- listNumbaParameterSignature: Sequence[ast.expr] = []
198
- for parameter in astCallable.args.args:
199
- signatureElement = makeNumbaParameterSignatureElement(parameter)
200
- if (signatureElement):
201
- listNumbaParameterSignature.append(signatureElement)
202
-
203
- astTupleSignatureParameters = ast.Tuple(elts=listNumbaParameterSignature, ctx=ast.Load())
204
-
205
- # TODO if `astCallable` has a return, the return needs to be added to `astArgsNumbaSignature` in the appropriate place
206
- # The return, when placed in the args, is treated as a `Call`. This is logical because numba is converting to machine code.
207
- # , args=[Call(func=Name(id='int64', ctx=Load()))]
208
- ast_argsSignature = astTupleSignatureParameters
209
-
210
- ImaReturn = next((node for node in astCallable.body if isinstance(node, ast.Return)), None)
211
- # Return(value=Name(id='groupsOfFolds', ctx=Load()))]
212
- if ImaReturn is not None and isinstance(ImaReturn.value, ast.Name):
213
- my_idIf_I_wereA_astCall_func_astName_idParameter = ImaReturn.value.id
214
- ast_argsSignature = ast.Call(
215
- func=ast.Name(id=my_idIf_I_wereA_astCall_func_astName_idParameter, ctx=ast.Load()),
216
- args=[astTupleSignatureParameters],
217
- keywords=[]
218
- )
219
- else:
220
- ast_argsSignature = astTupleSignatureParameters
221
-
222
- if parametersNumba is None:
223
- parametersNumba = parametersNumbaDEFAULT
224
-
225
- listKeywordsNumbaSignature = [ast.keyword(arg=parameterName, value=ast.Constant(value=parameterValue)) for parameterName, parameterValue in parametersNumba.items()]
226
-
227
- astDecoratorNumba = ast.Call(func=ast.Attribute(value=ast.Name(id='numba', ctx=ast.Load()), attr='jit', ctx=ast.Load()), args=[ast_argsSignature], keywords=listKeywordsNumbaSignature)
228
-
229
- astCallable.decorator_list = [astDecoratorNumba]
230
- return astCallable
231
-
232
- class UnpackArrayAccesses(ast.NodeTransformer):
233
- """
234
- A class that transforms array accesses using enum indices into local variables.
235
-
236
- This AST transformer identifies array accesses using enum indices and replaces them
237
- with local variables, adding initialization statements at the start of functions.
238
-
239
- Parameters:
240
- enumIndexClass (Type[EnumIndices]): The enum class used for array indexing
241
- arrayName (str): The name of the array being accessed
242
-
243
- Attributes:
244
- enumIndexClass (Type[EnumIndices]): Stored enum class for index lookups
245
- arrayName (str): Name of the array being transformed
246
- substitutions (dict): Tracks variable substitutions and their original nodes
247
-
248
- The transformer handles two main cases:
249
- 1. Scalar array access - array[EnumIndices.MEMBER]
250
- 2. Array slice access - array[EnumIndices.MEMBER, other_indices...]
251
- For each identified access pattern, it:
252
- 1. Creates a local variable named after the enum member
253
- 2. Adds initialization code at function start
254
- 3. Replaces original array access with the local variable
255
- """
256
-
257
- def __init__(self, enumIndexClass: Type[EnumIndices], arrayName: str):
258
- self.enumIndexClass = enumIndexClass
259
- self.arrayName = arrayName
260
- self.substitutions = {}
261
-
262
- def extract_member_name(self, node: ast.AST) -> Optional[str]:
263
- """Recursively extract enum member name from any node in the AST."""
264
- if isinstance(node, ast.Attribute) and node.attr == 'value':
265
- innerAttribute = node.value
266
- while isinstance(innerAttribute, ast.Attribute):
267
- if (isinstance(innerAttribute.value, ast.Name) and innerAttribute.value.id == self.enumIndexClass.__name__):
268
- return innerAttribute.attr
269
- innerAttribute = innerAttribute.value
270
- return None
271
-
272
- def transform_slice_element(self, node: ast.AST) -> ast.AST:
273
- """Transform any enum references within a slice element."""
274
- if isinstance(node, ast.Subscript):
275
- if isinstance(node.slice, ast.Attribute):
276
- member_name = self.extract_member_name(node.slice)
277
- if member_name:
278
- return ast.Name(id=member_name, ctx=node.ctx)
279
- elif isinstance(node, ast.Tuple):
280
- # Handle tuple slices by transforming each element
281
- return ast.Tuple(elts=cast(List[ast.expr], [self.transform_slice_element(elt) for elt in node.elts]), ctx=node.ctx)
282
- elif isinstance(node, ast.Attribute):
283
- member_name = self.extract_member_name(node)
284
- if member_name:
285
- return ast.Name(id=member_name, ctx=ast.Load())
286
- return node
287
-
288
- def visit_Subscript(self, node: ast.Subscript) -> ast.AST:
289
- # Recursively visit any nested subscripts in value or slice
290
- node.value = self.visit(node.value)
291
- node.slice = self.visit(node.slice)
292
- # If node.value is not our arrayName, just return node
293
- if not (isinstance(node.value, ast.Name) and node.value.id == self.arrayName):
294
- return node
295
-
296
- # Handle scalar array access
297
- if isinstance(node.slice, ast.Attribute):
298
- memberName = self.extract_member_name(node.slice)
299
- if memberName:
300
- self.substitutions[memberName] = ('scalar', node)
301
- return ast.Name(id=memberName, ctx=ast.Load())
302
-
303
- # Handle array slice access
304
- if isinstance(node.slice, ast.Tuple) and node.slice.elts:
305
- firstElement = node.slice.elts[0]
306
- memberName = self.extract_member_name(firstElement)
307
- sliceRemainder = [self.visit(elem) for elem in node.slice.elts[1:]]
308
- if memberName:
309
- self.substitutions[memberName] = ('array', node)
310
- if len(sliceRemainder) == 0:
311
- return ast.Name(id=memberName, ctx=ast.Load())
312
- return ast.Subscript(value=ast.Name(id=memberName, ctx=ast.Load()), slice=ast.Tuple(elts=sliceRemainder, ctx=ast.Load()) if len(sliceRemainder) > 1 else sliceRemainder[0], ctx=ast.Load())
313
-
314
- # If single-element tuple, unwrap
315
- if isinstance(node.slice, ast.Tuple) and len(node.slice.elts) == 1:
316
- node.slice = node.slice.elts[0]
317
-
318
- return node
319
-
320
- def visit_FunctionDef(self, node: ast.FunctionDef) -> ast.FunctionDef:
321
- node = cast(ast.FunctionDef, self.generic_visit(node))
322
-
323
- initializations = []
324
- for name, (kind, original_node) in self.substitutions.items():
325
- if kind == 'scalar':
326
- initializations.append(ast.Assign(targets=[ast.Name(id=name, ctx=ast.Store())], value=original_node))
327
- else: # array
328
- initializations.append(
329
- ast.Assign(
330
- targets=[ast.Name(id=name, ctx=ast.Store())],
331
- value=ast.Subscript(value=ast.Name(id=self.arrayName, ctx=ast.Load()),
332
- slice=ast.Attribute(value=ast.Attribute(
333
- value=ast.Name(id=self.enumIndexClass.__name__, ctx=ast.Load()),
334
- attr=name, ctx=ast.Load()), attr='value', ctx=ast.Load()), ctx=ast.Load())))
335
-
336
- node.body = initializations + node.body
337
- return node
338
-
339
- def inlineOneCallable(codeSource: str, callableTarget: str):
340
-
341
- """
342
- Inlines a target callable function and its dependencies within the provided code source.
343
-
344
- This function performs function inlining, optionally adds Numba decorators, and handles array access unpacking
345
- for specific callable targets. It processes the source code through AST manipulation and returns the modified source.
346
-
347
- Parameters:
348
- codeSource (str): The source code containing the callable to be inlined.
349
- callableTarget (str): The name of the callable function to be inlined. Special handling is provided for
350
- 'countParallel', 'countInitialize', and 'countSequential'.
351
-
352
- Returns:
353
- str: The modified source code with the inlined callable and necessary imports.
354
-
355
- The function performs the following operations:
356
- 1. Parses the source code into an AST
357
- 2. Extracts import statements and function definitions
358
- 3. Inlines the target function using RecursiveInliner
359
- 4. Applies Numba decoration if needed
360
- 5. Handles special array access unpacking for 'countSequential'
361
- 6. Reconstructs and returns the modified source code
362
-
363
- Note:
364
- - Special handling is provided for 'countParallel', 'countInitialize', and 'countSequential' targets
365
- - For 'countSequential', additional array access unpacking is performed for 'my' and 'track' indices
366
- - `UnpackArrayAccesses` would need modification to handle 'countParallel'
367
- """
368
-
369
- codeParsed: ast.Module = ast.parse(codeSource, type_comments=True)
370
- codeSourceImportStatements = {statement for statement in codeParsed.body if isinstance(statement, (ast.Import, ast.ImportFrom))}
371
- dictionaryFunctions = {statement.name: statement for statement in codeParsed.body if isinstance(statement, ast.FunctionDef)}
372
- callableInlinerWorkhorse = RecursiveInliner(dictionaryFunctions)
373
- callableInlined = callableInlinerWorkhorse.inlineFunctionBody(callableTarget)
374
-
375
- if callableInlined:
376
- ast.fix_missing_locations(callableInlined)
377
- parametersNumba = None
378
-
379
- match callableTarget:
380
- case 'countParallel':
381
- parametersNumba = parametersNumbaSuperJitParallel
382
- case 'countSequential':
383
- parametersNumba = parametersNumbaSuperJit
384
- case 'countInitialize':
385
- parametersNumba = parametersNumbaDEFAULT
386
-
387
- callableDecorated = decorateCallableWithNumba(callableInlined, parametersNumba)
388
-
389
- if callableTarget == 'countSequential':
390
- unpackerMy = UnpackArrayAccesses(indexMy, 'my')
391
- callableDecorated = cast(ast.FunctionDef, unpackerMy.visit(callableDecorated))
392
- ast.fix_missing_locations(callableDecorated)
393
-
394
- unpackerTrack = UnpackArrayAccesses(indexTrack, 'track')
395
- callableDecorated = cast(ast.FunctionDef, unpackerTrack.visit(callableDecorated))
396
- ast.fix_missing_locations(callableDecorated)
397
-
398
- moduleAST = ast.Module(body=cast(List[ast.stmt], list(codeSourceImportStatements) + [callableDecorated]), type_ignores=[])
399
- ast.fix_missing_locations(moduleAST)
400
- moduleSource = ast.unparse(moduleAST)
401
- return moduleSource
402
-
403
- def makeDispatcherNumba(codeSource: str, callableTarget: str, listStuffYouOughtaKnow: List[youOughtaKnow]) -> str:
404
-
405
- docstringDispatcherNumba = """What in tarnation is this stupid module and function?
406
-
407
- - This function is not in the same module as `countFolds` so that we can delay Numba just-in-time (jit) compilation of this function and the finalization of its settings until we are ready.
408
- - This function is not in the same module as the next function, which does the hard work, so that we can delay `numba.jit` compilation of the next function.
409
- - This function is "jitted" but the next function is super jitted, which makes it too arrogant to talk to plebian Python functions. It will, however, reluctantly talk to basic jitted functions.
410
- - So this module can talk to the next function, and because this module isn't as arrogant, it will talk to the low-class `countFolds` that called this function. Well, with a few restrictions, of course:
411
- - No `TypedDict`
412
- - The plebs must clean up their own memory problems
413
- - No oversized integers
414
- - No global variables, only global constants
415
- - It won't accept pleb nonlocal variables either
416
- - Python "class": they are all inferior to the jit class
417
- - No `**kwargs`
418
- - and just a few dozen-jillion other things."""
419
-
420
- astSource = ast.parse(codeSource)
421
-
422
- astImports = [node for node in astSource.body if isinstance(node, (ast.Import, ast.ImportFrom))]
423
- FunctionDefTarget = next((node for node in astSource.body if isinstance(node, ast.FunctionDef) and node.name == callableTarget), None)
424
-
425
- if not FunctionDefTarget:
426
- raise ValueError(f"Could not find function {callableTarget} in source code")
427
-
428
- # Zero-out the decorator list
429
- FunctionDefTarget = Z0Z_UnhandledDecorators(FunctionDefTarget)
430
-
431
- # Add Numba decorator
432
- FunctionDefTarget = decorateCallableWithNumba(FunctionDefTarget, parametersNumbaFailEarly)
433
- FunctionDefTarget.body.insert(0, ast.Expr(value=ast.Constant(value=docstringDispatcherNumba)))
434
-
435
- astModule = ast.Module(
436
- body=cast(List[ast.stmt]
437
- , astImports
438
- + [Don_Lapre_The_Road_to_Self_Improvement_For_Programmers_by_Using_Short_Identifiers.astForCompetentProgrammers
439
- for Don_Lapre_The_Road_to_Self_Improvement_For_Programmers_by_Using_Short_Identifiers in listStuffYouOughtaKnow]
440
- + [FunctionDefTarget])
441
- , type_ignores=[]
442
- )
443
-
444
- ast.fix_missing_locations(astModule)
445
- return ast.unparse(astModule)
446
-
447
- def makeNumbaOptimizedFlow(listCallablesInline: List[str], callableDispatcher: Optional[str] = None, algorithmSource: Optional[ModuleType] = None):
448
- if not algorithmSource:
449
- algorithmSource = getAlgorithmSource()
450
-
451
- formatModuleNameDEFAULT = "numba_{callableTarget}"
452
-
453
- # When I am a more competent programmer, I will make getPathFilenameWrite dependent on makeAstImport or vice versa,
454
- # so the name of the physical file doesn't get out of whack with the name of the logical module.
455
- def getPathFilenameWrite(callableTarget: str
456
- , pathWrite: Optional[pathlib.Path] = None
457
- , formatFilenameWrite: Optional[str] = None
458
- ) -> pathlib.Path:
459
- if not pathWrite:
460
- pathWrite = getPathSyntheticModules()
461
- if not formatFilenameWrite:
462
- formatFilenameWrite = formatModuleNameDEFAULT + '.py'
463
-
464
- pathFilename = pathWrite / formatFilenameWrite.format(callableTarget=callableTarget)
465
- return pathFilename
466
-
467
- def makeAstImport(callableTarget: str
468
- , packageName: Optional[str] = None
469
- , subPackageName: Optional[str] = None
470
- , moduleName: Optional[str] = None
471
- , astNodeLogicalPathThingy: Optional[ast.AST] = None
472
- ) -> ast.ImportFrom:
473
- """Creates import AST node for synthetic modules."""
474
- if astNodeLogicalPathThingy is None:
475
- if packageName is None:
476
- packageName = myPackageNameIs
477
- if subPackageName is None:
478
- subPackageName = moduleOfSyntheticModules
479
- if moduleName is None:
480
- moduleName = formatModuleNameDEFAULT.format(callableTarget=callableTarget)
481
- module=f'{packageName}.{subPackageName}.{moduleName}'
482
- else:
483
- module = str(astNodeLogicalPathThingy)
484
- return ast.ImportFrom(
485
- module=module,
486
- names=[ast.alias(name=callableTarget, asname=None)],
487
- level=0
488
- )
489
-
490
- listStuffYouOughtaKnow: List[youOughtaKnow] = []
491
-
492
- for callableTarget in listCallablesInline:
493
- codeSource = inspect.getsource(algorithmSource)
494
- moduleSource = inlineOneCallable(codeSource, callableTarget)
495
- if not moduleSource:
496
- raise Exception("Pylance, OMG! The sky is falling!")
497
-
498
- pathFilename = getPathFilenameWrite(callableTarget)
499
- astImport = makeAstImport(callableTarget)
500
-
501
- listStuffYouOughtaKnow.append(youOughtaKnow(
502
- callableSynthesized=callableTarget,
503
- pathFilenameForMe=pathFilename,
504
- astForCompetentProgrammers=astImport
505
- ))
506
- pathFilename.write_text(moduleSource)
507
-
508
- # Generate dispatcher if requested
509
- if callableDispatcher:
510
- codeSource = inspect.getsource(algorithmSource)
511
- moduleSource = makeDispatcherNumba(codeSource, callableDispatcher, listStuffYouOughtaKnow)
512
- if not moduleSource:
513
- raise Exception("Pylance, OMG! The sky is falling!")
514
-
515
- pathFilename = getPathFilenameWrite(callableDispatcher)
516
- astImport = makeAstImport(callableDispatcher)
517
-
518
- listStuffYouOughtaKnow.append(youOughtaKnow(
519
- callableSynthesized=callableDispatcher,
520
- pathFilenameForMe=pathFilename,
521
- astForCompetentProgrammers=astImport
522
- ))
523
- pathFilename.write_text(moduleSource)
524
-
525
- if __name__ == '__main__':
526
- setDatatypeModule('numpy', sourGrapes=True)
527
- setDatatypeFoldsTotal('int64', sourGrapes=True)
528
- setDatatypeElephino('uint8', sourGrapes=True)
529
- setDatatypeLeavesTotal('uint8', sourGrapes=True)
530
- listCallablesInline: List[str] = ['countInitialize', 'countParallel', 'countSequential']
531
- callableDispatcher = 'doTheNeedful'
532
- makeNumbaOptimizedFlow(listCallablesInline, callableDispatcher)
533
- # makeNumbaOptimizedFlow(listCallablesInline)