mapFolding 0.7.0__py3-none-any.whl → 0.8.0__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.
Files changed (39) hide show
  1. mapFolding/__init__.py +1 -1
  2. mapFolding/basecamp.py +2 -2
  3. mapFolding/beDRY.py +88 -85
  4. mapFolding/filesystem.py +37 -29
  5. mapFolding/noHomeYet.py +2 -2
  6. mapFolding/oeis.py +2 -2
  7. mapFolding/someAssemblyRequired/Z0Z_workbench.py +347 -31
  8. mapFolding/someAssemblyRequired/__init__.py +4 -3
  9. mapFolding/someAssemblyRequired/getLLVMforNoReason.py +0 -1
  10. mapFolding/someAssemblyRequired/ingredientsNumba.py +87 -2
  11. mapFolding/someAssemblyRequired/synthesizeDataConverters.py +34 -52
  12. mapFolding/someAssemblyRequired/{synthesizeNumbaJob.py → synthesizeNumbaJobVESTIGIAL.py} +18 -21
  13. mapFolding/someAssemblyRequired/transformationTools.py +547 -209
  14. mapFolding/syntheticModules/numbaCount_doTheNeedful.py +197 -12
  15. mapFolding/theDao.py +57 -39
  16. mapFolding/theSSOT.py +59 -59
  17. {mapfolding-0.7.0.dist-info → mapfolding-0.8.0.dist-info}/METADATA +6 -7
  18. mapfolding-0.8.0.dist-info/RECORD +41 -0
  19. {mapfolding-0.7.0.dist-info → mapfolding-0.8.0.dist-info}/WHEEL +1 -1
  20. tests/conftest.py +2 -3
  21. tests/test_computations.py +9 -5
  22. tests/test_filesystem.py +0 -2
  23. tests/test_other.py +2 -3
  24. tests/test_tasks.py +7 -5
  25. mapFolding/someAssemblyRequired/synthesizeCountingFunctions.py +0 -7
  26. mapFolding/someAssemblyRequired/synthesizeNumba.py +0 -91
  27. mapFolding/someAssemblyRequired/synthesizeNumbaModules.py +0 -91
  28. mapFolding/someAssemblyRequired/whatWillBe.py +0 -311
  29. mapFolding/syntheticModules/__init__.py +0 -0
  30. mapFolding/syntheticModules/dataNamespaceFlattened.py +0 -30
  31. mapFolding/syntheticModules/numbaCount.py +0 -90
  32. mapFolding/syntheticModules/numbaCountSequential.py +0 -110
  33. mapFolding/syntheticModules/numba_doTheNeedful.py +0 -12
  34. mapfolding-0.7.0.dist-info/RECORD +0 -50
  35. /mapFolding/syntheticModules/{numbaCountExample.py → numbaCountHistoricalExample.py} +0 -0
  36. /mapFolding/syntheticModules/{numba_doTheNeedfulExample.py → numba_doTheNeedfulHistoricalExample.py} +0 -0
  37. {mapfolding-0.7.0.dist-info → mapfolding-0.8.0.dist-info}/LICENSE +0 -0
  38. {mapfolding-0.7.0.dist-info → mapfolding-0.8.0.dist-info}/entry_points.txt +0 -0
  39. {mapfolding-0.7.0.dist-info → mapfolding-0.8.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,41 @@
1
+ mapFolding/__init__.py,sha256=hONqdWnBN1ebgrKZuMIZfI8m-1krSR66L4GTVRwBmw4,203
2
+ mapFolding/basecamp.py,sha256=Ik_oH-MpH8f6k-yBzwm99lfkv3pMDgFFEnSSDyiJjsQ,3861
3
+ mapFolding/beDRY.py,sha256=nn0AEGzrroM3wp91Fts7mmx1VQgG14s0EZsXR-Uy5x8,9049
4
+ mapFolding/filesystem.py,sha256=KqgsO-jaSWAlYib_9ovoXQY76PcQri09_73u0OqMWC8,4094
5
+ mapFolding/noHomeYet.py,sha256=DAppmTJG95Ip1qF1uVLU_vXGz4Lmonp8OYfGXtmOnTE,785
6
+ mapFolding/oeis.py,sha256=ZNt3UBklmpfjdmgbA7pO-ezz2prafr2JvdkpIDapi1w,11853
7
+ mapFolding/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ mapFolding/theDao.py,sha256=E-hisOy_1_iQqS6w4c7S-C-sIgIcwnAPFqooeWuinVY,9008
9
+ mapFolding/theSSOT.py,sha256=r7_9t0dOo_IfBMqmkm1WXOzMfZjyPNco0hl1g9uU_2Y,12710
10
+ mapFolding/reference/flattened.py,sha256=S6D9wiFTlbeoetEqaMLOcA-R22BHOzjqPRujffNxxUM,14875
11
+ mapFolding/reference/hunterNumba.py,sha256=jDS0ORHkIhcJ1rzA5hT49sZHKf3rgJOoGesUCcbKFFY,6054
12
+ mapFolding/reference/irvineJavaPort.py,sha256=7GvBU0tnS6wpFgkYad3465do9jBQW-2bYvbCYyABPHM,3341
13
+ mapFolding/reference/jax.py,sha256=7ji9YWia6Kof0cjcNdiS1GG1rMbC5SBjcyVr_07AeUk,13845
14
+ mapFolding/reference/lunnan.py,sha256=iAbJELfW6RKNMdPcBY9b6rGQ-z1zoRf-1XCurCRMOo8,3951
15
+ mapFolding/reference/lunnanNumpy.py,sha256=rwVP3WIDXimpAuaxhRIuBYU56nVDTKlfGiclw_FkgUU,3765
16
+ mapFolding/reference/lunnanWhile.py,sha256=uRrMT23jTJvoQDlD_FzeIQe_pfMXJG6_bRvs7uhC8z0,3271
17
+ mapFolding/reference/rotatedEntryPoint.py,sha256=USZY3n3zwhSE68ATscUuN66t1qShuEbMI790Gz9JFTw,9352
18
+ mapFolding/reference/total_countPlus1vsPlusN.py,sha256=wpgay-uqPOBd64Z4Pg6tg40j7-4pzWHGMM6v0bnmjhE,6288
19
+ mapFolding/someAssemblyRequired/Z0Z_workbench.py,sha256=g4VkNKp2ts0koqcMSPNbE_ySR2-23Y-5CJBDpvbT6XU,16853
20
+ mapFolding/someAssemblyRequired/__init__.py,sha256=G1uIo1RWcdBjeFPXFwa69kizsZFzkDR55B2uyyY5z7E,680
21
+ mapFolding/someAssemblyRequired/getLLVMforNoReason.py,sha256=2kGRji3FGaALZwUZ6qlEjS7QxOkJK1Si-mAnsWePs_Q,983
22
+ mapFolding/someAssemblyRequired/ingredientsNumba.py,sha256=u5621TzZW7Sp8BXedq0yooyYoFwDDsd9smoqObzRf8g,7359
23
+ mapFolding/someAssemblyRequired/synthesizeDataConverters.py,sha256=J1qLKxqCMQd5JhcrTg9fvpPCfhb5TLz2wXY-J9z-TH8,5792
24
+ mapFolding/someAssemblyRequired/synthesizeNumbaJobVESTIGIAL.py,sha256=3yRCEMIf9UCswu6wQvdUK9H3MW6Ossn-wg5eOq8LWz8,22362
25
+ mapFolding/someAssemblyRequired/transformationTools.py,sha256=u2ah47kOqvVGKifuk7rZe4bSm3Z681nJzp73IXavYw4,36297
26
+ mapFolding/syntheticModules/numbaCountHistoricalExample.py,sha256=Oo0Xeex89sLD15iRt3N76OKRFScKl9qwO84-d5sv6lM,11871
27
+ mapFolding/syntheticModules/numbaCount_doTheNeedful.py,sha256=52RuwJVH2fROvWU2dT8wYcQvLgRuvkNZPq01kujCC_U,15725
28
+ mapFolding/syntheticModules/numba_doTheNeedfulHistoricalExample.py,sha256=J9wZ9PW5EVduOQWVze7CgpTHkUjRIvBPG8fNuT3IVpA,1145
29
+ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ tests/conftest.py,sha256=rRlXOhihwheHyQ8ggjRBbmgPVERxWjupajguVBzBkVE,10783
31
+ tests/test_computations.py,sha256=YhadlskBh_r5RiefHRy0FlrYQ0FelYbqcSNNSkSJMIY,3368
32
+ tests/test_filesystem.py,sha256=Kou0gj5T72oISao6umYfU6L_W5Hi7QS9_IxTv2hU0Pw,3147
33
+ tests/test_oeis.py,sha256=uxvwmgbnylSDdsVJfuAT0LuYLbIVFwSgdLxHm-xUGBM,5043
34
+ tests/test_other.py,sha256=1uuApByNWPiTf0zaro2dETkvyWQFfMweU_ge4aJuVgM,4244
35
+ tests/test_tasks.py,sha256=hkZygihT8bCEO2zc-2VcxReQrZJBwgLNbYx0YP4lTDg,2853
36
+ mapfolding-0.8.0.dist-info/LICENSE,sha256=NxH5Y8BdC-gNU-WSMwim3uMbID2iNDXJz7fHtuTdXhk,19346
37
+ mapfolding-0.8.0.dist-info/METADATA,sha256=AA0b9jY45EztgHbZQq8SbpBExcDpnmhotXZB4DDO_2A,7670
38
+ mapfolding-0.8.0.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
39
+ mapfolding-0.8.0.dist-info/entry_points.txt,sha256=F3OUeZR1XDTpoH7k3wXuRb3KF_kXTTeYhu5AGK1SiOQ,146
40
+ mapfolding-0.8.0.dist-info/top_level.txt,sha256=1gP2vFaqPwHujGwb3UjtMlLEGN-943VSYFR7V4gDqW8,17
41
+ mapfolding-0.8.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (76.0.0)
2
+ Generator: setuptools (76.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
tests/conftest.py CHANGED
@@ -1,5 +1,5 @@
1
1
  from collections.abc import Callable, Generator, Sequence
2
- from mapFolding.theSSOT import getAlgorithmDispatcher, getSourceAlgorithm, getPackageDispatcher, theModuleOfSyntheticModules, FREAKOUT
2
+ from mapFolding.theSSOT import getAlgorithmDispatcher, getSourceAlgorithm, getPackageDispatcher, theModuleOfSyntheticModules, raiseIfNoneGitHubIssueNumber3
3
3
  from mapFolding.beDRY import getLeavesTotal, validateListDimensions, makeDataContainer
4
4
  from mapFolding.oeis import oeisIDsImplemented, settingsOEIS
5
5
  from pathlib import Path
@@ -10,7 +10,6 @@ import random
10
10
  import shutil
11
11
  import unittest.mock
12
12
  import uuid
13
- # TODO learn how to run tests and coverage analysis without `env = ["NUMBA_DISABLE_JIT=1"]`
14
13
 
15
14
  # SSOT for test data paths and filenames
16
15
  pathDataSamples = Path("tests/dataSamples")
@@ -215,7 +214,7 @@ def syntheticDispatcherFixture(useThisDispatcher: Callable[..., Any]) -> Callabl
215
214
  dispatcherSynthetic = stuff
216
215
 
217
216
  if dispatcherSynthetic is None:
218
- raise FREAKOUT
217
+ raise raiseIfNoneGitHubIssueNumber3
219
218
 
220
219
  dispatcherSpec = importlib.util.spec_from_file_location(dispatcherSynthetic.callableSynthesized, dispatcherSynthetic.pathFilenameForMe)
221
220
  if dispatcherSpec is None:
@@ -3,16 +3,20 @@ from mapFolding.filesystem import getPathFilenameFoldsTotal
3
3
  from mapFolding.noHomeYet import getFoldsTotalKnown
4
4
  from mapFolding.oeis import settingsOEIS, oeisIDfor_n
5
5
  # from mapFolding.someAssemblyRequired import writeJobNumba
6
+ from pathlib import Path
6
7
  from tests.conftest import standardizedEqualToCallableReturn, registrarRecordsTmpObject
8
+ from types import ModuleType
7
9
  import importlib.util
10
+ import multiprocessing
8
11
  import pytest
9
- from pathlib import Path
10
- from types import ModuleType
11
12
 
12
- def test_algorithmSourceParallel(listDimensionsTestParallelization, useAlgorithmSourceDispatcher: None) -> None:
13
- standardizedEqualToCallableReturn(getFoldsTotalKnown(tuple(listDimensionsTestParallelization)), countFolds, listDimensionsTestParallelization, None, 'maximum')
13
+ if __name__ == '__main__':
14
+ multiprocessing.set_start_method('spawn')
15
+
16
+ def test_algorithmSourceParallel(listDimensionsTestParallelization: list[int], useAlgorithmSourceDispatcher: None) -> None:
17
+ standardizedEqualToCallableReturn(getFoldsTotalKnown(tuple(listDimensionsTestParallelization)), countFolds, listDimensionsTestParallelization, None, 'maximum', None)
14
18
 
15
- def test_algorithmSourceSequential(listDimensionsTestCountFolds, useAlgorithmSourceDispatcher: None) -> None:
19
+ def test_algorithmSourceSequential(listDimensionsTestCountFolds: tuple[int, ...], useAlgorithmSourceDispatcher: None) -> None:
16
20
  standardizedEqualToCallableReturn(getFoldsTotalKnown(tuple(listDimensionsTestCountFolds)), countFolds, listDimensionsTestCountFolds)
17
21
 
18
22
  def test_aOFn_calculate_value(oeisID: str) -> None:
tests/test_filesystem.py CHANGED
@@ -3,9 +3,7 @@ from mapFolding.filesystem import getFilenameFoldsTotal, getPathFilenameFoldsTot
3
3
  from mapFolding.beDRY import validateListDimensions
4
4
  from mapFolding.theSSOT import getPathJobRootDEFAULT
5
5
  from pathlib import Path
6
- from typing import Any
7
6
  import io
8
- import numpy
9
7
  import pytest
10
8
  import unittest.mock
11
9
 
tests/test_other.py CHANGED
@@ -42,8 +42,8 @@ import sys
42
42
  (tuple([3, 5, 7]), [3, 5, 7], (3, 5, 7)), # tuple sequence type
43
43
  ])
44
44
  def test_listDimensionsAsParameter(listDimensions: None | list[str] | list[int] | list[float] | list[None] | list[bool] | list[list[int]] | list[complex] | range | tuple[int, ...],
45
- expected_intInnit: type[ValueError] | list[int] | type[TypeError],
46
- expected_validateListDimensions: type[ValueError] | type[NotImplementedError] | tuple[int, ...] | type[TypeError]) -> None:
45
+ expected_intInnit: type[ValueError] | list[int] | type[TypeError],
46
+ expected_validateListDimensions: type[ValueError] | type[NotImplementedError] | tuple[int, ...] | type[TypeError]) -> None:
47
47
  """Test both validateListDimensions and getLeavesTotal with the same inputs."""
48
48
  standardizedEqualToCallableReturn(expected_intInnit, intInnit, listDimensions)
49
49
  standardizedEqualToCallableReturn(expected_validateListDimensions, validateListDimensions, listDimensions)
@@ -56,7 +56,6 @@ def test_getLeavesTotal_edge_cases() -> None:
56
56
  # Input preservation
57
57
  mapShape = (2, 3)
58
58
  standardizedEqualToCallableReturn(6, getLeavesTotal, mapShape)
59
- # Remove the lambda entirely for a simpler approach
60
59
  assert mapShape == (2, 3), "Input tuple was modified"
61
60
 
62
61
  @pytest.mark.parametrize("nameOfTest,callablePytest", PytestFor_intInnit())
tests/test_tasks.py CHANGED
@@ -1,20 +1,22 @@
1
- from typing import Literal
1
+ from collections.abc import Callable
2
2
  from mapFolding.basecamp import countFolds
3
3
  from mapFolding.beDRY import getTaskDivisions, setCPUlimit, validateListDimensions, getLeavesTotal
4
4
  from mapFolding.noHomeYet import getFoldsTotalKnown
5
5
  from tests.conftest import standardizedEqualToCallableReturn
6
+ from typing import Literal
6
7
  from Z0Z_tools.pytestForYourUse import PytestFor_defineConcurrencyLimit
7
- from collections.abc import Callable
8
+ import multiprocessing
8
9
  import pytest
9
10
 
10
- # TODO add a test. `C` = number of logical cores available. `n = C + 1`. Ensure that `[2,n]` is computed correctly.
11
- # Or, probably smarter: limit the number of cores, then run a test with C+1.
11
+ # When to use multiprocessing.set_start_method https://github.com/hunterhogan/mapFolding/issues/6
12
+ if __name__ == '__main__':
13
+ multiprocessing.set_start_method('spawn')
12
14
 
13
15
  def test_countFoldsComputationDivisionsInvalid(mapShapeTestFunctionality: tuple[int, ...]) -> None:
14
16
  standardizedEqualToCallableReturn(ValueError, countFolds, mapShapeTestFunctionality, None, {"wrong": "value"})
15
17
 
16
18
  def test_countFoldsComputationDivisionsMaximum(listDimensionsTestParallelization: list[int]) -> None:
17
- standardizedEqualToCallableReturn(getFoldsTotalKnown(tuple(listDimensionsTestParallelization)), countFolds, listDimensionsTestParallelization, None, 'maximum')
19
+ standardizedEqualToCallableReturn(getFoldsTotalKnown(tuple(listDimensionsTestParallelization)), countFolds, listDimensionsTestParallelization, None, 'maximum', None)
18
20
 
19
21
  @pytest.mark.parametrize("nameOfTest,callablePytest", PytestFor_defineConcurrencyLimit())
20
22
  def test_defineConcurrencyLimit(nameOfTest: str, callablePytest: Callable[[], None]) -> None:
@@ -1,7 +0,0 @@
1
- from mapFolding.someAssemblyRequired import IngredientsFunction, Make
2
- from typing import cast
3
- from types import ModuleType
4
- import ast
5
-
6
- def Z0Z_makeCountingFunction(callableTarget: str, sourceAlgorithm: ModuleType, inline: bool, dataclass: bool):
7
- pass
@@ -1,91 +0,0 @@
1
- from collections.abc import Sequence
2
- from mapFolding.someAssemblyRequired.whatWillBe import LedgerOfImports, ParametersNumba, Z0Z_getDatatypeModuleScalar, parametersNumbaDEFAULT
3
- from mapFolding.someAssemblyRequired.whatWillBe import Z0Z_getDecoratorCallable
4
- from mapFolding.someAssemblyRequired import Make, ifThis
5
- from typing import Any, cast
6
- import ast
7
-
8
- def thisIsNumbaDotJit(Ima: ast.AST) -> bool:
9
- return ifThis.isCallNamespace_Identifier(Z0Z_getDatatypeModuleScalar(), Z0Z_getDecoratorCallable())(Ima)
10
-
11
- def thisIsJit(Ima: ast.AST) -> bool:
12
- return ifThis.isCall_Identifier(Z0Z_getDecoratorCallable())(Ima)
13
-
14
- def thisIsAnyNumbaJitDecorator(Ima: ast.AST) -> bool:
15
- return thisIsNumbaDotJit(Ima) or thisIsJit(Ima)
16
-
17
- def decorateCallableWithNumba(FunctionDefTarget: ast.FunctionDef, allImports: LedgerOfImports, parametersNumba: ParametersNumba | None = None) -> tuple[ast.FunctionDef, LedgerOfImports]:
18
- def Z0Z_UnhandledDecorators(astCallable: ast.FunctionDef) -> ast.FunctionDef:
19
- # TODO: more explicit handling of decorators. I'm able to ignore this because I know `algorithmSource` doesn't have any decorators.
20
- for decoratorItem in astCallable.decorator_list.copy():
21
- import warnings
22
- astCallable.decorator_list.remove(decoratorItem)
23
- warnings.warn(f"Removed decorator {ast.unparse(decoratorItem)} from {astCallable.name}")
24
- return astCallable
25
-
26
- def make_arg4parameter(signatureElement: ast.arg) -> ast.Subscript | ast.Name | None:
27
- if isinstance(signatureElement.annotation, ast.Subscript) and isinstance(signatureElement.annotation.slice, ast.Tuple):
28
- annotationShape: ast.expr = signatureElement.annotation.slice.elts[0]
29
- if isinstance(annotationShape, ast.Subscript) and isinstance(annotationShape.slice, ast.Tuple):
30
- shapeAsListSlices: list[ast.Slice] = [ast.Slice() for _axis in range(len(annotationShape.slice.elts))]
31
- shapeAsListSlices[-1] = ast.Slice(step=ast.Constant(value=1))
32
- shapeAST: ast.Slice | ast.Tuple = ast.Tuple(elts=list(shapeAsListSlices), ctx=ast.Load())
33
- else:
34
- shapeAST = ast.Slice(step=ast.Constant(value=1))
35
-
36
- annotationDtype: ast.expr = signatureElement.annotation.slice.elts[1]
37
- if (isinstance(annotationDtype, ast.Subscript) and isinstance(annotationDtype.slice, ast.Attribute)):
38
- datatypeAST = annotationDtype.slice.attr
39
- else:
40
- datatypeAST = None
41
-
42
- ndarrayName = signatureElement.arg
43
- Z0Z_hacky_dtype: str = ndarrayName
44
- datatype_attr = datatypeAST or Z0Z_hacky_dtype
45
- allImports.addImportFromStr(datatypeModuleDecorator, datatype_attr)
46
- datatypeNumba = ast.Name(id=datatype_attr, ctx=ast.Load())
47
-
48
- return ast.Subscript(value=datatypeNumba, slice=shapeAST, ctx=ast.Load())
49
-
50
- elif isinstance(signatureElement.annotation, ast.Name):
51
- return signatureElement.annotation
52
- return None
53
-
54
- datatypeModuleDecorator: str = Z0Z_getDatatypeModuleScalar()
55
- list_argsDecorator: Sequence[ast.expr] = []
56
-
57
- list_arg4signature_or_function: list[ast.expr] = []
58
- for parameter in FunctionDefTarget.args.args:
59
- signatureElement: ast.Subscript | ast.Name | None = make_arg4parameter(parameter)
60
- if signatureElement:
61
- list_arg4signature_or_function.append(signatureElement)
62
-
63
- if FunctionDefTarget.returns and isinstance(FunctionDefTarget.returns, ast.Name):
64
- theReturn: ast.Name = FunctionDefTarget.returns
65
- list_argsDecorator = [cast(ast.expr, ast.Call(func=ast.Name(id=theReturn.id, ctx=ast.Load())
66
- , args=list_arg4signature_or_function if list_arg4signature_or_function else [], keywords=[] ) )]
67
- elif list_arg4signature_or_function:
68
- list_argsDecorator = [cast(ast.expr, ast.Tuple(elts=list_arg4signature_or_function, ctx=ast.Load()))]
69
-
70
- for decorator in FunctionDefTarget.decorator_list.copy():
71
- if thisIsAnyNumbaJitDecorator(decorator):
72
- decorator = cast(ast.Call, decorator)
73
- if parametersNumba is None:
74
- parametersNumbaSherpa: dict[str, Any] = Make.copy_astCallKeywords(decorator)
75
- if (_HunterIsSureThereAreBetterWaysToDoThis := True):
76
- if parametersNumbaSherpa:
77
- parametersNumba = cast(ParametersNumba, parametersNumbaSherpa)
78
- FunctionDefTarget.decorator_list.remove(decorator)
79
-
80
- FunctionDefTarget = Z0Z_UnhandledDecorators(FunctionDefTarget)
81
- if parametersNumba is None:
82
- parametersNumba = parametersNumbaDEFAULT
83
- listDecoratorKeywords: list[ast.keyword] = [ast.keyword(arg=parameterName, value=ast.Constant(value=parameterValue)) for parameterName, parameterValue in parametersNumba.items()]
84
-
85
- decoratorModule: str = Z0Z_getDatatypeModuleScalar()
86
- decoratorCallable: str = Z0Z_getDecoratorCallable()
87
- allImports.addImportFromStr(decoratorModule, decoratorCallable)
88
- astDecorator: ast.Call = Make.astCall(Make.astName(decoratorCallable), list_argsDecorator, listDecoratorKeywords)
89
-
90
- FunctionDefTarget.decorator_list = [astDecorator]
91
- return FunctionDefTarget, allImports
@@ -1,91 +0,0 @@
1
- # pyright: basic
2
- from os import PathLike
3
- from typing import TYPE_CHECKING
4
- if TYPE_CHECKING:
5
- from mapFolding.someAssemblyRequired.whatWillBe import ParametersSynthesizeNumbaCallable, listNumbaCallableDispatchees
6
- from mapFolding.theSSOT import theModuleOfSyntheticModules
7
- from mapFolding.theSSOT import getSourceAlgorithm
8
- import types
9
-
10
- def makeFlowNumbaOptimized(listCallablesInline: list[ParametersSynthesizeNumbaCallable] = listNumbaCallableDispatchees, callableDispatcher: bool = True, algorithmSource: types.ModuleType = getSourceAlgorithm(), relativePathWrite: str | PathLike[str] = theModuleOfSyntheticModules, filenameModuleWrite: str = 'filenameModuleSyntheticWrite', formatFilenameWrite: str = 'formatStrFilenameForCallableSynthetic'):
11
- from mapFolding.someAssemblyRequired.whatWillBe import ParametersSynthesizeNumbaCallable, listNumbaCallableDispatchees
12
- from mapFolding.someAssemblyRequired.whatWillBe import LedgerOfImports, Z0Z_autoflake_additional_imports
13
- from mapFolding.theSSOT import FREAKOUT
14
- from mapFolding.theSSOT import thePathPackage, getDatatypePackage
15
- from mapFolding.someAssemblyRequired.whatWillBe import FunctionInliner, YouOughtaKnow, ast_Identifier
16
- from pathlib import Path
17
- from typing import cast
18
- import ast
19
- import autoflake
20
- import inspect
21
- import warnings
22
- if relativePathWrite and Path(relativePathWrite).is_absolute():
23
- raise ValueError("The path to write the module must be relative to the root of the package.")
24
-
25
- listStuffYouOughtaKnow: list[YouOughtaKnow] = []
26
-
27
- listFunctionDefs: list[ast.FunctionDef] = []
28
- allImportsModule = LedgerOfImports()
29
- for tupleParameters in listCallablesInline:
30
- pythonSource: str = inspect.getsource(algorithmSource)
31
- astModule: ast.Module = ast.parse(pythonSource)
32
- if allImports is None:
33
- allImports = LedgerOfImports(astModule)
34
- else:
35
- allImports.walkThis(astModule)
36
-
37
- if inlineCallables:
38
- dictionaryFunctionDef: dict[ast_Identifier, ast.FunctionDef] = {statement.name: statement for statement in astModule.body if isinstance(statement, ast.FunctionDef)}
39
- callableInlinerWorkhorse = FunctionInliner(dictionaryFunctionDef)
40
- FunctionDefTarget = callableInlinerWorkhorse.inlineFunctionBody(callableTarget)
41
- else:
42
- FunctionDefTarget = next((statement for statement in astModule.body if isinstance(statement, ast.FunctionDef) and statement.name == callableTarget), None)
43
- if not FunctionDefTarget:
44
- raise ValueError(f"Could not find function {callableTarget} in source code")
45
-
46
- ast.fix_missing_locations(FunctionDefTarget)
47
- listFunctionDefs.append(FunctionDefTarget)
48
- allImportsModule.update(allImports)
49
-
50
- listAstImports: list[ast.ImportFrom | ast.Import] = allImportsModule.makeListAst()
51
- additional_imports: list[str] = Z0Z_autoflake_additional_imports
52
- additional_imports.append(getDatatypePackage())
53
-
54
- astModule = ast.Module(body=cast(list[ast.stmt], listAstImports + listFunctionDefs), type_ignores=[])
55
- ast.fix_missing_locations(astModule)
56
- pythonSource: str = ast.unparse(astModule)
57
- if not pythonSource: raise FREAKOUT
58
- pythonSource = autoflake.fix_code(pythonSource, additional_imports)
59
-
60
- pathWrite: Path = thePathPackage / relativePathWrite
61
-
62
- if not filenameWrite:
63
- if len(listCallableSynthesized) == 1:
64
- callableTarget: str = listCallableSynthesized[0].callableTarget
65
- else:
66
- callableTarget = filenameWriteCallableTargetDEFAULT
67
- # NOTE WARNING I think I broken this format string. See theSSOT.py
68
- filenameWrite = formatFilenameWrite.format(callableTarget=callableTarget)
69
- else:
70
- if not filenameWrite.endswith('.py'):
71
- warnings.warn(f"Filename {filenameWrite=} does not end with '.py'.")
72
-
73
- pathFilename: Path = pathWrite / filenameWrite
74
-
75
- pathFilename.write_text(pythonSource)
76
-
77
- howIsThisStillAThing: Path = thePathPackage.parent
78
- dumbassPythonNamespace: tuple[str, ...] = pathFilename.relative_to(howIsThisStillAThing).with_suffix('').parts
79
- ImaModule: str = '.'.join(dumbassPythonNamespace)
80
-
81
- for item in listCallableSynthesized:
82
- callableTarget: str = item.callableTarget
83
- astImportFrom = ast.ImportFrom(module=ImaModule, names=[ast.alias(name=callableTarget, asname=None)], level=0)
84
- stuff = YouOughtaKnow(callableSynthesized=callableTarget, pathFilenameForMe=pathFilename, astForCompetentProgrammers=astImportFrom)
85
- listStuffYouOughtaKnow.append(stuff)
86
- listStuffYouOughtaKnow.extend(listStuff)
87
-
88
- if callableDispatcher:
89
- pass
90
-
91
- return listStuffYouOughtaKnow
@@ -1,311 +0,0 @@
1
- """
2
- - Settings for synthesizing the modules used by the package (i.e., the flow for numba)
3
- - Settings for synthesizing modules that could be used by the package (e.g., the flow for JAX)
4
- - Therefore, an abstracted system for creating settings for the package
5
- - And with only a little more effort, an abstracted system for creating settings to synthesize arbitrary subsets of modules for arbitrary packages
6
- """
7
- from mapFolding.someAssemblyRequired.transformationTools import *
8
- from mapFolding.theSSOT import (
9
- FREAKOUT,
10
- getDatatypePackage,
11
- getSourceAlgorithm,
12
- theDataclassIdentifierAsStr,
13
- theDataclassInstanceAsStr,
14
- theDispatcherCallableAsStr,
15
- theFileExtension,
16
- theFormatStrModuleForCallableSynthetic,
17
- theFormatStrModuleSynthetic,
18
- theLogicalPathModuleDataclass,
19
- theLogicalPathModuleDispatcherSynthetic,
20
- theModuleOfSyntheticModules,
21
- thePackageName,
22
- thePathPackage,
23
- Z0Z_sequentialCallableAsStr,
24
- )
25
- from autoflake import fix_code as autoflake_fix_code
26
- from collections import defaultdict
27
- from collections.abc import Sequence
28
- from inspect import getsource as inspect_getsource
29
- from mapFolding.someAssemblyRequired.ingredientsNumba import parametersNumbaDEFAULT, parametersNumbaSuperJit, parametersNumbaSuperJitParallel, ParametersNumba
30
- from pathlib import Path
31
- from types import ModuleType
32
- from typing import NamedTuple
33
- from Z0Z_tools import updateExtendPolishDictionaryLists
34
- import ast
35
- import dataclasses
36
-
37
- """
38
- Start with what is: theDao.py
39
- Create settings that can transform into what I or the user want it to be.
40
-
41
- The simplest flow with numba is:
42
- 1. one module
43
- 2. dispatcher
44
- - initialize data with makeJob
45
- - smash dataclass
46
- - call countSequential
47
- 3. countSequential
48
- - jitted, not super-jitted
49
- - functions inlined (or I'd have to jit them)
50
- - return groupsOfFolds
51
- 4. recycle the dataclass with groupsOfFolds
52
- 5. return the dataclass
53
- """
54
-
55
- @dataclasses.dataclass
56
- class RecipeSynthesizeFlow:
57
- """Settings for synthesizing flow."""
58
- # TODO consider `IngredientsFlow` or similar
59
- sourceAlgorithm: ModuleType = getSourceAlgorithm()
60
- sourcePython: str = inspect_getsource(sourceAlgorithm)
61
- # sourcePython: str = inspect_getsource(self.sourceAlgorithm)
62
- # "self" is not defined
63
- # I still hate the OOP paradigm. But I like this dataclass stuff.
64
- source_astModule: ast.Module = ast.parse(sourcePython)
65
-
66
- # ========================================
67
- # Filesystem
68
- pathPackage: Path = thePathPackage
69
- fileExtension: str = theFileExtension
70
-
71
- # ========================================
72
- # Logical identifiers
73
- # meta
74
- formatStrModuleSynthetic: str = theFormatStrModuleSynthetic
75
- formatStrModuleForCallableSynthetic: str = theFormatStrModuleForCallableSynthetic
76
-
77
- # Package
78
- packageName: ast_Identifier = thePackageName
79
-
80
- # Module
81
- moduleOfSyntheticModules: str = theModuleOfSyntheticModules
82
- logicalPathModuleDataclass: str = theLogicalPathModuleDataclass
83
- logicalPathModuleDispatcher: str = theLogicalPathModuleDispatcherSynthetic
84
- dataConverterModule: str = 'dataNamespaceFlattened'
85
-
86
- # Function
87
- dataclassIdentifierAsStr: str = theDataclassIdentifierAsStr
88
- dispatcherCallableAsStr: str = theDispatcherCallableAsStr
89
- dataConverterCallableAsStr: str = 'flattenData'
90
- sequentialCallableAsStr: str = Z0Z_sequentialCallableAsStr
91
-
92
- # Variable
93
- dataclassInstanceAsStr: str = theDataclassInstanceAsStr
94
-
95
- class LedgerOfImports:
96
- def __init__(self, startWith: ast.AST | None = None) -> None:
97
- self.dictionaryImportFrom: dict[str, list[tuple[str, str | None]]] = defaultdict(list)
98
- self.listImport: list[str] = []
99
-
100
- if startWith:
101
- self.walkThis(startWith)
102
-
103
- def addAst(self, astImport_: ast.Import | ast.ImportFrom) -> None:
104
- if not isinstance(astImport_, (ast.Import, ast.ImportFrom)): # pyright: ignore[reportUnnecessaryIsInstance]
105
- raise ValueError(f"Expected ast.Import or ast.ImportFrom, got {type(astImport_)}")
106
- if isinstance(astImport_, ast.Import):
107
- for alias in astImport_.names:
108
- self.listImport.append(alias.name)
109
- else:
110
- if astImport_.module is not None:
111
- for alias in astImport_.names:
112
- self.dictionaryImportFrom[astImport_.module].append((alias.name, alias.asname))
113
-
114
- def addImportStr(self, module: str) -> None:
115
- self.listImport.append(module)
116
-
117
- def addImportFromStr(self, module: str, name: str, asname: str | None = None) -> None:
118
- self.dictionaryImportFrom[module].append((name, asname))
119
-
120
- def makeListAst(self) -> list[ast.ImportFrom | ast.Import]:
121
- listAstImportFrom: list[ast.ImportFrom] = []
122
-
123
- for module, listOfNameTuples in sorted(self.dictionaryImportFrom.items()):
124
- listOfNameTuples = sorted(list(set(listOfNameTuples)), key=lambda nameTuple: nameTuple[0])
125
- listAlias: list[ast.alias] = []
126
- for name, asname in listOfNameTuples:
127
- listAlias.append(Make.astAlias(name, asname))
128
- listAstImportFrom.append(Make.astImportFrom(module, listAlias))
129
-
130
- listAstImport: list[ast.Import] = [Make.astImport(name) for name in sorted(set(self.listImport))]
131
- return listAstImportFrom + listAstImport
132
-
133
- def update(self, *fromLedger: 'LedgerOfImports') -> None:
134
- """
135
- Update this ledger with imports from one or more other ledgers.
136
-
137
- Parameters:
138
- *fromTracker: One or more other `LedgerOfImports` objects from which to merge.
139
- """
140
- self.dictionaryImportFrom = updateExtendPolishDictionaryLists(self.dictionaryImportFrom, *(ledger.dictionaryImportFrom for ledger in fromLedger), destroyDuplicates=True, reorderLists=True)
141
-
142
- for ledger in fromLedger:
143
- self.listImport.extend(ledger.listImport)
144
-
145
- def walkThis(self, walkThis: ast.AST) -> None:
146
- for smurf in ast.walk(walkThis):
147
- if isinstance(smurf, (ast.Import, ast.ImportFrom)):
148
- self.addAst(smurf)
149
-
150
- @dataclasses.dataclass
151
- class IngredientsFunction:
152
- """Everything necessary to integrate a function into a module should be here."""
153
- FunctionDef: ast.FunctionDef # hint `Make.astFunctionDef`
154
- imports: LedgerOfImports = dataclasses.field(default_factory=LedgerOfImports)
155
-
156
- @dataclasses.dataclass
157
- class IngredientsModule:
158
- """Everything necessary to create a module, including the package context, should be here."""
159
- name: ast_Identifier
160
- ingredientsFunction: dataclasses.InitVar[Sequence[IngredientsFunction] | IngredientsFunction | None] = None
161
-
162
- imports: LedgerOfImports = dataclasses.field(default_factory=LedgerOfImports)
163
- prologue: list[ast.stmt] = dataclasses.field(default_factory=list)
164
- functions: list[ast.FunctionDef | ast.stmt] = dataclasses.field(default_factory=list)
165
- epilogue: list[ast.stmt] = dataclasses.field(default_factory=list)
166
- launcher: list[ast.stmt] = dataclasses.field(default_factory=list)
167
-
168
- packageName: ast_Identifier | None= thePackageName
169
- logicalPathINFIX: ast_Identifier | strDotStrCuzPyStoopid | None = None # module names other than the module itself and the package name
170
- pathPackage: Path = thePathPackage
171
- fileExtension: str = theFileExtension
172
- type_ignores: list[ast.TypeIgnore] = dataclasses.field(default_factory=list)
173
-
174
- def _getLogicalPathParent(self) -> str | None:
175
- listModules: list[ast_Identifier] = []
176
- if self.packageName:
177
- listModules.append(self.packageName)
178
- if self.logicalPathINFIX:
179
- listModules.append(self.logicalPathINFIX)
180
- if listModules:
181
- return '.'.join(listModules)
182
-
183
- def _getLogicalPathAbsolute(self) -> str:
184
- listModules: list[ast_Identifier] = []
185
- logicalPathParent: str | None = self._getLogicalPathParent()
186
- if logicalPathParent:
187
- listModules.append(logicalPathParent)
188
- listModules.append(self.name)
189
- return '.'.join(listModules)
190
-
191
- @property
192
- def pathFilename(self) -> Path:
193
- pathRoot: Path = self.pathPackage
194
- filename = self.name + self.fileExtension
195
- if self.logicalPathINFIX:
196
- whyIsThisStillAThing = self.logicalPathINFIX.split('.')
197
- pathRoot = pathRoot.joinpath(*whyIsThisStillAThing)
198
- return pathRoot.joinpath(filename)
199
-
200
- @property
201
- def absoluteImport(self) -> ast.Import:
202
- return Make.astImport(self._getLogicalPathAbsolute())
203
-
204
- @property
205
- def absoluteImportFrom(self) -> ast.ImportFrom:
206
- """ `from . import theModule` """
207
- logicalPathParent: str | None = self._getLogicalPathParent()
208
- if logicalPathParent is None:
209
- logicalPathParent = '.'
210
- return Make.astImportFrom(logicalPathParent, [Make.astAlias(self.name)])
211
-
212
- def __post_init__(self, ingredientsFunction: Sequence[IngredientsFunction] | IngredientsFunction | None = None) -> None:
213
- if ingredientsFunction is not None:
214
- if isinstance(ingredientsFunction, IngredientsFunction):
215
- self.addIngredientsFunction(ingredientsFunction)
216
- else:
217
- self.addIngredientsFunction(*ingredientsFunction)
218
-
219
- def addIngredientsFunction(self, *ingredientsFunction: IngredientsFunction) -> None:
220
- """Add one or more `IngredientsFunction`. """
221
- listLedgers: list[LedgerOfImports] = []
222
- for definition in ingredientsFunction:
223
- self.functions.append(definition.FunctionDef)
224
- listLedgers.append(definition.imports)
225
- self.imports.update(*listLedgers)
226
-
227
- def _makeModuleBody(self) -> list[ast.stmt]:
228
- """Constructs the body of the module, including prologue, functions, epilogue, and launcher."""
229
- body: list[ast.stmt] = []
230
- body.extend(self.imports.makeListAst())
231
- body.extend(self.prologue)
232
- body.extend(self.functions)
233
- body.extend(self.epilogue)
234
- body.extend(self.launcher)
235
- # TODO `launcher` must start with `if __name__ == '__main__':` and be indented
236
- return body
237
-
238
- def writeModule(self) -> None:
239
- """Writes the module to disk with proper imports and functions.
240
-
241
- This method creates a proper AST module with imports and function definitions,
242
- fixes missing locations, unpacks the AST to Python code, applies autoflake
243
- to clean up imports, and writes the resulting code to the appropriate file.
244
- """
245
- astModule = Make.astModule(body=self._makeModuleBody(), type_ignores=self.type_ignores)
246
- ast.fix_missing_locations(astModule)
247
- pythonSource: str = ast.unparse(astModule)
248
- if not pythonSource: raise FREAKOUT
249
- autoflake_additional_imports: list[str] = []
250
- if self.packageName:
251
- autoflake_additional_imports.append(self.packageName)
252
- # TODO LedgerOfImports method: list of package names. autoflake_additional_imports.extend()
253
- autoflake_additional_imports.append(getDatatypePackage())
254
- pythonSource = autoflake_fix_code(pythonSource, autoflake_additional_imports, expand_star_imports=False, remove_all_unused_imports=False, remove_duplicate_keys = False, remove_unused_variables = False,)
255
- self.pathFilename.write_text(pythonSource)
256
-
257
- @dataclasses.dataclass
258
- class RecipeSynthesizeCountingFunction:
259
- """Settings for synthesizing counting functions."""
260
- ingredients: IngredientsFunction
261
-
262
- numbaFlow: RecipeSynthesizeFlow = RecipeSynthesizeFlow()
263
-
264
- # https://github.com/hunterhogan/mapFolding/issues/3
265
- sequentialFunctionDef = extractFunctionDef(numbaFlow.sequentialCallableAsStr, numbaFlow.source_astModule)
266
- if sequentialFunctionDef is None: raise FREAKOUT
267
-
268
- numbaCountSequential = RecipeSynthesizeCountingFunction(IngredientsFunction(
269
- FunctionDef=sequentialFunctionDef,
270
- imports=LedgerOfImports(numbaFlow.source_astModule)
271
- ))
272
-
273
- # the data converter and the dispatcher could be in the same module.
274
-
275
- Z0Z_autoflake_additional_imports: list[str] = []
276
- Z0Z_autoflake_additional_imports.append(thePackageName)
277
-
278
- class ParametersSynthesizeNumbaCallable(NamedTuple):
279
- callableTarget: str
280
- parametersNumba: ParametersNumba | None = None
281
- inlineCallables: bool = False
282
-
283
- listNumbaCallableDispatchees: list[ParametersSynthesizeNumbaCallable] = [
284
- ParametersSynthesizeNumbaCallable('countParallel', parametersNumbaSuperJitParallel, True),
285
- ParametersSynthesizeNumbaCallable('countSequential', parametersNumbaSuperJit, True),
286
- ParametersSynthesizeNumbaCallable('countInitialize', parametersNumbaDEFAULT, True),
287
- ]
288
-
289
- _datatypeModuleScalar = ''
290
- _decoratorCallable = ''
291
-
292
- # if numba
293
- _datatypeModuleScalar = 'numba'
294
- _decoratorCallable = 'jit'
295
- Z0Z_autoflake_additional_imports.append('numba')
296
-
297
- def Z0Z_getDatatypeModuleScalar() -> str:
298
- return _datatypeModuleScalar
299
-
300
- def Z0Z_setDatatypeModuleScalar(moduleName: str) -> str:
301
- global _datatypeModuleScalar
302
- _datatypeModuleScalar = moduleName
303
- return _datatypeModuleScalar
304
-
305
- def Z0Z_getDecoratorCallable() -> str:
306
- return _decoratorCallable
307
-
308
- def Z0Z_setDecoratorCallable(decoratorName: str) -> str:
309
- global _decoratorCallable
310
- _decoratorCallable = decoratorName
311
- return _decoratorCallable
File without changes