mapFolding 0.12.2__py3-none-any.whl → 0.12.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.
@@ -29,36 +29,37 @@ essential progress feedback capabilities for large-scale computational research.
29
29
  """
30
30
 
31
31
  from astToolkit import (
32
- Be, ClassIsAndAttribute, extractFunctionDef, identifierDotAttribute, IngredientsFunction,
33
- IngredientsModule, LedgerOfImports, Make, NodeChanger, NodeTourist, Then,
34
- )
32
+ Be, extractFunctionDef, identifierDotAttribute, IngredientsFunction, IngredientsModule, LedgerOfImports, Make,
33
+ NodeChanger, NodeTourist, Then)
35
34
  from astToolkit.transformationTools import write_astModule
35
+ from hunterMakesPy import autoDecodingRLE, raiseIfNone
36
36
  from mapFolding import getPathFilenameFoldsTotal, MapFoldingState, packageSettings
37
37
  from mapFolding.someAssemblyRequired import IfThis
38
38
  from mapFolding.someAssemblyRequired.RecipeJob import RecipeJobTheorem2Numba
39
- from mapFolding.someAssemblyRequired.toolkitNumba import (
40
- decorateCallableWithNumba, parametersNumbaLight, SpicesJobNumba,
41
- )
39
+ from mapFolding.someAssemblyRequired.toolkitNumba import decorateCallableWithNumba, parametersNumbaLight, SpicesJobNumba
42
40
  from mapFolding.syntheticModules.initializeCount import initializeGroupsOfFolds
43
41
  from pathlib import PurePosixPath
44
- from typing import cast, NamedTuple
45
- from Z0Z_tools import autoDecodingRLE, raiseIfNone
42
+ from typing import cast, NamedTuple, TYPE_CHECKING
43
+ from typing_extensions import TypeIs
46
44
  import ast
47
45
 
46
+ if TYPE_CHECKING:
47
+ from collections.abc import Callable
48
+
48
49
  # Configuration lists for code optimization and dead code elimination
49
- listIdentifiersNotUsedAllHARDCODED: list[str] = ['concurrencyLimit', 'foldsTotal', 'mapShape',]
50
+ listIdentifiersNotUsedAllHARDCODED: list[str] = ['concurrencyLimit', 'foldsTotal', 'mapShape']
50
51
  """Identifiers that are universally unused across all optimization contexts."""
51
52
 
52
53
  listIdentifiersNotUsedParallelSequentialHARDCODED: list[str] = ['indexLeaf']
53
54
  """Identifiers unused in both parallel and sequential execution modes."""
54
55
 
55
- listIdentifiersNotUsedSequentialHARDCODED: list[str] = ['foldGroups', 'taskDivisions', 'taskIndex',]
56
+ listIdentifiersNotUsedSequentialHARDCODED: list[str] = ['foldGroups', 'taskDivisions', 'taskIndex']
56
57
  """Identifiers unused specifically in sequential execution mode."""
57
58
 
58
- listIdentifiersReplacedHARDCODED: list[str] = ['groupsOfFolds',]
59
+ listIdentifiersReplacedHARDCODED: list[str] = ['groupsOfFolds']
59
60
  """Identifiers that get replaced with optimized equivalents during transformation."""
60
61
 
61
- listIdentifiersStaticValuesHARDCODED: list[str] = ['dimensionsTotal', 'leavesTotal',]
62
+ listIdentifiersStaticValuesHARDCODED: list[str] = ['dimensionsTotal', 'leavesTotal']
62
63
  """Identifiers with compile-time constant values that can be embedded directly."""
63
64
 
64
65
  listIdentifiersNotUsedHARDCODED: list[str] = listIdentifiersStaticValuesHARDCODED + listIdentifiersReplacedHARDCODED + listIdentifiersNotUsedAllHARDCODED + listIdentifiersNotUsedParallelSequentialHARDCODED + listIdentifiersNotUsedSequentialHARDCODED
@@ -67,6 +68,8 @@ listIdentifiersNotUsedHARDCODED: list[str] = listIdentifiersStaticValuesHARDCODE
67
68
  def addLauncherNumbaProgress(ingredientsModule: IngredientsModule, ingredientsFunction: IngredientsFunction, job: RecipeJobTheorem2Numba, spices: SpicesJobNumba) -> tuple[IngredientsModule, IngredientsFunction]:
68
69
  """Add progress tracking capabilities to a Numba-optimized function.
69
70
 
71
+ (AI generated docstring)
72
+
70
73
  This function modifies both the module and the function to integrate Numba-compatible
71
74
  progress tracking for long-running calculations. It performs several key transformations:
72
75
 
@@ -79,16 +82,23 @@ def addLauncherNumbaProgress(ingredientsModule: IngredientsModule, ingredientsFu
79
82
  which can take hours or days to complete, providing visual feedback and
80
83
  estimated completion times.
81
84
 
82
- Parameters:
83
- ingredientsModule: The module where the function is defined.
84
- ingredientsFunction: The function to modify with progress tracking.
85
- job: Configuration specifying shape details and output paths.
86
- spices: Configuration specifying progress bar details.
87
-
88
- Returns:
85
+ Parameters
86
+ ----------
87
+ ingredientsModule : IngredientsModule
88
+ The module where the function is defined.
89
+ ingredientsFunction : IngredientsFunction
90
+ The function to modify with progress tracking.
91
+ job : RecipeJobTheorem2Numba
92
+ Configuration specifying shape details and output paths.
93
+ spices : SpicesJobNumba
94
+ Configuration specifying progress bar details.
95
+
96
+ Returns
97
+ -------
98
+ moduleAndFunction : tuple[IngredientsModule, IngredientsFunction]
89
99
  Modified module and function with integrated progress tracking capabilities.
90
- """
91
100
 
101
+ """
92
102
  linesLaunch: str = f"""
93
103
  if __name__ == '__main__':
94
104
  with ProgressBar(total={job.foldsTotalEstimated}, update_interval=2) as statusUpdate:
@@ -107,9 +117,9 @@ if __name__ == '__main__':
107
117
  ast_argNumbaProgress = ast.arg(arg=spices.numbaProgressBarIdentifier, annotation=ast.Name(id=numba_progressPythonClass, ctx=ast.Load()))
108
118
  ingredientsFunction.astFunctionDef.args.args.append(ast_argNumbaProgress)
109
119
 
110
- findThis = ClassIsAndAttribute.targetIs(ast.AugAssign, IfThis.isNameIdentifier(job.shatteredDataclass.countingVariableName.id))
111
- doThat = Then.replaceWith(Make.Expr(Make.Call(Make.Attribute(Make.Name(spices.numbaProgressBarIdentifier),'update'),[Make.Constant(1)])))
112
- countWithProgressBar = NodeChanger(findThis, doThat)
120
+ findThis: Callable[[ast.AST], TypeIs[ast.AugAssign] | bool] = Be.AugAssign.targetIs(IfThis.isNameIdentifier(job.shatteredDataclass.countingVariableName.id))
121
+ doThat: Callable[[ast.AugAssign], ast.Expr] = Then.replaceWith(Make.Expr(Make.Call(Make.Attribute(Make.Name(spices.numbaProgressBarIdentifier),'update'),[Make.Constant(1)])))
122
+ countWithProgressBar: NodeChanger[ast.AugAssign, ast.Expr] = NodeChanger(findThis, doThat)
113
123
  countWithProgressBar.visit(ingredientsFunction.astFunctionDef)
114
124
 
115
125
  removeReturnStatement = NodeChanger(Be.Return, Then.removeIt)
@@ -123,6 +133,8 @@ if __name__ == '__main__':
123
133
  def move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsFunction: IngredientsFunction, job: RecipeJobTheorem2Numba) -> IngredientsFunction:
124
134
  """Convert function parameters into initialized variables with concrete values.
125
135
 
136
+ (AI generated docstring)
137
+
126
138
  This function implements a critical transformation that converts function parameters
127
139
  into statically initialized variables in the function body. This enables several
128
140
  optimizations:
@@ -136,12 +148,18 @@ def move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsFunction: Ingre
136
148
  replacing abstract parameter references with concrete values from the computation state.
137
149
  It also removes unused parameters and variables to eliminate dead code.
138
150
 
139
- Parameters:
140
- ingredientsFunction: The function to transform.
141
- job: Recipe containing concrete values for parameters and field metadata.
151
+ Parameters
152
+ ----------
153
+ ingredientsFunction : IngredientsFunction
154
+ The function to transform.
155
+ job : RecipeJobTheorem2Numba
156
+ Recipe containing concrete values for parameters and field metadata.
142
157
 
143
- Returns:
158
+ Returns
159
+ -------
160
+ modifiedFunction : IngredientsFunction
144
161
  The modified function with parameters converted to initialized variables.
162
+
145
163
  """
146
164
  ingredientsFunction.imports.update(job.shatteredDataclass.imports)
147
165
 
@@ -160,24 +178,24 @@ def move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsFunction: Ingre
160
178
  ImaAnnAssign, elementConstructor = job.shatteredDataclass.Z0Z_field2AnnAssign[ast_arg.arg]
161
179
  match elementConstructor:
162
180
  case 'scalar':
163
- cast(ast.Constant, cast(ast.Call, ImaAnnAssign.value).args[0]).value = int(job.state.__dict__[ast_arg.arg])
181
+ cast('ast.Constant', cast('ast.Call', ImaAnnAssign.value).args[0]).value = int(job.state.__dict__[ast_arg.arg])
164
182
  case 'array':
165
- dataAsStrRLE: str = autoDecodingRLE(job.state.__dict__[ast_arg.arg], True)
166
- dataAs_astExpr: ast.expr = cast(ast.Expr, ast.parse(dataAsStrRLE).body[0]).value
167
- cast(ast.Call, ImaAnnAssign.value).args = [dataAs_astExpr]
183
+ dataAsStrRLE: str = autoDecodingRLE(job.state.__dict__[ast_arg.arg], assumeAddSpaces=True)
184
+ dataAs_astExpr: ast.expr = cast('ast.Expr', ast.parse(dataAsStrRLE).body[0]).value
185
+ cast('ast.Call', ImaAnnAssign.value).args = [dataAs_astExpr]
168
186
  case _:
169
187
  list_exprDOTannotation: list[ast.expr] = []
170
188
  list_exprDOTvalue: list[ast.expr] = []
171
189
  for dimension in job.state.mapShape:
172
190
  list_exprDOTannotation.append(Make.Name(elementConstructor))
173
191
  list_exprDOTvalue.append(Make.Call(Make.Name(elementConstructor), [Make.Constant(dimension)]))
174
- cast(ast.Tuple, cast(ast.Subscript, cast(ast.AnnAssign, ImaAnnAssign).annotation).slice).elts = list_exprDOTannotation
175
- cast(ast.Tuple, ImaAnnAssign.value).elts = list_exprDOTvalue
192
+ cast('ast.Tuple', cast('ast.Subscript', cast('ast.AnnAssign', ImaAnnAssign).annotation).slice).elts = list_exprDOTannotation
193
+ cast('ast.Tuple', ImaAnnAssign.value).elts = list_exprDOTvalue
176
194
 
177
195
  ingredientsFunction.astFunctionDef.body.insert(0, ImaAnnAssign)
178
196
 
179
- findThis = IfThis.is_argIdentifier(ast_arg.arg)
180
- remove_arg = NodeChanger(findThis, Then.removeIt)
197
+ findThis: Callable[[ast.AST], TypeIs[ast.arg] | bool] = IfThis.is_argIdentifier(ast_arg.arg)
198
+ remove_arg: NodeChanger[ast.arg, None] = NodeChanger(findThis, Then.removeIt)
181
199
  remove_arg.visit(ingredientsFunction.astFunctionDef)
182
200
 
183
201
  ast.fix_missing_locations(ingredientsFunction.astFunctionDef)
@@ -186,6 +204,8 @@ def move_arg2FunctionDefDOTbodyAndAssignInitialValues(ingredientsFunction: Ingre
186
204
  def makeJobNumba(job: RecipeJobTheorem2Numba, spices: SpicesJobNumba) -> None:
187
205
  """Generate an optimized Numba-compiled computation module for map folding calculations.
188
206
 
207
+ (AI generated docstring)
208
+
189
209
  This function orchestrates the complete code transformation pipeline to convert
190
210
  a generic map folding algorithm into a highly optimized, specialized computation
191
211
  module. The transformation process includes:
@@ -203,26 +223,25 @@ def makeJobNumba(job: RecipeJobTheorem2Numba, spices: SpicesJobNumba) -> None:
203
223
  map folding calculations for the specific map dimensions with maximum
204
224
  performance through just-in-time compilation.
205
225
 
206
- Parameters:
207
- job: Configuration recipe containing source locations, target paths, and state.
208
- spices: Optimization settings including Numba parameters and progress options.
209
- """
226
+ Parameters
227
+ ----------
228
+ job : RecipeJobTheorem2Numba
229
+ Configuration recipe containing source locations, target paths, and state.
230
+ spices : SpicesJobNumba
231
+ Optimization settings including Numba parameters and progress options.
210
232
 
233
+ """
211
234
  astFunctionDef: ast.FunctionDef = raiseIfNone(extractFunctionDef(job.source_astModule, job.countCallable))
212
235
  ingredientsCount: IngredientsFunction = IngredientsFunction(astFunctionDef, LedgerOfImports())
213
236
 
214
237
  # Remove `foldGroups` and any other unused statements, so you can dynamically determine which variables are not used
215
- findThis = ClassIsAndAttribute.targetsIs(ast.Assign, lambda list_expr: any([IfThis.isSubscriptIdentifier('foldGroups')(node) for node in list_expr ]))
216
- # findThis = IfThis.isAssignAndTargets0Is(IfThis.isSubscriptIdentifier('foldGroups'))
217
- doThat = Then.removeIt
218
- remove_foldGroups = NodeChanger(findThis, doThat)
219
- # remove_foldGroups.visit(ingredientsCount.astFunctionDef)
238
+ # NodeChanger[ast.Name, None](Be.Assign.targetsIs(lambda list_expr: any(IfThis.isSubscriptIdentifier('foldGroups')(node) for node in list_expr)) , Then.removeIt).visit(ingredientsCount.astFunctionDef) # noqa: ERA001
220
239
 
221
240
  # replace identifiers with static values with their values, so you can dynamically determine which variables are not used
222
241
  listIdentifiersStaticValues: list[str] = listIdentifiersStaticValuesHARDCODED
223
242
  for identifier in listIdentifiersStaticValues:
224
- findThis = IfThis.isNameIdentifier(identifier)
225
- doThat = Then.replaceWith(Make.Constant(int(job.state.__dict__[identifier])))
243
+ findThis: Callable[[ast.AST], TypeIs[ast.Name] | bool] = IfThis.isNameIdentifier(identifier)
244
+ doThat: Callable[[ast.Name], ast.Constant] = Then.replaceWith(Make.Constant(int(job.state.__dict__[identifier])))
226
245
  NodeChanger(findThis, doThat).visit(ingredientsCount.astFunctionDef)
227
246
 
228
247
  ingredientsModule = IngredientsModule()
@@ -242,8 +261,8 @@ if __name__ == '__main__':
242
261
  writeStream.write(str(foldsTotal))
243
262
  writeStream.close()
244
263
  """
245
- # from mapFolding.oeis import getFoldsTotalKnown
246
- # print(foldsTotal == getFoldsTotalKnown({job.state.mapShape}))
264
+ # from mapFolding.oeis import getFoldsTotalKnown # noqa: ERA001
265
+ # print(foldsTotal == getFoldsTotalKnown({job.state.mapShape})) # noqa: ERA001
247
266
  ingredientsModule.appendLauncher(ast.parse(linesLaunch))
248
267
  changeReturnParallelCallable = NodeChanger(Be.Return, Then.replaceWith(Make.Return(job.shatteredDataclass.countingVariableName)))
249
268
  changeReturnParallelCallable.visit(ingredientsCount.astFunctionDef)
@@ -258,12 +277,18 @@ if __name__ == '__main__':
258
277
  generation. Each configuration specifies the source module, target type name,
259
278
  and optional import alias for the transformation.
260
279
 
261
- Attributes:
262
- fml: Framework datatype identifier to be replaced.
263
- Z0Z_module: Module containing the target datatype (e.g., 'numba', 'numpy').
264
- Z0Z_type_name: Concrete type name in the target module.
265
- Z0Z_asname: Optional import alias for the type.
280
+ Attributes
281
+ ----------
282
+ fml : str
283
+ Framework datatype identifier to be replaced.
284
+ Z0Z_module : identifierDotAttribute
285
+ Module containing the target datatype (e.g., 'numba', 'numpy').
286
+ Z0Z_type_name : str
287
+ Concrete type name in the target module.
288
+ Z0Z_asname : str | None = None
289
+ Optional import alias for the type.
266
290
  """
291
+
267
292
  fml: str
268
293
  Z0Z_module: identifierDotAttribute
269
294
  Z0Z_type_name: str
@@ -296,7 +321,6 @@ if __name__ == '__main__':
296
321
  ingredientsCount.imports.addImportFrom_asStr(typeConfig.Z0Z_module, typeConfig.Z0Z_type_name, typeConfig.Z0Z_asname)
297
322
 
298
323
  ingredientsCount.astFunctionDef.decorator_list = [] # TODO low-priority, handle this more elegantly
299
- # TODO when I add the function signature in numba style back to the decorator, the logic needs to handle `ProgressBarType:`
300
324
  ingredientsCount = decorateCallableWithNumba(ingredientsCount, spices.parametersNumba)
301
325
  ingredientsModule.appendIngredientsFunction(ingredientsCount)
302
326
  write_astModule(ingredientsModule, job.pathFilenameModule, job.packageIdentifier)
@@ -326,12 +350,12 @@ if __name__ == '__main__':
326
350
  mapShape = (2,4)
327
351
  state = MapFoldingState(mapShape)
328
352
  state = initializeGroupsOfFolds(state)
329
- # foldsTotalEstimated = getFoldsTotalKnown(state.mapShape) // state.leavesTotal
330
- # foldsTotalEstimated = dictionaryEstimates[state.mapShape] // state.leavesTotal
353
+ # foldsTotalEstimated = getFoldsTotalKnown(state.mapShape) // state.leavesTotal # noqa: ERA001
354
+ # foldsTotalEstimated = dictionaryEstimates[state.mapShape] // state.leavesTotal # noqa: ERA001
331
355
  foldsTotalEstimated = 0
332
356
  pathModule = PurePosixPath(packageSettings.pathPackage, 'jobs')
333
357
  pathFilenameFoldsTotal = PurePosixPath(getPathFilenameFoldsTotal(state.mapShape, pathModule))
334
358
  aJob = RecipeJobTheorem2Numba(state, foldsTotalEstimated, pathModule=pathModule, pathFilenameFoldsTotal=pathFilenameFoldsTotal)
335
359
  spices = SpicesJobNumba(useNumbaProgressBar=False, parametersNumba=parametersNumbaLight)
336
- # spices = SpicesJobNumba()
360
+ # spices = SpicesJobNumba() # noqa: ERA001
337
361
  makeJobNumba(aJob, spices)
@@ -26,13 +26,14 @@ system to produce standalone modules optimized for specific map dimensions and c
26
26
  """
27
27
 
28
28
  from astToolkit import identifierDotAttribute, IngredientsFunction, Make
29
- from collections.abc import Callable, Sequence
30
- from numba.core.compiler import CompilerBase as numbaCompilerBase
31
- from typing import Any, cast, Final, NotRequired, TypedDict
29
+ from typing import cast, Final, NotRequired, TYPE_CHECKING, TypedDict
32
30
  import ast
33
31
  import dataclasses
34
32
  import warnings
35
33
 
34
+ if TYPE_CHECKING:
35
+ from collections.abc import Sequence
36
+
36
37
  class ParametersNumba(TypedDict):
37
38
  """
38
39
  Configuration parameters for Numba compilation decorators.
@@ -56,6 +57,7 @@ class ParametersNumba(TypedDict):
56
57
  optional via `NotRequired`, allowing flexible configuration while requiring explicit
57
58
  decisions on critical performance and correctness parameters.
58
59
  """
60
+
59
61
  _dbg_extend_lifetimes: NotRequired[bool]
60
62
  _dbg_optnone: NotRequired[bool]
61
63
  _nrt: NotRequired[bool]
@@ -67,7 +69,7 @@ class ParametersNumba(TypedDict):
67
69
  forceinline: NotRequired[bool]
68
70
  forceobj: NotRequired[bool]
69
71
  inline: NotRequired[str]
70
- locals: NotRequired[dict[str, Any]]
72
+ # locals: NotRequired[dict[str, Any]]
71
73
  looplift: NotRequired[bool]
72
74
  no_cfunc_wrapper: NotRequired[bool]
73
75
  no_cpython_wrapper: NotRequired[bool]
@@ -75,11 +77,11 @@ class ParametersNumba(TypedDict):
75
77
  nogil: NotRequired[bool]
76
78
  nopython: NotRequired[bool]
77
79
  parallel: NotRequired[bool]
78
- pipeline_class: NotRequired[type[numbaCompilerBase]]
79
- signature_or_function: NotRequired[Any | Callable[..., Any] | str | tuple[Any, ...]]
80
+ # pipeline_class: NotRequired[type[numbaCompilerBase]]
81
+ # signature_or_function: NotRequired[Any | Callable[..., Any] | str | tuple[Any, ...]]
80
82
  target: NotRequired[str]
81
83
 
82
- parametersNumbaDefault: Final[ParametersNumba] = { '_nrt': True, 'boundscheck': False, 'cache': True, 'error_model': 'numpy', 'fastmath': True, 'forceinline': True, 'inline': 'always', 'looplift': False, 'no_cfunc_wrapper': False, 'no_cpython_wrapper': False, 'nopython': True, 'parallel': False, }
84
+ parametersNumbaDefault: Final[ParametersNumba] = { '_nrt': True, 'boundscheck': False, 'cache': True, 'error_model': 'numpy', 'fastmath': True, 'forceinline': True, 'inline': 'always', 'looplift': False, 'no_cfunc_wrapper': False, 'no_cpython_wrapper': False, 'nopython': True, 'parallel': False }
83
85
  """
84
86
  Comprehensive Numba configuration for maximum performance optimization.
85
87
 
@@ -132,54 +134,69 @@ While Numba offers multiple decorators (`@jit`, `@njit`, `@vectorize`), this too
132
134
  on the general-purpose `@jit` decorator with configurable parameters for flexibility.
133
135
  """
134
136
 
135
- def decorateCallableWithNumba(ingredientsFunction: IngredientsFunction, parametersNumba: ParametersNumba | None = None) -> IngredientsFunction:
136
- """
137
- Transform a Python function into a Numba-accelerated version with appropriate decorators.
137
+ def decorateCallableWithNumba(ingredientsFunction: IngredientsFunction, parametersNumba: ParametersNumba | None = None) -> IngredientsFunction: # noqa: C901
138
+ """Transform a Python function into a Numba-accelerated version with appropriate decorators.
138
139
 
139
- This function applies Numba's @jit decorator to an existing function definition within
140
- an IngredientsFunction container. It handles the complete transformation pipeline:
140
+ (AI generated docstring)
141
141
 
142
- 1. Removes any existing decorators that might conflict with Numba
143
- 2. Constructs type signatures for Numba compilation when possible
144
- 3. Applies the @jit decorator with specified or default parameters
145
- 4. Updates import requirements to include necessary Numba modules
142
+ This function applies Numba's `@jit` decorator to an existing function definition within
143
+ an `IngredientsFunction` container. It handles the complete transformation pipeline
144
+ including removing any existing decorators that might conflict with Numba, constructing
145
+ type signatures for Numba compilation when possible, applying the `@jit` decorator with
146
+ specified or default parameters, and updating import requirements to include necessary
147
+ Numba modules.
146
148
 
147
149
  The transformation preserves function semantics while enabling significant performance
148
150
  improvements through just-in-time compilation. Type inference is attempted for
149
151
  function parameters and return values to enable optimized compilation paths.
150
- Parameters:
151
- ingredientsFunction: Container holding the function definition and associated metadata
152
- parametersNumba: Optional Numba configuration; uses parametersNumbaDefault if None
153
- Returns:
154
- Modified IngredientsFunction with Numba decorator applied and imports updated
152
+
153
+ Parameters
154
+ ----------
155
+ ingredientsFunction : IngredientsFunction
156
+ Container holding the function definition and associated metadata.
157
+ parametersNumba : ParametersNumba | None = None
158
+ Optional Numba configuration; uses `parametersNumbaDefault` if `None`.
159
+
160
+ Returns
161
+ -------
162
+ ingredientsFunction : IngredientsFunction
163
+ Modified `IngredientsFunction` with Numba decorator applied and imports updated.
164
+
155
165
  """
156
166
  def Z0Z_UnhandledDecorators(astCallable: ast.FunctionDef) -> ast.FunctionDef:
157
- """
158
- Remove existing decorators from function definition to prevent conflicts with Numba.
167
+ """Remove existing decorators from function definition to prevent conflicts with Numba.
168
+
169
+ (AI generated docstring)
159
170
 
160
171
  Numba compilation can be incompatible with certain Python decorators, so this
161
172
  function strips all existing decorators from a function definition before
162
- applying the Numba @jit decorator. Removed decorators are logged as warnings
173
+ applying the Numba `@jit` decorator. Removed decorators are logged as warnings
163
174
  for debugging purposes.
164
175
 
165
176
  TODO: Implement more sophisticated decorator handling that can preserve
166
177
  compatible decorators and intelligently handle decorator composition.
167
178
 
168
- Parameters:
169
- astCallable: Function definition AST node to process
179
+ Parameters
180
+ ----------
181
+ astCallable : ast.FunctionDef
182
+ Function definition AST node to process.
183
+
184
+ Returns
185
+ -------
186
+ astCallable : ast.FunctionDef
187
+ Function definition with decorator list cleared.
170
188
 
171
- Returns:
172
- astCallable: Function definition with decorator list cleared
173
189
  """
174
- # TODO: more explicit handling of decorators. I'm able to ignore this because I know `algorithmSource` doesn't have any decorators.
190
+ # TODO more explicit handling of decorators. I'm able to ignore this because I know `algorithmSource` doesn't have any decorators.
175
191
  for decoratorItem in astCallable.decorator_list.copy():
176
192
  astCallable.decorator_list.remove(decoratorItem)
177
- warnings.warn(f"Removed decorator {ast.unparse(decoratorItem)} from {astCallable.name}")
193
+ warnings.warn(f"Removed decorator {ast.unparse(decoratorItem)} from {astCallable.name}", stacklevel=2)
178
194
  return astCallable
179
195
 
180
196
  def makeSpecialSignatureForNumba(signatureElement: ast.arg) -> ast.Subscript | ast.Name | None: # pyright: ignore[reportUnusedFunction]
181
- """
182
- Generate Numba-compatible type signatures for function parameters.
197
+ """Generate Numba-compatible type signatures for function parameters.
198
+
199
+ (AI generated docstring)
183
200
 
184
201
  This function analyzes function parameter type annotations and converts them into
185
202
  Numba-compatible type signature expressions. It handles various annotation patterns
@@ -189,20 +206,25 @@ def decorateCallableWithNumba(ingredientsFunction: IngredientsFunction, paramete
189
206
  The generated signatures enable Numba to perform more efficient compilation by
190
207
  providing explicit type information rather than relying solely on type inference.
191
208
 
192
- Parameters:
193
- signatureElement: Function parameter with type annotation to convert
209
+ Parameters
210
+ ----------
211
+ signatureElement : ast.arg
212
+ Function parameter with type annotation to convert.
213
+
214
+ Returns
215
+ -------
216
+ ast.Subscript | ast.Name | None
217
+ Numba-compatible type signature AST node, or None if conversion not possible.
194
218
 
195
- Returns:
196
- Numba-compatible type signature AST node, or None if conversion not possible
197
219
  """
198
220
  if isinstance(signatureElement.annotation, ast.Subscript) and isinstance(signatureElement.annotation.slice, ast.Tuple):
199
221
  annotationShape: ast.expr = signatureElement.annotation.slice.elts[0]
200
222
  if isinstance(annotationShape, ast.Subscript) and isinstance(annotationShape.slice, ast.Tuple):
201
223
  shapeAsListSlices: list[ast.Slice] = [ast.Slice() for _axis in range(len(annotationShape.slice.elts))]
202
- shapeAsListSlices[-1] = ast.Slice(step=ast.Constant(value=1))
203
- shapeAST: ast.Slice | ast.Tuple = ast.Tuple(elts=list(shapeAsListSlices), ctx=ast.Load())
224
+ shapeAsListSlices[-1] = Make.Slice(step=Make.Constant(1))
225
+ shapeAST: ast.Slice | ast.Tuple = Make.Tuple(list(shapeAsListSlices))
204
226
  else:
205
- shapeAST = ast.Slice(step=ast.Constant(value=1))
227
+ shapeAST = Make.Slice(step=Make.Constant(1))
206
228
 
207
229
  annotationDtype: ast.expr = signatureElement.annotation.slice.elts[1]
208
230
  if (isinstance(annotationDtype, ast.Subscript) and isinstance(annotationDtype.slice, ast.Attribute)):
@@ -214,9 +236,9 @@ def decorateCallableWithNumba(ingredientsFunction: IngredientsFunction, paramete
214
236
  Z0Z_hacky_dtype: str = ndarrayName
215
237
  datatype_attr = datatypeAST or Z0Z_hacky_dtype
216
238
  ingredientsFunction.imports.addImportFrom_asStr(datatypeModuleDecorator, datatype_attr)
217
- datatypeNumba = ast.Name(id=datatype_attr, ctx=ast.Load())
239
+ datatypeNumba = Make.Name(datatype_attr)
218
240
 
219
- return ast.Subscript(value=datatypeNumba, slice=shapeAST, ctx=ast.Load())
241
+ return Make.Subscript(datatypeNumba, slice=shapeAST)
220
242
 
221
243
  elif isinstance(signatureElement.annotation, ast.Name):
222
244
  return signatureElement.annotation
@@ -235,14 +257,15 @@ def decorateCallableWithNumba(ingredientsFunction: IngredientsFunction, paramete
235
257
 
236
258
  if ingredientsFunction.astFunctionDef.returns and isinstance(ingredientsFunction.astFunctionDef.returns, ast.Name):
237
259
  theReturn: ast.Name = ingredientsFunction.astFunctionDef.returns
238
- list_argsDecorator = [cast(ast.expr, ast.Call(func=ast.Name(id=theReturn.id, ctx=ast.Load())
239
- , args=list_arg4signature_or_function if list_arg4signature_or_function else [], keywords=[] ) )]
260
+ list_argsDecorator = [cast("ast.expr", Make.Call(Make.Name(theReturn.id)
261
+ , list_arg4signature_or_function if list_arg4signature_or_function else [], [] ) )]
240
262
  elif list_arg4signature_or_function:
241
- list_argsDecorator = [cast(ast.expr, ast.Tuple(elts=list_arg4signature_or_function, ctx=ast.Load()))]
263
+ list_argsDecorator = [cast("ast.expr", Make.Tuple(list_arg4signature_or_function))]
242
264
 
243
265
  ingredientsFunction.astFunctionDef = Z0Z_UnhandledDecorators(ingredientsFunction.astFunctionDef)
244
266
  if parametersNumba is None:
245
267
  parametersNumba = parametersNumbaDefault
268
+
246
269
  listDecoratorKeywords: list[ast.keyword] = [Make.keyword(parameterName, Make.Constant(parameterValue)) for parameterName, parameterValue in parametersNumba.items()] # pyright: ignore[reportArgumentType]
247
270
 
248
271
  decoratorModule = Z0Z_numbaDataTypeModule
@@ -257,8 +280,9 @@ def decorateCallableWithNumba(ingredientsFunction: IngredientsFunction, paramete
257
280
 
258
281
  @dataclasses.dataclass
259
282
  class SpicesJobNumba:
260
- """
261
- Configuration container for Numba-specific job processing options.
283
+ """Configuration container for Numba-specific job processing options.
284
+
285
+ (AI generated docstring)
262
286
 
263
287
  This dataclass encapsulates configuration settings that control how Numba
264
288
  compilation and execution is applied to job processing functions. It provides
@@ -269,11 +293,17 @@ class SpicesJobNumba:
269
293
  Numba's specialized requirements, enabling consistent application of
270
294
  optimization settings across different computational contexts.
271
295
 
272
- Attributes:
273
- useNumbaProgressBar: Enable progress bar display for long-running computations
274
- numbaProgressBarIdentifier: Progress bar implementation identifier
275
- parametersNumba: Numba compilation parameters with sensible defaults
296
+ Attributes
297
+ ----------
298
+ useNumbaProgressBar : bool
299
+ Enable progress bar display for long-running computations.
300
+ numbaProgressBarIdentifier : str
301
+ Progress bar implementation identifier.
302
+ parametersNumba : ParametersNumba
303
+ Numba compilation parameters with sensible defaults.
304
+
276
305
  """
306
+
277
307
  useNumbaProgressBar: bool = True
278
308
  """Enable progress bar display for Numba-compiled functions with long execution times."""
279
309