mapFolding 0.9.0__py3-none-any.whl → 0.9.2__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.
- mapFolding/__init__.py +49 -48
- mapFolding/basecamp.py +40 -35
- mapFolding/beDRY.py +75 -69
- mapFolding/oeis.py +74 -85
- mapFolding/reference/__init__.py +2 -2
- mapFolding/someAssemblyRequired/RecipeJob.py +103 -0
- mapFolding/someAssemblyRequired/__init__.py +31 -29
- mapFolding/someAssemblyRequired/_theTypes.py +9 -1
- mapFolding/someAssemblyRequired/_tool_Make.py +1 -2
- mapFolding/someAssemblyRequired/_tool_Then.py +16 -8
- mapFolding/someAssemblyRequired/_toolboxAntecedents.py +111 -23
- mapFolding/someAssemblyRequired/_toolboxContainers.py +27 -28
- mapFolding/someAssemblyRequired/_toolboxPython.py +3 -0
- mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +83 -51
- mapFolding/someAssemblyRequired/toolboxNumba.py +19 -220
- mapFolding/someAssemblyRequired/transformationTools.py +183 -12
- mapFolding/syntheticModules/{numbaCount_doTheNeedful.py → numbaCount.py} +13 -12
- mapFolding/theDao.py +37 -36
- mapFolding/theSSOT.py +29 -33
- mapFolding/toolboxFilesystem.py +29 -38
- {mapfolding-0.9.0.dist-info → mapfolding-0.9.2.dist-info}/METADATA +2 -1
- mapfolding-0.9.2.dist-info/RECORD +47 -0
- tests/test_computations.py +2 -1
- tests/test_other.py +0 -7
- mapfolding-0.9.0.dist-info/RECORD +0 -46
- /mapFolding/reference/{lunnanNumpy.py → lunnonNumpy.py} +0 -0
- /mapFolding/reference/{lunnanWhile.py → lunnonWhile.py} +0 -0
- {mapfolding-0.9.0.dist-info → mapfolding-0.9.2.dist-info}/WHEEL +0 -0
- {mapfolding-0.9.0.dist-info → mapfolding-0.9.2.dist-info}/entry_points.txt +0 -0
- {mapfolding-0.9.0.dist-info → mapfolding-0.9.2.dist-info}/licenses/LICENSE +0 -0
- {mapfolding-0.9.0.dist-info → mapfolding-0.9.2.dist-info}/top_level.txt +0 -0
mapFolding/oeis.py
CHANGED
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Interface to The Online Encyclopedia of Integer Sequences (OEIS) for map folding sequences.
|
|
3
3
|
|
|
4
|
-
This module provides a comprehensive interface for accessing and utilizing integer sequences
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
This module provides a comprehensive interface for accessing and utilizing integer sequences from the OEIS that relate
|
|
5
|
+
to map folding problems. It serves as the bridge between mathematical sequence definitions and the computational
|
|
6
|
+
algorithm, implementing:
|
|
7
7
|
|
|
8
8
|
1. Retrieval of sequence data from OEIS with local caching for performance optimization.
|
|
9
9
|
2. Mapping of sequence indices to corresponding map shapes based on sequence definitions.
|
|
10
10
|
3. Command-line and programmatic interfaces for sequence lookups and validation.
|
|
11
11
|
4. Computation of sequence terms not available in the OEIS database.
|
|
12
12
|
|
|
13
|
-
The module maintains a registry of implemented OEIS sequences (A001415-A001418, A195646)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
literature while also extending sequences beyond their currently known terms.
|
|
13
|
+
The module maintains a registry of implemented OEIS sequences (A001415-A001418, A195646) with their metadata, known
|
|
14
|
+
values, and conversion functions between sequence indices and map dimensions. This allows the package to validate
|
|
15
|
+
results against established mathematical literature while also extending sequences beyond their currently known terms.
|
|
17
16
|
|
|
18
|
-
Each sequence is carefully mapped to its corresponding map folding problem, enabling
|
|
19
|
-
|
|
20
|
-
implementation in the package.
|
|
17
|
+
Each sequence is carefully mapped to its corresponding map folding problem, enabling seamless integration between the
|
|
18
|
+
mathematical definition in OEIS and the computational implementation in the package.
|
|
21
19
|
"""
|
|
22
20
|
from collections.abc import Callable
|
|
23
21
|
from datetime import datetime, timedelta
|
|
@@ -59,14 +57,20 @@ class SettingsOEIShardcodedValues(TypedDict):
|
|
|
59
57
|
valuesTestValidation: list[int]
|
|
60
58
|
|
|
61
59
|
settingsOEIShardcodedValues: dict[str, SettingsOEIShardcodedValues] = {
|
|
60
|
+
'A000136': {
|
|
61
|
+
'getMapShape': lambda n: tuple(sorted([1, n])),
|
|
62
|
+
'valuesBenchmark': [14],
|
|
63
|
+
'valuesTestParallelization': [*range(3, 7)],
|
|
64
|
+
'valuesTestValidation': [random.randint(2, 9)],
|
|
65
|
+
},
|
|
62
66
|
'A001415': {
|
|
63
|
-
'getMapShape': lambda n: (2, n)
|
|
67
|
+
'getMapShape': lambda n: tuple(sorted([2, n])),
|
|
64
68
|
'valuesBenchmark': [14],
|
|
65
69
|
'valuesTestParallelization': [*range(3, 7)],
|
|
66
70
|
'valuesTestValidation': [random.randint(2, 9)],
|
|
67
71
|
},
|
|
68
72
|
'A001416': {
|
|
69
|
-
'getMapShape': lambda n: (3, n)
|
|
73
|
+
'getMapShape': lambda n: tuple(sorted([3, n])),
|
|
70
74
|
'valuesBenchmark': [9],
|
|
71
75
|
'valuesTestParallelization': [*range(3, 5)],
|
|
72
76
|
'valuesTestValidation': [random.randint(2, 6)],
|
|
@@ -98,10 +102,8 @@ def validateOEISid(oeisIDcandidate: str) -> str:
|
|
|
98
102
|
"""
|
|
99
103
|
Validates an OEIS sequence ID against implemented sequences.
|
|
100
104
|
|
|
101
|
-
If the provided ID is recognized within the application's implemented
|
|
102
|
-
|
|
103
|
-
Otherwise, a KeyError is raised indicating that the sequence is not
|
|
104
|
-
directly supported.
|
|
105
|
+
If the provided ID is recognized within the application's implemented OEIS sequences, the function returns the
|
|
106
|
+
verified ID in uppercase. Otherwise, a KeyError is raised indicating that the sequence is not directly supported.
|
|
105
107
|
|
|
106
108
|
Parameters:
|
|
107
109
|
oeisIDcandidate: The OEIS sequence identifier to validate.
|
|
@@ -132,25 +134,23 @@ def _parseBFileOEIS(OEISbFile: str, oeisID: str) -> dict[int, int]:
|
|
|
132
134
|
"""
|
|
133
135
|
Parses the content of an OEIS b-file for a given sequence ID.
|
|
134
136
|
|
|
135
|
-
This function processes a multiline string representing an OEIS b-file and
|
|
136
|
-
|
|
137
|
-
values. The first line of the b-file is expected to contain a comment that
|
|
137
|
+
This function processes a multiline string representing an OEIS b-file and creates a dictionary mapping integer
|
|
138
|
+
indices to their corresponding sequence values. The first line of the b-file is expected to contain a comment that
|
|
138
139
|
matches the given sequence ID. If it does not match, a ValueError is raised.
|
|
139
140
|
|
|
140
141
|
Parameters:
|
|
141
|
-
OEISbFile: A multiline string representing an OEIS b-file.
|
|
142
|
-
oeisID: The expected OEIS sequence identifier.
|
|
142
|
+
OEISbFile: A multiline string representing an OEIS b-file. oeisID: The expected OEIS sequence identifier.
|
|
143
143
|
Returns:
|
|
144
|
-
OEISsequence: A dictionary where each key is an integer index `n` and
|
|
145
|
-
|
|
144
|
+
OEISsequence: A dictionary where each key is an integer index `n` and each value is the sequence value `a(n)`
|
|
145
|
+
corresponding to that index.
|
|
146
146
|
Raises:
|
|
147
|
-
ValueError: If the first line of the file does not indicate the expected
|
|
148
|
-
|
|
147
|
+
ValueError: If the first line of the file does not indicate the expected sequence ID or if the content format is
|
|
148
|
+
invalid.
|
|
149
149
|
"""
|
|
150
150
|
bFileLines: list[str] = OEISbFile.strip().splitlines()
|
|
151
|
-
if not bFileLines.pop(0).startswith(f"# {oeisID}"):
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
# if not bFileLines.pop(0).startswith(f"# {oeisID}"):
|
|
152
|
+
# warnings.warn(f"Content does not match sequence {oeisID}")
|
|
153
|
+
# return {-1: -1}
|
|
154
154
|
|
|
155
155
|
OEISsequence: dict[int, int] = {}
|
|
156
156
|
for line in bFileLines:
|
|
@@ -164,23 +164,21 @@ def getOEISofficial(pathFilenameCache: Path, url: str) -> None | str:
|
|
|
164
164
|
"""
|
|
165
165
|
Retrieve OEIS sequence data from cache or online source.
|
|
166
166
|
|
|
167
|
-
This function implements a caching strategy for OEIS sequence data, first checking
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
writes it to the cache for future use.
|
|
167
|
+
This function implements a caching strategy for OEIS sequence data, first checking if a local cached copy exists and
|
|
168
|
+
is not expired. If a valid cache exists, it returns the cached content; otherwise, it fetches the data from the OEIS
|
|
169
|
+
website and writes it to the cache for future use.
|
|
171
170
|
|
|
172
171
|
Parameters:
|
|
173
|
-
pathFilenameCache: Path to the local cache file.
|
|
174
|
-
|
|
172
|
+
pathFilenameCache: Path to the local cache file. url: URL to retrieve the OEIS sequence data from if cache is
|
|
173
|
+
invalid or missing.
|
|
175
174
|
|
|
176
175
|
Returns:
|
|
177
|
-
oeisInformation: The retrieved OEIS sequence information as a string, or None if
|
|
178
|
-
|
|
176
|
+
oeisInformation: The retrieved OEIS sequence information as a string, or None if the information could not be
|
|
177
|
+
retrieved.
|
|
179
178
|
|
|
180
179
|
Notes:
|
|
181
|
-
The cache expiration period is controlled by the global `cacheDays` variable.
|
|
182
|
-
|
|
183
|
-
it will return None and issue a warning.
|
|
180
|
+
The cache expiration period is controlled by the global `cacheDays` variable. If the function fails to retrieve
|
|
181
|
+
data from both cache and online source, it will return None and issue a warning.
|
|
184
182
|
"""
|
|
185
183
|
tryCache: bool = False
|
|
186
184
|
if pathFilenameCache.exists():
|
|
@@ -207,22 +205,20 @@ def getOEISofficial(pathFilenameCache: Path, url: str) -> None | str:
|
|
|
207
205
|
|
|
208
206
|
def getOEISidValues(oeisID: str) -> dict[int, int]:
|
|
209
207
|
"""
|
|
210
|
-
Retrieves the specified OEIS sequence as a dictionary mapping integer indices
|
|
211
|
-
to their corresponding values.
|
|
208
|
+
Retrieves the specified OEIS sequence as a dictionary mapping integer indices to their corresponding values.
|
|
212
209
|
|
|
213
|
-
This function checks for a cached local copy of the sequence data, using it if
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
mapping each index to its sequence value.
|
|
210
|
+
This function checks for a cached local copy of the sequence data, using it if it has not expired. Otherwise, it
|
|
211
|
+
fetches the sequence data from the OEIS website and writes it to the cache. The parsed data is returned as a
|
|
212
|
+
dictionary mapping each index to its sequence value.
|
|
217
213
|
|
|
218
214
|
Parameters:
|
|
219
215
|
oeisID: The identifier of the OEIS sequence to retrieve.
|
|
220
216
|
Returns:
|
|
221
|
-
OEISsequence: A dictionary where each key is an integer index, `n`, and each
|
|
222
|
-
|
|
217
|
+
OEISsequence: A dictionary where each key is an integer index, `n`, and each value is the corresponding `a(n)`
|
|
218
|
+
from the OEIS entry.
|
|
223
219
|
Raises:
|
|
224
|
-
ValueError: If the cached or downloaded file format is invalid.
|
|
225
|
-
|
|
220
|
+
ValueError: If the cached or downloaded file format is invalid. IOError: If there is an error reading from or
|
|
221
|
+
writing to the local cache.
|
|
226
222
|
"""
|
|
227
223
|
|
|
228
224
|
pathFilenameCache: Path = pathCache / getFilenameOEISbFile(oeisID)
|
|
@@ -238,23 +234,19 @@ def getOEISidInformation(oeisID: str) -> tuple[str, int]:
|
|
|
238
234
|
"""
|
|
239
235
|
Retrieve the description and offset for an OEIS sequence.
|
|
240
236
|
|
|
241
|
-
This function fetches the metadata for a given OEIS sequence ID, including
|
|
242
|
-
|
|
243
|
-
to avoid redundant network requests while ensuring data freshness.
|
|
237
|
+
This function fetches the metadata for a given OEIS sequence ID, including its textual description and index offset
|
|
238
|
+
value. It uses a caching mechanism to avoid redundant network requests while ensuring data freshness.
|
|
244
239
|
|
|
245
240
|
Parameters:
|
|
246
241
|
oeisID: The OEIS sequence identifier to retrieve information for.
|
|
247
242
|
|
|
248
243
|
Returns:
|
|
249
|
-
A tuple containing:
|
|
250
|
-
|
|
251
|
-
- offset: An integer representing the starting index of the sequence.
|
|
252
|
-
Usually 0 or 1, depending on the mathematical context.
|
|
244
|
+
A tuple containing: - description: A string describing the sequence's mathematical meaning. - offset: An integer
|
|
245
|
+
representing the starting index of the sequence. Usually 0 or 1, depending on the mathematical context.
|
|
253
246
|
|
|
254
247
|
Notes:
|
|
255
|
-
Sequence descriptions are parsed from the machine-readable format of OEIS.
|
|
256
|
-
|
|
257
|
-
fallback values are returned.
|
|
248
|
+
Sequence descriptions are parsed from the machine-readable format of OEIS. If information cannot be retrieved,
|
|
249
|
+
warning messages are issued and fallback values are returned.
|
|
258
250
|
"""
|
|
259
251
|
oeisID = validateOEISid(oeisID)
|
|
260
252
|
pathFilenameCache: Path = pathCache / f"{oeisID}.txt"
|
|
@@ -287,23 +279,23 @@ def getOEISidInformation(oeisID: str) -> tuple[str, int]:
|
|
|
287
279
|
def makeSettingsOEIS() -> dict[str, SettingsOEIS]:
|
|
288
280
|
"""
|
|
289
281
|
Construct the comprehensive settings dictionary for all implemented OEIS sequences.
|
|
290
|
-
|
|
291
|
-
This function builds a complete configuration dictionary for all supported OEIS
|
|
292
|
-
|
|
282
|
+
|
|
283
|
+
This function builds a complete configuration dictionary for all supported OEIS sequences by retrieving and
|
|
284
|
+
combining:
|
|
293
285
|
1. Sequence values from OEIS b-files
|
|
294
286
|
2. Sequence metadata (descriptions and offsets)
|
|
295
287
|
3. Hardcoded mapping functions and test values
|
|
296
|
-
|
|
297
|
-
The resulting dictionary provides a single authoritative source for all OEIS-related
|
|
298
|
-
|
|
288
|
+
|
|
289
|
+
The resulting dictionary provides a single authoritative source for all OEIS-related configurations used throughout
|
|
290
|
+
the package, including:
|
|
299
291
|
- Mathematical descriptions of each sequence
|
|
300
292
|
- Functions to convert between sequence indices and map dimensions
|
|
301
293
|
- Known sequence values retrieved from OEIS
|
|
302
294
|
- Testing and benchmarking reference values
|
|
303
|
-
|
|
295
|
+
|
|
304
296
|
Returns:
|
|
305
|
-
A dictionary mapping OEIS sequence IDs to their complete settings objects,
|
|
306
|
-
|
|
297
|
+
A dictionary mapping OEIS sequence IDs to their complete settings objects, containing all metadata and known
|
|
298
|
+
values needed for computation and validation.
|
|
307
299
|
"""
|
|
308
300
|
settingsTarget: dict[str, SettingsOEIS] = {}
|
|
309
301
|
for oeisID in oeisIDsImplemented:
|
|
@@ -334,29 +326,28 @@ def makeDictionaryFoldsTotalKnown() -> dict[tuple[int, ...], int]:
|
|
|
334
326
|
|
|
335
327
|
for n, foldingsTotal in sequence.items():
|
|
336
328
|
mapShape = settings['getMapShape'](n)
|
|
337
|
-
mapShape = tuple(
|
|
329
|
+
mapShape = tuple(mapShape)
|
|
338
330
|
dictionaryMapDimensionsToFoldsTotalKnown[mapShape] = foldingsTotal
|
|
339
331
|
return dictionaryMapDimensionsToFoldsTotalKnown
|
|
340
332
|
|
|
341
333
|
def getFoldsTotalKnown(mapShape: tuple[int, ...]) -> int:
|
|
342
334
|
"""
|
|
343
335
|
Retrieve the known total number of foldings for a given map shape.
|
|
344
|
-
|
|
345
|
-
This function looks up precalculated folding totals for specific map dimensions
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
336
|
+
|
|
337
|
+
This function looks up precalculated folding totals for specific map dimensions from OEIS sequences. It serves as a
|
|
338
|
+
rapid reference for known values without requiring computation, and can be used to validate algorithm results.
|
|
339
|
+
|
|
349
340
|
Parameters:
|
|
350
341
|
mapShape: A tuple of integers representing the dimensions of the map.
|
|
351
|
-
|
|
342
|
+
|
|
352
343
|
Returns:
|
|
353
|
-
foldingsTotal: The known total number of foldings for the given map shape,
|
|
354
|
-
|
|
355
|
-
|
|
344
|
+
foldingsTotal: The known total number of foldings for the given map shape, or -1 if the map shape doesn't match
|
|
345
|
+
any known values in the OEIS sequences.
|
|
346
|
+
|
|
356
347
|
Notes:
|
|
357
|
-
The function uses a cached dictionary (via makeDictionaryFoldsTotalKnown) to
|
|
358
|
-
|
|
359
|
-
|
|
348
|
+
The function uses a cached dictionary (via makeDictionaryFoldsTotalKnown) to efficiently retrieve values without
|
|
349
|
+
repeatedly parsing OEIS data. Map shape tuples are sorted internally to ensure consistent lookup regardless of
|
|
350
|
+
dimension order.
|
|
360
351
|
"""
|
|
361
352
|
lookupFoldsTotal = makeDictionaryFoldsTotalKnown()
|
|
362
353
|
return lookupFoldsTotal.get(tuple(mapShape), -1)
|
|
@@ -389,15 +380,13 @@ def oeisIDfor_n(oeisID: str, n: int | Any) -> int:
|
|
|
389
380
|
Calculate `a(n)` of a sequence from "The On-Line Encyclopedia of Integer Sequences" (OEIS).
|
|
390
381
|
|
|
391
382
|
Parameters:
|
|
392
|
-
oeisID: The ID of the OEIS sequence.
|
|
393
|
-
n: A non-negative integer for which to calculate the sequence value.
|
|
383
|
+
oeisID: The ID of the OEIS sequence. n: A non-negative integer for which to calculate the sequence value.
|
|
394
384
|
|
|
395
385
|
Returns:
|
|
396
386
|
sequenceValue: `a(n)` of the OEIS sequence.
|
|
397
387
|
|
|
398
388
|
Raises:
|
|
399
|
-
ValueError: If `n` is negative.
|
|
400
|
-
KeyError: If the OEIS sequence ID is not directly implemented.
|
|
389
|
+
ValueError: If `n` is negative. KeyError: If the OEIS sequence ID is not directly implemented.
|
|
401
390
|
"""
|
|
402
391
|
oeisID = validateOEISid(oeisID)
|
|
403
392
|
|
mapFolding/reference/__init__.py
CHANGED
|
@@ -13,8 +13,8 @@ Categories of reference implementations:
|
|
|
13
13
|
- foldings.AA - Reconstructed Atlas Autocode version with corrections
|
|
14
14
|
|
|
15
15
|
2. Direct translations:
|
|
16
|
-
-
|
|
17
|
-
-
|
|
16
|
+
- lunnonWhile.py - Python translation using while loops
|
|
17
|
+
- lunnonNumpy.py - NumPy-based translation with array operations
|
|
18
18
|
|
|
19
19
|
3. Alternative implementations:
|
|
20
20
|
- irvineJavaPort.py - Port from Sean A. Irvine's Java implementation
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
from mapFolding.someAssemblyRequired import ShatteredDataclass, ast_Identifier, parsePathFilename2astModule, str_nameDOTname
|
|
2
|
+
from mapFolding.someAssemblyRequired.toolboxNumba import theNumbaFlow
|
|
3
|
+
from mapFolding.someAssemblyRequired.transformationTools import shatter_dataclassesDOTdataclass
|
|
4
|
+
from mapFolding.theSSOT import ComputationState, DatatypeElephino as TheDatatypeElephino, DatatypeFoldsTotal as TheDatatypeFoldsTotal, DatatypeLeavesTotal as TheDatatypeLeavesTotal
|
|
5
|
+
from mapFolding.toolboxFilesystem import getPathFilenameFoldsTotal, getPathRootJobDEFAULT
|
|
6
|
+
|
|
7
|
+
import dataclasses
|
|
8
|
+
from pathlib import Path, PurePosixPath
|
|
9
|
+
from typing import TypeAlias
|
|
10
|
+
|
|
11
|
+
@dataclasses.dataclass
|
|
12
|
+
class RecipeJob:
|
|
13
|
+
state: ComputationState
|
|
14
|
+
# TODO create function to calculate `foldsTotalEstimated`
|
|
15
|
+
foldsTotalEstimated: int = 0
|
|
16
|
+
shatteredDataclass: ShatteredDataclass = dataclasses.field(default=None, init=True) # pyright: ignore[reportAssignmentType]
|
|
17
|
+
|
|
18
|
+
# ========================================
|
|
19
|
+
# Source
|
|
20
|
+
source_astModule = parsePathFilename2astModule(theNumbaFlow.pathFilenameSequential)
|
|
21
|
+
sourceCountCallable: ast_Identifier = theNumbaFlow.callableSequential
|
|
22
|
+
|
|
23
|
+
sourceLogicalPathModuleDataclass: str_nameDOTname = theNumbaFlow.logicalPathModuleDataclass
|
|
24
|
+
sourceDataclassIdentifier: ast_Identifier = theNumbaFlow.dataclassIdentifier
|
|
25
|
+
sourceDataclassInstance: ast_Identifier = theNumbaFlow.dataclassInstance
|
|
26
|
+
|
|
27
|
+
sourcePathPackage: PurePosixPath | None = theNumbaFlow.pathPackage
|
|
28
|
+
sourcePackageIdentifier: ast_Identifier | None = theNumbaFlow.packageIdentifier
|
|
29
|
+
|
|
30
|
+
# ========================================
|
|
31
|
+
# Filesystem (names of physical objects)
|
|
32
|
+
pathPackage: PurePosixPath | None = None
|
|
33
|
+
pathModule: PurePosixPath | None = PurePosixPath(getPathRootJobDEFAULT())
|
|
34
|
+
""" `pathModule` will override `pathPackage` and `logicalPathRoot`."""
|
|
35
|
+
fileExtension: str = theNumbaFlow.fileExtension
|
|
36
|
+
pathFilenameFoldsTotal: PurePosixPath = dataclasses.field(default=None, init=True) # pyright: ignore[reportAssignmentType]
|
|
37
|
+
|
|
38
|
+
# ========================================
|
|
39
|
+
# Logical identifiers (as opposed to physical identifiers)
|
|
40
|
+
packageIdentifier: ast_Identifier | None = None
|
|
41
|
+
logicalPathRoot: str_nameDOTname | None = None
|
|
42
|
+
""" `logicalPathRoot` likely corresponds to a physical filesystem directory."""
|
|
43
|
+
moduleIdentifier: ast_Identifier = dataclasses.field(default=None, init=True) # pyright: ignore[reportAssignmentType]
|
|
44
|
+
countCallable: ast_Identifier = sourceCountCallable
|
|
45
|
+
dataclassIdentifier: ast_Identifier | None = sourceDataclassIdentifier
|
|
46
|
+
dataclassInstance: ast_Identifier | None = sourceDataclassInstance
|
|
47
|
+
logicalPathModuleDataclass: str_nameDOTname | None = sourceLogicalPathModuleDataclass
|
|
48
|
+
|
|
49
|
+
# ========================================
|
|
50
|
+
# Datatypes
|
|
51
|
+
DatatypeFoldsTotal: TypeAlias = TheDatatypeFoldsTotal
|
|
52
|
+
DatatypeElephino: TypeAlias = TheDatatypeElephino
|
|
53
|
+
DatatypeLeavesTotal: TypeAlias = TheDatatypeLeavesTotal
|
|
54
|
+
|
|
55
|
+
def _makePathFilename(self,
|
|
56
|
+
pathRoot: PurePosixPath | None = None,
|
|
57
|
+
logicalPathINFIX: str_nameDOTname | None = None,
|
|
58
|
+
filenameStem: str | None = None,
|
|
59
|
+
fileExtension: str | None = None,
|
|
60
|
+
) -> PurePosixPath:
|
|
61
|
+
if pathRoot is None:
|
|
62
|
+
pathRoot = self.pathPackage or PurePosixPath(Path.cwd())
|
|
63
|
+
if logicalPathINFIX:
|
|
64
|
+
whyIsThisStillAThing: list[str] = logicalPathINFIX.split('.')
|
|
65
|
+
pathRoot = pathRoot.joinpath(*whyIsThisStillAThing)
|
|
66
|
+
if filenameStem is None:
|
|
67
|
+
filenameStem = self.moduleIdentifier
|
|
68
|
+
if fileExtension is None:
|
|
69
|
+
fileExtension = self.fileExtension
|
|
70
|
+
filename: str = filenameStem + fileExtension
|
|
71
|
+
return pathRoot.joinpath(filename)
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def pathFilenameModule(self) -> PurePosixPath:
|
|
75
|
+
if self.pathModule is None:
|
|
76
|
+
return self._makePathFilename()
|
|
77
|
+
else:
|
|
78
|
+
return self._makePathFilename(pathRoot=self.pathModule, logicalPathINFIX=None)
|
|
79
|
+
|
|
80
|
+
def __post_init__(self):
|
|
81
|
+
pathFilenameFoldsTotal = PurePosixPath(getPathFilenameFoldsTotal(self.state.mapShape))
|
|
82
|
+
|
|
83
|
+
if self.moduleIdentifier is None: # pyright: ignore[reportUnnecessaryComparison]
|
|
84
|
+
self.moduleIdentifier = pathFilenameFoldsTotal.stem
|
|
85
|
+
|
|
86
|
+
if self.pathFilenameFoldsTotal is None: # pyright: ignore[reportUnnecessaryComparison]
|
|
87
|
+
self.pathFilenameFoldsTotal = pathFilenameFoldsTotal
|
|
88
|
+
|
|
89
|
+
if self.shatteredDataclass is None and self.logicalPathModuleDataclass and self.dataclassIdentifier and self.dataclassInstance: # pyright: ignore[reportUnnecessaryComparison]
|
|
90
|
+
self.shatteredDataclass = shatter_dataclassesDOTdataclass(self.logicalPathModuleDataclass, self.dataclassIdentifier, self.dataclassInstance)
|
|
91
|
+
|
|
92
|
+
# ========================================
|
|
93
|
+
# Fields you probably don't need =================================
|
|
94
|
+
# Dispatcher =================================
|
|
95
|
+
sourceDispatcherCallable: ast_Identifier = theNumbaFlow.callableDispatcher
|
|
96
|
+
dispatcherCallable: ast_Identifier = sourceDispatcherCallable
|
|
97
|
+
# Parallel counting =================================
|
|
98
|
+
sourceDataclassInstanceTaskDistribution: ast_Identifier = theNumbaFlow.dataclassInstanceTaskDistribution
|
|
99
|
+
sourceConcurrencyManagerNamespace: ast_Identifier = theNumbaFlow.concurrencyManagerNamespace
|
|
100
|
+
sourceConcurrencyManagerIdentifier: ast_Identifier = theNumbaFlow.concurrencyManagerIdentifier
|
|
101
|
+
dataclassInstanceTaskDistribution: ast_Identifier = sourceDataclassInstanceTaskDistribution
|
|
102
|
+
concurrencyManagerNamespace: ast_Identifier = sourceConcurrencyManagerNamespace
|
|
103
|
+
concurrencyManagerIdentifier: ast_Identifier = sourceConcurrencyManagerIdentifier
|
|
@@ -48,40 +48,42 @@ to verify correctness at each transformation stage through the integrated test s
|
|
|
48
48
|
"""
|
|
49
49
|
|
|
50
50
|
from mapFolding.someAssemblyRequired._theTypes import (
|
|
51
|
-
ast_expr_Slice,
|
|
52
|
-
ast_Identifier,
|
|
53
|
-
astClassHasDOTnameNotName,
|
|
54
|
-
astClassHasDOTtarget,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
astClassOptionallyHasDOTnameNotName,
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
51
|
+
ast_expr_Slice as ast_expr_Slice,
|
|
52
|
+
ast_Identifier as ast_Identifier,
|
|
53
|
+
astClassHasDOTnameNotName as astClassHasDOTnameNotName,
|
|
54
|
+
astClassHasDOTtarget as astClassHasDOTtarget,
|
|
55
|
+
astClassHasDOTtarget_expr as astClassHasDOTtarget_expr,
|
|
56
|
+
astClassHasDOTtargetAttributeNameSubscript as astClassHasDOTtargetAttributeNameSubscript,
|
|
57
|
+
astClassHasDOTvalue as astClassHasDOTvalue,
|
|
58
|
+
astClassHasDOTvalue_expr as astClassHasDOTvalue_expr,
|
|
59
|
+
astClassHasDOTvalue_exprNone as astClassHasDOTvalue_exprNone,
|
|
60
|
+
astClassOptionallyHasDOTnameNotName as astClassOptionallyHasDOTnameNotName,
|
|
61
|
+
ImaCallToName as ImaCallToName,
|
|
62
|
+
intORlist_ast_type_paramORstr_orNone as intORlist_ast_type_paramORstr_orNone,
|
|
63
|
+
intORstr_orNone as intORstr_orNone,
|
|
64
|
+
list_ast_type_paramORstr_orNone as list_ast_type_paramORstr_orNone,
|
|
65
|
+
NodeORattribute as NodeORattribute,
|
|
66
|
+
str_nameDOTname as str_nameDOTname,
|
|
67
|
+
个 as 个,
|
|
66
68
|
)
|
|
67
69
|
|
|
68
70
|
from mapFolding.someAssemblyRequired._toolboxPython import (
|
|
69
|
-
importLogicalPath2Callable,
|
|
70
|
-
importPathFilename2Callable,
|
|
71
|
-
NodeChanger,
|
|
72
|
-
NodeTourist,
|
|
73
|
-
parseLogicalPath2astModule,
|
|
74
|
-
parsePathFilename2astModule,
|
|
71
|
+
importLogicalPath2Callable as importLogicalPath2Callable,
|
|
72
|
+
importPathFilename2Callable as importPathFilename2Callable,
|
|
73
|
+
NodeChanger as NodeChanger,
|
|
74
|
+
NodeTourist as NodeTourist,
|
|
75
|
+
parseLogicalPath2astModule as parseLogicalPath2astModule,
|
|
76
|
+
parsePathFilename2astModule as parsePathFilename2astModule,
|
|
75
77
|
)
|
|
76
78
|
|
|
77
|
-
from mapFolding.someAssemblyRequired._toolboxAntecedents import DOT, ifThis
|
|
78
|
-
from mapFolding.someAssemblyRequired._tool_Make import Make
|
|
79
|
-
from mapFolding.someAssemblyRequired._tool_Then import grab, Then
|
|
79
|
+
from mapFolding.someAssemblyRequired._toolboxAntecedents import be as be, DOT as DOT, ifThis as ifThis
|
|
80
|
+
from mapFolding.someAssemblyRequired._tool_Make import Make as Make
|
|
81
|
+
from mapFolding.someAssemblyRequired._tool_Then import grab as grab, Then as Then
|
|
80
82
|
|
|
81
83
|
from mapFolding.someAssemblyRequired._toolboxContainers import (
|
|
82
|
-
IngredientsFunction,
|
|
83
|
-
IngredientsModule,
|
|
84
|
-
LedgerOfImports,
|
|
85
|
-
RecipeSynthesizeFlow,
|
|
86
|
-
ShatteredDataclass,
|
|
84
|
+
IngredientsFunction as IngredientsFunction,
|
|
85
|
+
IngredientsModule as IngredientsModule,
|
|
86
|
+
LedgerOfImports as LedgerOfImports,
|
|
87
|
+
RecipeSynthesizeFlow as RecipeSynthesizeFlow,
|
|
88
|
+
ShatteredDataclass as ShatteredDataclass,
|
|
87
89
|
)
|
|
@@ -13,10 +13,17 @@ else:
|
|
|
13
13
|
astClassHasDOTnameNotName = stuPyd
|
|
14
14
|
astClassHasDOTvalue_expr = stuPyd
|
|
15
15
|
|
|
16
|
+
class ImaCallToName(ast.Call):
|
|
17
|
+
func: ast.Name # pyright: ignore[reportIncompatibleVariableOverride]
|
|
18
|
+
# assert isinstance(ast.Call.func, ast.Name), "brinksmanship"
|
|
19
|
+
# func: ast.Name
|
|
20
|
+
|
|
16
21
|
astClassHasDOTtargetAttributeNameSubscript: typing_TypeAlias = ast.AnnAssign | ast.AugAssign
|
|
17
22
|
astClassHasDOTtarget_expr: typing_TypeAlias = ast.AsyncFor | ast.comprehension | ast.For
|
|
18
23
|
astClassHasDOTtarget: typing_TypeAlias = ast.NamedExpr | astClassHasDOTtarget_expr | astClassHasDOTtargetAttributeNameSubscript
|
|
24
|
+
|
|
19
25
|
astClassOptionallyHasDOTnameNotName: typing_TypeAlias = ast.ExceptHandler | ast.MatchAs | ast.MatchStar
|
|
26
|
+
|
|
20
27
|
astClassHasDOTvalue_exprNone: typing_TypeAlias = ast.AnnAssign | ast.Return | ast.Yield
|
|
21
28
|
astClassHasDOTvalue: typing_TypeAlias = ast.Constant | ast.MatchSingleton | astClassHasDOTvalue_expr | astClassHasDOTvalue_exprNone
|
|
22
29
|
|
|
@@ -27,7 +34,8 @@ intORstr_orNone: typing_TypeAlias = Any
|
|
|
27
34
|
list_ast_type_paramORstr_orNone: typing_TypeAlias = Any
|
|
28
35
|
str_nameDOTname: typing_TypeAlias = stuPyd
|
|
29
36
|
|
|
30
|
-
个 = typing_TypeVar('个', bound= ast.AST, covariant=True)
|
|
37
|
+
个 = typing_TypeVar('个', bound = ast.AST, covariant = True)
|
|
38
|
+
NodeORattribute = typing_TypeVar('NodeORattribute', bound = ast.AST | ast_expr_Slice | ast_Identifier | str_nameDOTname | bool | Any | None, covariant = True)
|
|
31
39
|
|
|
32
40
|
# All ast classes by subgroup:
|
|
33
41
|
Ima_ast_boolop: typing_TypeAlias = ast.boolop | ast.And | ast.Or
|
|
@@ -56,7 +56,7 @@ class Make:
|
|
|
56
56
|
return ast.arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults, kwarg, defaults)
|
|
57
57
|
|
|
58
58
|
@staticmethod
|
|
59
|
-
def Assign(listTargets:
|
|
59
|
+
def Assign(listTargets: list[ast.expr], value: ast.expr, **keywordArguments: intORstr_orNone) -> ast.Assign:
|
|
60
60
|
return ast.Assign(listTargets, value, **keywordArguments)
|
|
61
61
|
|
|
62
62
|
@staticmethod
|
|
@@ -83,7 +83,6 @@ class Make:
|
|
|
83
83
|
|
|
84
84
|
@staticmethod
|
|
85
85
|
def Constant(value: Any, **keywordArguments: intORstr_orNone) -> ast.Constant:
|
|
86
|
-
"""value: str|int|float|bool|None|bytes|bytearray|memoryview|complex|list|tuple|dict|set, or any other type that can be represented as a constant in Python."""
|
|
87
86
|
return ast.Constant(value, **keywordArguments)
|
|
88
87
|
|
|
89
88
|
@staticmethod
|
|
@@ -15,7 +15,7 @@ once they have been identified using predicate functions from ifThis.
|
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
17
|
from collections.abc import Callable, Sequence
|
|
18
|
-
from mapFolding.someAssemblyRequired import ast_Identifier, astClassHasDOTvalue
|
|
18
|
+
from mapFolding.someAssemblyRequired import ast_Identifier, astClassHasDOTvalue, ImaCallToName, NodeORattribute
|
|
19
19
|
from typing import Any
|
|
20
20
|
import ast
|
|
21
21
|
|
|
@@ -46,6 +46,13 @@ class grab:
|
|
|
46
46
|
return node
|
|
47
47
|
return workhorse
|
|
48
48
|
|
|
49
|
+
@staticmethod
|
|
50
|
+
def funcDOTidAttribute(action: Callable[[ast_Identifier], Any]) -> Callable[[ImaCallToName], ImaCallToName]:
|
|
51
|
+
def workhorse(node: ImaCallToName) -> ImaCallToName:
|
|
52
|
+
node.func = grab.idAttribute(action)(node.func)
|
|
53
|
+
return node
|
|
54
|
+
return workhorse
|
|
55
|
+
|
|
49
56
|
@staticmethod
|
|
50
57
|
def idAttribute(action: Callable[[ast_Identifier], ast_Identifier]) -> Callable[[ast.Name], ast.Name]:
|
|
51
58
|
def workhorse(node: ast.Name) -> ast.Name:
|
|
@@ -54,7 +61,7 @@ class grab:
|
|
|
54
61
|
return workhorse
|
|
55
62
|
|
|
56
63
|
@staticmethod
|
|
57
|
-
def valueAttribute(action: Callable[[Any
|
|
64
|
+
def valueAttribute(action: Callable[[Any], Any]) -> Callable[[astClassHasDOTvalue], astClassHasDOTvalue]:
|
|
58
65
|
def workhorse(node: astClassHasDOTvalue) -> astClassHasDOTvalue:
|
|
59
66
|
node.value = action(node.value)
|
|
60
67
|
return node
|
|
@@ -73,14 +80,14 @@ class Then:
|
|
|
73
80
|
pattern-matching-and-action workflow for AST manipulation.
|
|
74
81
|
"""
|
|
75
82
|
@staticmethod
|
|
76
|
-
def appendTo(listOfAny: list[Any]) -> Callable[[ast.AST | ast_Identifier],
|
|
77
|
-
def workhorse(node: ast.AST | ast_Identifier) ->
|
|
83
|
+
def appendTo(listOfAny: list[Any]) -> Callable[[ast.AST | ast_Identifier], ast.AST | ast_Identifier]:
|
|
84
|
+
def workhorse(node: ast.AST | ast_Identifier) -> ast.AST | ast_Identifier:
|
|
78
85
|
listOfAny.append(node)
|
|
79
|
-
return
|
|
86
|
+
return node
|
|
80
87
|
return workhorse
|
|
81
88
|
|
|
82
89
|
@staticmethod
|
|
83
|
-
def extractIt(node:
|
|
90
|
+
def extractIt(node: NodeORattribute) -> NodeORattribute:
|
|
84
91
|
return node
|
|
85
92
|
|
|
86
93
|
@staticmethod
|
|
@@ -92,10 +99,11 @@ class Then:
|
|
|
92
99
|
return lambda belowMe: [belowMe, *list_astAST]
|
|
93
100
|
|
|
94
101
|
@staticmethod
|
|
95
|
-
def removeIt(
|
|
102
|
+
def removeIt(_removeMe: ast.AST) -> None:
|
|
103
|
+
return None
|
|
96
104
|
|
|
97
105
|
@staticmethod
|
|
98
|
-
def replaceWith(astAST:
|
|
106
|
+
def replaceWith(astAST: NodeORattribute) -> Callable[[NodeORattribute], NodeORattribute]:
|
|
99
107
|
return lambda _replaceMe: astAST
|
|
100
108
|
|
|
101
109
|
@staticmethod
|