mapFolding 0.8.2__py3-none-any.whl → 0.8.4__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 (37) hide show
  1. mapFolding/__init__.py +6 -2
  2. mapFolding/basecamp.py +11 -5
  3. mapFolding/filesystem.py +134 -109
  4. mapFolding/oeis.py +1 -1
  5. mapFolding/reference/__init__.py +7 -0
  6. mapFolding/reference/jobsCompleted/[2x19]/p2x19.py +197 -0
  7. mapFolding/reference/jobsCompleted/__init__.py +50 -0
  8. mapFolding/reference/jobsCompleted/p2x19/p2x19.py +29 -0
  9. mapFolding/someAssemblyRequired/__init__.py +37 -18
  10. mapFolding/someAssemblyRequired/_theTypes.py +35 -0
  11. mapFolding/someAssemblyRequired/_tool_Make.py +92 -0
  12. mapFolding/someAssemblyRequired/_tool_Then.py +65 -0
  13. mapFolding/someAssemblyRequired/_toolboxAntecedents.py +326 -0
  14. mapFolding/someAssemblyRequired/_toolboxContainers.py +306 -0
  15. mapFolding/someAssemblyRequired/_toolboxPython.py +76 -0
  16. mapFolding/someAssemblyRequired/getLLVMforNoReason.py +20 -1
  17. mapFolding/someAssemblyRequired/ingredientsNumba.py +17 -24
  18. mapFolding/someAssemblyRequired/synthesizeNumbaFlow.py +112 -149
  19. mapFolding/someAssemblyRequired/synthesizeNumbaJob.py +247 -0
  20. mapFolding/someAssemblyRequired/transformDataStructures.py +167 -100
  21. mapFolding/someAssemblyRequired/transformationTools.py +63 -678
  22. mapFolding/syntheticModules/__init__.py +1 -0
  23. mapFolding/syntheticModules/numbaCount_doTheNeedful.py +36 -33
  24. mapFolding/theDao.py +13 -11
  25. mapFolding/theSSOT.py +69 -119
  26. {mapfolding-0.8.2.dist-info → mapfolding-0.8.4.dist-info}/METADATA +4 -2
  27. mapfolding-0.8.4.dist-info/RECORD +49 -0
  28. {mapfolding-0.8.2.dist-info → mapfolding-0.8.4.dist-info}/WHEEL +1 -1
  29. tests/conftest.py +34 -29
  30. tests/test_computations.py +40 -31
  31. tests/test_filesystem.py +3 -3
  32. tests/test_other.py +4 -3
  33. mapFolding/someAssemblyRequired/synthesizeNumbaJobVESTIGIAL.py +0 -413
  34. mapfolding-0.8.2.dist-info/RECORD +0 -39
  35. {mapfolding-0.8.2.dist-info → mapfolding-0.8.4.dist-info}/entry_points.txt +0 -0
  36. {mapfolding-0.8.2.dist-info → mapfolding-0.8.4.dist-info}/licenses/LICENSE +0 -0
  37. {mapfolding-0.8.2.dist-info → mapfolding-0.8.4.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,29 @@
1
+ from numba import uint8,jit,int64
2
+ from numpy import uint8
3
+ from numpy import array
4
+ @jit(int64(),_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)
5
+ def countSequential()->int64:
6
+ groupsOfFolds=int64(0);leafAbove=array([1,2]+[0]*37,dtype=uint8);countDimensionsGapped=array([0]*39,dtype=uint8);gapRangeStart=array([0]*2+[1]+[0]*36,dtype=uint8);leafBelow=array([2,0,1]+[0]*36,dtype=uint8);gap1ndex=uint8(1);indexMiniGap=uint8(2);leafConnectee=uint8(2);indexDimension=uint8(2);gap1ndexCeiling=uint8(2);dimensionsUnconstrained=uint8(1);leaf1ndex=uint8(3);gapsWhere=array([1]+[0]*1444,dtype=uint8);connectionGraph=array([[[0]*39,[0,1]+[0]*37,[0,2,1]+[0]*36,[0,1,2,3]+[0]*35,[0,2,1,4,3]+[0]*34,[*range(0,6)]+[0]*33,[0,2,1,4,3,6,5]+[0]*32,[*range(0,8)]+[0]*31,[0,2,1,4,3,6,5,8,7]+[0]*30,[*range(0,10)]+[0]*29,[0,2,1,4,3,6,5,8,7,10,9]+[0]*28,[*range(0,12)]+[0]*27,[0,2,1,4,3,6,5,8,7,10,9,12,11]+[0]*26,[*range(0,14)]+[0]*25,[0,2,1,4,3,6,5,8,7,10,9,12,11,14,13]+[0]*24,[*range(0,16)]+[0]*23,[0,2,1,4,3,6,5,8,7,10,9,12,11,14,13,16,15]+[0]*22,[*range(0,18)]+[0]*21,[0,2,1,4,3,6,5,8,7,10,9,12,11,14,13,16,15,18,17]+[0]*20,[*range(0,20)]+[0]*19,[0,2,1,4,3,6,5,8,7,10,9,12,11,14,13,16,15,18,17,20,19]+[0]*18,[*range(0,22)]+[0]*17,[0,2,1,4,3,6,5,8,7,10,9,12,11,14,13,16,15,18,17,20,19,22,21]+[0]*16,[*range(0,24)]+[0]*15,[0,2,1,4,3,6,5,8,7,10,9,12,11,14,13,16,15,18,17,20,19,22,21,24,23]+[0]*14,[*range(0,26)]+[0]*13,[0,2,1,4,3,6,5,8,7,10,9,12,11,14,13,16,15,18,17,20,19,22,21,24,23,26,25]+[0]*12,[*range(0,28)]+[0]*11,[0,2,1,4,3,6,5,8,7,10,9,12,11,14,13,16,15,18,17,20,19,22,21,24,23,26,25,28,27]+[0]*10,[*range(0,30)]+[0]*9,[0,2,1,4,3,6,5,8,7,10,9,12,11,14,13,16,15,18,17,20,19,22,21,24,23,26,25,28,27,30,29]+[0]*8,[*range(0,32)]+[0]*7,[0,2,1,4,3,6,5,8,7,10,9,12,11,14,13,16,15,18,17,20,19,22,21,24,23,26,25,28,27,30,29,32,31]+[0]*6,[*range(0,34)]+[0]*5,[0,2,1,4,3,6,5,8,7,10,9,12,11,14,13,16,15,18,17,20,19,22,21,24,23,26,25,28,27,30,29,32,31,34,33]+[0]*4,[*range(0,36)]+[0]*3,[0,2,1,4,3,6,5,8,7,10,9,12,11,14,13,16,15,18,17,20,19,22,21,24,23,26,25,28,27,30,29,32,31,34,33,36,35]+[0]*2,[*range(0,38),0],[0,2,1,4,3,6,5,8,7,10,9,12,11,14,13,16,15,18,17,20,19,22,21,24,23,26,25,28,27,30,29,32,31,34,33,36,35,38,37]],[[0]*39,[0,1]+[0]*37,[0,1,2]+[0]*36,[0,3,2,1]+[0]*35,[0,3,4,1,2]+[0]*34,[0,1,2,5,4,3]+[0]*33,[0,1,2,5,6,3,4]+[0]*32,[0,3,4,1,2,7,6,5]+[0]*31,[0,3,4,1,2,7,8,5,6]+[0]*30,[0,1,2,5,6,3,4,9,8,7]+[0]*29,[0,1,2,5,6,3,4,9,10,7,8]+[0]*28,[0,3,4,1,2,7,8,5,6,11,10,9]+[0]*27,[0,3,4,1,2,7,8,5,6,11,12,9,10]+[0]*26,[0,1,2,5,6,3,4,9,10,7,8,13,12,11]+[0]*25,[0,1,2,5,6,3,4,9,10,7,8,13,14,11,12]+[0]*24,[0,3,4,1,2,7,8,5,6,11,12,9,10,15,14,13]+[0]*23,[0,3,4,1,2,7,8,5,6,11,12,9,10,15,16,13,14]+[0]*22,[0,1,2,5,6,3,4,9,10,7,8,13,14,11,12,17,16,15]+[0]*21,[0,1,2,5,6,3,4,9,10,7,8,13,14,11,12,17,18,15,16]+[0]*20,[0,3,4,1,2,7,8,5,6,11,12,9,10,15,16,13,14,19,18,17]+[0]*19,[0,3,4,1,2,7,8,5,6,11,12,9,10,15,16,13,14,19,20,17,18]+[0]*18,[0,1,2,5,6,3,4,9,10,7,8,13,14,11,12,17,18,15,16,21,20,19]+[0]*17,[0,1,2,5,6,3,4,9,10,7,8,13,14,11,12,17,18,15,16,21,22,19,20]+[0]*16,[0,3,4,1,2,7,8,5,6,11,12,9,10,15,16,13,14,19,20,17,18,23,22,21]+[0]*15,[0,3,4,1,2,7,8,5,6,11,12,9,10,15,16,13,14,19,20,17,18,23,24,21,22]+[0]*14,[0,1,2,5,6,3,4,9,10,7,8,13,14,11,12,17,18,15,16,21,22,19,20,25,24,23]+[0]*13,[0,1,2,5,6,3,4,9,10,7,8,13,14,11,12,17,18,15,16,21,22,19,20,25,26,23,24]+[0]*12,[0,3,4,1,2,7,8,5,6,11,12,9,10,15,16,13,14,19,20,17,18,23,24,21,22,27,26,25]+[0]*11,[0,3,4,1,2,7,8,5,6,11,12,9,10,15,16,13,14,19,20,17,18,23,24,21,22,27,28,25,26]+[0]*10,[0,1,2,5,6,3,4,9,10,7,8,13,14,11,12,17,18,15,16,21,22,19,20,25,26,23,24,29,28,27]+[0]*9,[0,1,2,5,6,3,4,9,10,7,8,13,14,11,12,17,18,15,16,21,22,19,20,25,26,23,24,29,30,27,28]+[0]*8,[0,3,4,1,2,7,8,5,6,11,12,9,10,15,16,13,14,19,20,17,18,23,24,21,22,27,28,25,26,31,30,29]+[0]*7,[0,3,4,1,2,7,8,5,6,11,12,9,10,15,16,13,14,19,20,17,18,23,24,21,22,27,28,25,26,31,32,29,30]+[0]*6,[0,1,2,5,6,3,4,9,10,7,8,13,14,11,12,17,18,15,16,21,22,19,20,25,26,23,24,29,30,27,28,33,32,31]+[0]*5,[0,1,2,5,6,3,4,9,10,7,8,13,14,11,12,17,18,15,16,21,22,19,20,25,26,23,24,29,30,27,28,33,34,31,32]+[0]*4,[0,3,4,1,2,7,8,5,6,11,12,9,10,15,16,13,14,19,20,17,18,23,24,21,22,27,28,25,26,31,32,29,30,35,34,33]+[0]*3,[0,3,4,1,2,7,8,5,6,11,12,9,10,15,16,13,14,19,20,17,18,23,24,21,22,27,28,25,26,31,32,29,30,35,36,33,34]+[0]*2,[0,1,2,5,6,3,4,9,10,7,8,13,14,11,12,17,18,15,16,21,22,19,20,25,26,23,24,29,30,27,28,33,34,31,32,37,36,35,0],[0,1,2,5,6,3,4,9,10,7,8,13,14,11,12,17,18,15,16,21,22,19,20,25,26,23,24,29,30,27,28,33,34,31,32,37,38,35,36]]],dtype=uint8)
7
+ while leaf1ndex:
8
+ if leaf1ndex<=1 or leafBelow[0]==1:
9
+ if leaf1ndex>38:groupsOfFolds+=1
10
+ else:
11
+ dimensionsUnconstrained=2;gap1ndexCeiling=gapRangeStart[leaf1ndex-1];indexDimension=0
12
+ while indexDimension<2:
13
+ if connectionGraph[indexDimension,leaf1ndex,leaf1ndex]==leaf1ndex:dimensionsUnconstrained-=1
14
+ else:
15
+ leafConnectee=connectionGraph[indexDimension,leaf1ndex,leaf1ndex]
16
+ while leafConnectee!=leaf1ndex:
17
+ gapsWhere[gap1ndexCeiling]=leafConnectee
18
+ if countDimensionsGapped[leafConnectee]==0:gap1ndexCeiling+=1
19
+ countDimensionsGapped[leafConnectee]+=1;leafConnectee=connectionGraph[indexDimension,leaf1ndex,leafBelow[leafConnectee]]
20
+ indexDimension+=1
21
+ indexMiniGap=gap1ndex
22
+ while indexMiniGap<gap1ndexCeiling:
23
+ gapsWhere[gap1ndex]=gapsWhere[indexMiniGap]
24
+ if countDimensionsGapped[gapsWhere[indexMiniGap]]==dimensionsUnconstrained:gap1ndex+=1
25
+ countDimensionsGapped[gapsWhere[indexMiniGap]]=0;indexMiniGap+=1
26
+ while leaf1ndex and gap1ndex==gapRangeStart[leaf1ndex-1]:leaf1ndex-=1;leafBelow[leafAbove[leaf1ndex]]=leafBelow[leaf1ndex];leafAbove[leafBelow[leaf1ndex]]=leafAbove[leaf1ndex]
27
+ if leaf1ndex:gap1ndex-=1;leafAbove[leaf1ndex]=gapsWhere[gap1ndex];leafBelow[leaf1ndex]=leafBelow[leafAbove[leaf1ndex]];leafBelow[leafAbove[leaf1ndex]]=leaf1ndex;leafAbove[leafBelow[leaf1ndex]]=leaf1ndex;gapRangeStart[leaf1ndex]=gap1ndex;leaf1ndex+=1
28
+ return groupsOfFolds*38
29
+ if __name__=='__main__':import time;timeStart=time.perf_counter();foldsTotal=countSequential();print(foldsTotal,time.perf_counter()-timeStart);writeStream=open('C:/apps/mapFolding/mapFolding/jobs/p2x19.foldsTotal','w');writeStream.write(str(foldsTotal));writeStream.close()
@@ -24,23 +24,42 @@ These tools were developed for map folding computation optimization but are desi
24
24
  general-purpose utilities applicable to a wide range of code transformation scenarios,
25
25
  particularly for numerically-intensive algorithms that benefit from just-in-time compilation.
26
26
  """
27
+ from mapFolding.someAssemblyRequired._theTypes import (
28
+ ast_expr_Slice,
29
+ ast_Identifier,
30
+ ImaAnnotationType,
31
+ astClassHasDOTnameNotName,
32
+ astClassHasDOTnameNotNameOptional,
33
+ astClassHasDOTtarget,
34
+ astClassHasDOTvalue,
35
+ astMosDef,
36
+ intORlist_ast_type_paramORstr_orNone,
37
+ intORstr_orNone,
38
+ list_ast_type_paramORstr_orNone,
39
+ str_nameDOTname,
40
+ typeCertified,
41
+ )
42
+
43
+ from mapFolding.someAssemblyRequired._toolboxPython import (
44
+ importLogicalPath2Callable,
45
+ importPathFilename2Callable,
46
+ NodeChanger,
47
+ NodeTourist,
48
+ parseLogicalPath2astModule,
49
+ parsePathFilename2astModule,
50
+ )
51
+
52
+ from mapFolding.someAssemblyRequired._toolboxAntecedents import be, ifThis, 又
53
+ from mapFolding.someAssemblyRequired._tool_Make import Make
54
+ from mapFolding.someAssemblyRequired._tool_Then import Then
55
+
27
56
  from mapFolding.someAssemblyRequired.transformationTools import (
28
- ast_Identifier as ast_Identifier,
29
- extractClassDef as extractClassDef,
30
- extractFunctionDef as extractFunctionDef,
31
- ifThis as ifThis,
32
- IngredientsFunction as IngredientsFunction,
33
- IngredientsModule as IngredientsModule,
34
- inlineThisFunctionWithTheseValues as inlineThisFunctionWithTheseValues,
35
- LedgerOfImports as LedgerOfImports,
36
- Make as Make,
37
- makeDictionaryReplacementStatements as makeDictionaryReplacementStatements,
38
- NodeCollector as NodeCollector,
39
- NodeReplacer as NodeReplacer,
40
- RecipeSynthesizeFlow as RecipeSynthesizeFlow,
41
- strDotStrCuzPyStoopid as strDotStrCuzPyStoopid,
42
- Then as Then,
43
- write_astModule as write_astModule,
44
- Z0Z_executeActionUnlessDescendantMatches as Z0Z_executeActionUnlessDescendantMatches,
45
- Z0Z_replaceMatchingASTnodes as Z0Z_replaceMatchingASTnodes,
57
+ dictionaryEstimates,
58
+ extractClassDef,
59
+ extractFunctionDef,
60
+ write_astModule,
61
+ Z0Z_executeActionUnlessDescendantMatches,
62
+ Z0Z_inlineThisFunctionWithTheseValues,
63
+ Z0Z_lameFindReplace,
64
+ Z0Z_makeDictionaryReplacementStatements,
46
65
  )
@@ -0,0 +1,35 @@
1
+ """
2
+ Type definitions used across the AST transformation modules.
3
+
4
+ This module provides type aliases and variables used in AST manipulation,
5
+ centralizing type definitions to prevent circular imports.
6
+ """
7
+ from typing import Any, TYPE_CHECKING, TypeAlias as typing_TypeAlias, TypeVar as typing_TypeVar
8
+ import ast
9
+
10
+ stuPyd: typing_TypeAlias = str
11
+
12
+ if TYPE_CHECKING:
13
+ astClassHasDOTnameNotName: typing_TypeAlias = ast.alias | ast.AsyncFunctionDef | ast.ClassDef | ast.FunctionDef | ast.ParamSpec | ast.TypeVar | ast.TypeVarTuple
14
+ astClassHasDOTnameNotNameOptional: typing_TypeAlias = astClassHasDOTnameNotName | ast.ExceptHandler | ast.MatchAs | ast.MatchStar | None
15
+ astClassHasDOTtarget: typing_TypeAlias = ast.AnnAssign | ast.AsyncFor | ast.AugAssign | ast.comprehension | ast.For | ast.NamedExpr
16
+ astClassHasDOTvalue: typing_TypeAlias = ast.AnnAssign | ast.Assign | ast.Attribute | ast.AugAssign | ast.Await | ast.Constant | ast.DictComp | ast.Expr | ast.FormattedValue | ast.keyword | ast.MatchValue | ast.NamedExpr | ast.Return | ast.Starred | ast.Subscript | ast.TypeAlias | ast.Yield | ast.YieldFrom
17
+ else:
18
+ astClassHasDOTnameNotName = stuPyd
19
+ astClassHasDOTnameNotNameOptional = stuPyd
20
+ astClassHasDOTtarget = stuPyd
21
+ astClassHasDOTvalue = stuPyd
22
+
23
+ ast_expr_Slice: typing_TypeAlias = ast.expr
24
+ ast_Identifier: typing_TypeAlias = str
25
+ intORlist_ast_type_paramORstr_orNone: typing_TypeAlias = Any
26
+ intORstr_orNone: typing_TypeAlias = Any
27
+ list_ast_type_paramORstr_orNone: typing_TypeAlias = Any
28
+ # TODO I am using the moniker `nameDOTname` in two very different ways: differentiate them.
29
+ str_nameDOTname: typing_TypeAlias = stuPyd
30
+ ImaAnnotationType: typing_TypeAlias = ast.Attribute | ast.Constant | ast.Name | ast.Subscript
31
+
32
+ # TODO understand whatever the fuck `typing.TypeVar` is _supposed_ to fucking do.
33
+ typeCertified = typing_TypeVar('typeCertified')
34
+
35
+ astMosDef = typing_TypeVar('astMosDef', bound=astClassHasDOTnameNotName)
@@ -0,0 +1,92 @@
1
+ from collections.abc import Sequence
2
+ from mapFolding.someAssemblyRequired import ast_expr_Slice, ast_Identifier, ImaAnnotationType, intORlist_ast_type_paramORstr_orNone, intORstr_orNone, list_ast_type_paramORstr_orNone
3
+ from typing import Any
4
+ import ast
5
+
6
+ class Make:
7
+ """Almost all parameters described here are only accessible through a method's `**keywordArguments` parameter.
8
+
9
+ Parameters:
10
+ context (ast.Load()): Are you loading from, storing to, or deleting the identifier? The `context` (also, `ctx`) value is `ast.Load()`, `ast.Store()`, or `ast.Del()`.
11
+ col_offset (0): int Position information specifying the column where an AST node begins.
12
+ end_col_offset (None): int|None Position information specifying the column where an AST node ends.
13
+ end_lineno (None): int|None Position information specifying the line number where an AST node ends.
14
+ level (0): int Module import depth level that controls relative vs absolute imports. Default 0 indicates absolute import.
15
+ lineno: int Position information manually specifying the line number where an AST node begins.
16
+ kind (None): str|None Used for type annotations in limited cases.
17
+ type_comment (None): str|None "type_comment is an optional string with the type annotation as a comment." or `# type: ignore`.
18
+ type_params: list[ast.type_param] Type parameters for generic type definitions.
19
+
20
+ The `ast._Attributes`, lineno, col_offset, end_lineno, and end_col_offset, hold position information; however, they are, importantly, _not_ `ast._fields`.
21
+ """
22
+ @staticmethod
23
+ def alias(name: ast_Identifier, asname: ast_Identifier | None = None) -> ast.alias:
24
+ return ast.alias(name, asname)
25
+ @staticmethod
26
+ def AnnAssign(target: ast.Attribute | ast.Name | ast.Subscript, annotation: ImaAnnotationType, value: ast.expr | None = None, **keywordArguments: int) -> ast.AnnAssign: # `simple: int`: uses a clever int-from-boolean to assign the correct value to the `simple` attribute. So, don't make it a method parameter.
27
+ return ast.AnnAssign(target, annotation, value, simple=int(isinstance(target, ast.Name)), **keywordArguments)
28
+ @staticmethod
29
+ def arg(identifier: ast_Identifier, annotation: ast.expr | None = None, **keywordArguments: intORstr_orNone) -> ast.arg:
30
+ return ast.arg(identifier, annotation, **keywordArguments)
31
+ @staticmethod
32
+ def argumentsSpecification(posonlyargs:list[ast.arg]=[], args:list[ast.arg]=[], vararg:ast.arg|None=None, kwonlyargs:list[ast.arg]=[], kw_defaults:list[ast.expr|None]=[None], kwarg:ast.arg|None=None, defaults:list[ast.expr]=[]) -> ast.arguments:
33
+ return ast.arguments(posonlyargs, args, vararg, kwonlyargs, kw_defaults, kwarg, defaults)
34
+ @staticmethod
35
+ def Assign(listTargets: Any, value: ast.expr, **keywordArguments: intORstr_orNone) -> ast.Assign:
36
+ return ast.Assign(listTargets, value, **keywordArguments)
37
+ @staticmethod
38
+ def Attribute(value: ast.expr, *attribute: ast_Identifier, context: ast.expr_context = ast.Load(), **keywordArguments: int) -> ast.Attribute:
39
+ """ If two `ast_Identifier` are joined by a dot `.`, they are _usually_ an `ast.Attribute`, but see `ast.ImportFrom`.
40
+ Parameters:
41
+ value: the part before the dot (Often `ast.Name`, but also `ast.Attribute`, `ast.Starred`, and `ast.Subscript`.)
42
+ attribute: an `ast_Identifier` after a dot `.`; you can pass multiple `attribute` and they will be chained together.
43
+ """
44
+ # TODO confirm the precision of the docstring.
45
+ def addDOTattribute(chain, identifier: ast_Identifier, context: ast.expr_context, **keywordArguments: int) -> ast.Attribute:
46
+ return ast.Attribute(value=chain, attr=identifier, ctx=context, **keywordArguments)
47
+ buffaloBuffalo = addDOTattribute(value, attribute[0], context, **keywordArguments)
48
+ for identifier in attribute[1:None]:
49
+ buffaloBuffalo = addDOTattribute(buffaloBuffalo, identifier, context, **keywordArguments)
50
+ return buffaloBuffalo
51
+ @staticmethod
52
+ # TODO are the types for `callee` comprehensive?
53
+ # TODO is there an easier way to create precise typings for `ast`? I mean, it's a fucking closed system: there should be a lot of mystery involved.
54
+ def Call(callee: ast.Attribute | ast.Name | ast.Subscript, listArguments: Sequence[ast.expr] | None = None, list_astKeywords: Sequence[ast.keyword] | None = None) -> ast.Call:
55
+ return ast.Call(func=callee, args=list(listArguments) if listArguments else [], keywords=list(list_astKeywords) if list_astKeywords else [])
56
+ @staticmethod
57
+ def ClassDef(name: ast_Identifier, listBases: list[ast.expr]=[], list_keyword: list[ast.keyword]=[], body: list[ast.stmt]=[], decorator_list: list[ast.expr]=[], **keywordArguments: list_ast_type_paramORstr_orNone) -> ast.ClassDef:
58
+ return ast.ClassDef(name, listBases, list_keyword, body, decorator_list, **keywordArguments)
59
+ @staticmethod
60
+ def Constant(value: Any, **keywordArguments: intORstr_orNone) -> ast.Constant:
61
+ """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."""
62
+ return ast.Constant(value, **keywordArguments)
63
+ @staticmethod
64
+ def Expr(value: ast.expr, **keywordArguments: int) -> ast.Expr:
65
+ return ast.Expr(value, **keywordArguments)
66
+ @staticmethod
67
+ def FunctionDef(name: ast_Identifier, argumentsSpecification:ast.arguments=ast.arguments(), body:list[ast.stmt]=[], decorator_list:list[ast.expr]=[], returns:ast.expr|None=None, **keywordArguments: intORlist_ast_type_paramORstr_orNone) -> ast.FunctionDef:
68
+ return ast.FunctionDef(name, argumentsSpecification, body, decorator_list, returns, **keywordArguments)
69
+ @staticmethod
70
+ def Import(moduleIdentifier: ast_Identifier, asname: ast_Identifier | None = None, **keywordArguments: int) -> ast.Import:
71
+ return ast.Import(names=[Make.alias(moduleIdentifier, asname)], **keywordArguments)
72
+ @staticmethod
73
+ def ImportFrom(moduleIdentifier: ast_Identifier, list_astAlias: list[ast.alias], **keywordArguments: int) -> ast.ImportFrom:
74
+ return ast.ImportFrom(moduleIdentifier, list_astAlias, **keywordArguments)
75
+ @staticmethod
76
+ def keyword(keywordArgument: ast_Identifier, value: ast.expr, **keywordArguments: int) -> ast.keyword:
77
+ return ast.keyword(arg=keywordArgument, value=value, **keywordArguments)
78
+ @staticmethod
79
+ def Module(body: list[ast.stmt] = [], type_ignores: list[ast.TypeIgnore] = []) -> ast.Module:
80
+ return ast.Module(body, type_ignores)
81
+ @staticmethod
82
+ def Name(identifier: ast_Identifier, context: ast.expr_context = ast.Load(), **keywordArguments: int) -> ast.Name:
83
+ return ast.Name(identifier, context, **keywordArguments)
84
+ @staticmethod
85
+ def Return(value: ast.expr | None = None, **keywordArguments: int) -> ast.Return:
86
+ return ast.Return(value, **keywordArguments)
87
+ @staticmethod
88
+ def Subscript(value: ast.expr, slice: ast_expr_Slice, context: ast.expr_context = ast.Load(), **keywordArguments: int) -> ast.Subscript:
89
+ return ast.Subscript(value, slice, context, **keywordArguments)
90
+ @staticmethod
91
+ def Tuple(elements: Sequence[ast.expr] = [], context: ast.expr_context = ast.Load(), **keywordArguments: int) -> ast.Tuple:
92
+ return ast.Tuple(list(elements), context, **keywordArguments)
@@ -0,0 +1,65 @@
1
+ from collections.abc import Callable, Sequence
2
+ from mapFolding.someAssemblyRequired import ast_Identifier, astClassHasDOTvalue, astMosDef
3
+ from typing import Any
4
+ import ast
5
+
6
+ class Then:
7
+ @staticmethod
8
+ def allOf(listActions: Sequence[Callable[[ast.AST], Any]]) -> Callable[[ast.AST], ast.AST]:
9
+ def workhorse(node: ast.AST) -> ast.AST:
10
+ for action in listActions: action(node)
11
+ return node
12
+ return workhorse
13
+
14
+ @staticmethod
15
+ def appendTo(listOfAny: list[Any]) -> Callable[[ast.AST], None]:
16
+ return lambda node: listOfAny.append(node)
17
+
18
+ @staticmethod
19
+ def DOTarg(action: Callable[[Any], Any]) -> Callable[[ast.arg | ast.keyword], ast.arg | ast.keyword]:
20
+ def workhorse(node: ast.arg | ast.keyword) -> ast.arg | ast.keyword:
21
+ node.arg = action(node.arg)
22
+ return node
23
+ return workhorse
24
+ @staticmethod
25
+ def DOTfunc(action: Callable[[Any], Any]) -> Callable[[ast.Call], ast.Call]:
26
+ def workhorse(node: ast.Call) -> ast.Call:
27
+ node.func = action(node.func)
28
+ return node
29
+ return workhorse
30
+ @staticmethod
31
+ def DOTid(action: Callable[[Any], Any]) -> Callable[[ast.Name], ast.Name]:
32
+ def workhorse(node: ast.Name) -> ast.Name:
33
+ node.id = action(node.id)
34
+ return node
35
+ return workhorse
36
+ @staticmethod
37
+ def DOTtarget(action: Callable[[Any], Any]) -> Callable[[ast.AnnAssign | ast.AugAssign], ast.AnnAssign | ast.AugAssign]:
38
+ def workhorse(node: ast.AnnAssign | ast.AugAssign) -> ast.AnnAssign | ast.AugAssign:
39
+ node.target = action(node.target)
40
+ return node
41
+ return workhorse
42
+ @staticmethod
43
+ def DOTvalue(action: Callable[[Any], Any]) -> Callable[[astClassHasDOTvalue], astClassHasDOTvalue]:
44
+ def workhorse(node: astClassHasDOTvalue) -> astClassHasDOTvalue:
45
+ node.value = action(node.value)
46
+ return node
47
+ return workhorse
48
+
49
+ @staticmethod
50
+ def getIt(node: ast.AST) -> ast.AST | ast_Identifier:
51
+ return node
52
+ @staticmethod
53
+ def insertThisAbove(list_astAST: Sequence[ast.AST]) -> Callable[[ast.AST], Sequence[ast.AST]]:
54
+ return lambda aboveMe: [*list_astAST, aboveMe]
55
+ @staticmethod
56
+ def insertThisBelow(list_astAST: Sequence[ast.AST]) -> Callable[[ast.AST], Sequence[ast.AST]]:
57
+ return lambda belowMe: [belowMe, *list_astAST]
58
+ @staticmethod
59
+ def removeIt(_node: ast.AST) -> None: return None
60
+ @staticmethod
61
+ def replaceWith(astAST: ast.AST | ast_Identifier) -> Callable[[ast.AST], ast.AST | ast_Identifier]:
62
+ return lambda _replaceMe: astAST
63
+ @staticmethod
64
+ def updateThis(dictionaryOf_astMosDef: dict[ast_Identifier, astMosDef]) -> Callable[[astMosDef], astMosDef]:
65
+ return lambda node: dictionaryOf_astMosDef.setdefault(node.name, node)
@@ -0,0 +1,326 @@
1
+ from collections.abc import Callable, Container
2
+ from mapFolding.someAssemblyRequired import ast_expr_Slice, ast_Identifier, astClassHasDOTnameNotName, astClassHasDOTtarget, astClassHasDOTvalue, ImaAnnotationType, typeCertified
3
+ from typing import Any, overload, TypeGuard
4
+ import ast
5
+
6
+ Ima_targetType = ast.AST
7
+
8
+ class 又:
9
+ @staticmethod
10
+ @overload
11
+ def annotation(predicate: Callable[[ImaAnnotationType], ast.AST | ast_Identifier]) -> Callable[[ast.AnnAssign | ast.arg], ast.AST | ast_Identifier]:...
12
+ @staticmethod
13
+ @overload
14
+ def annotation(predicate: Callable[[ImaAnnotationType], TypeGuard[ImaAnnotationType] | bool]) -> Callable[[ast.AnnAssign | ast.arg], TypeGuard[ast.AnnAssign] | TypeGuard[ast.arg] | bool]:...
15
+ @staticmethod
16
+ def annotation(predicate: Callable[[ImaAnnotationType], TypeGuard[ImaAnnotationType] | ast.AST | ast_Identifier | bool]) -> Callable[[ast.AnnAssign | ast.arg], TypeGuard[ast.AnnAssign] | TypeGuard[ast.arg] | ast.AST | ast_Identifier | bool]:
17
+ @overload
18
+ def workhorse(node: ast.AnnAssign | ast.arg) -> ast.AST | ast_Identifier:...
19
+ @overload
20
+ def workhorse(node: ast.AnnAssign | ast.arg) -> TypeGuard[ast.AnnAssign] | TypeGuard[ast.arg] | bool:...
21
+ def workhorse(node: ast.AnnAssign | ast.arg) -> TypeGuard[ast.AnnAssign] | TypeGuard[ast.arg] | ast.AST | ast_Identifier | bool:
22
+ ImaAnnotation = node.annotation
23
+ if ImaAnnotation is None: return False
24
+ assert be.Attribute(ImaAnnotation) or be.Constant(ImaAnnotation) or be.Name(ImaAnnotation) or be.Subscript(ImaAnnotation)
25
+ # assert be.Annotation(ImaAnnotation)
26
+ return predicate(ImaAnnotation)
27
+ return workhorse
28
+ @staticmethod
29
+ @overload
30
+ def arg(predicate: Callable[[ast_Identifier], ast.AST | ast_Identifier]) -> Callable[[ast.arg | ast.keyword], ast.AST | ast_Identifier]:...
31
+ @staticmethod
32
+ @overload
33
+ def arg(predicate: Callable[[ast_Identifier], TypeGuard[ast_Identifier] | bool]) -> Callable[[ast.arg | ast.keyword], TypeGuard[ast.arg] | TypeGuard[ast.keyword] | bool]:...
34
+ @staticmethod
35
+ def arg(predicate: Callable[[ast_Identifier], TypeGuard[ast_Identifier] | ast.AST | ast_Identifier | bool]) -> Callable[[ast.arg | ast.keyword], TypeGuard[ast.arg] | TypeGuard[ast.keyword] | ast.AST | ast_Identifier | bool]:
36
+ @overload
37
+ def workhorse(node: ast.arg | ast.keyword) -> ast.AST | ast_Identifier:...
38
+ @overload
39
+ def workhorse(node: ast.arg | ast.keyword) -> TypeGuard[ast.arg] | TypeGuard[ast.keyword] | bool:...
40
+ def workhorse(node: ast.arg | ast.keyword) -> TypeGuard[ast.arg] | TypeGuard[ast.keyword] | ast.AST | ast_Identifier | bool:
41
+ Ima_arg = node.arg
42
+ if Ima_arg is None: return False
43
+ return predicate(Ima_arg)
44
+ return workhorse
45
+ @staticmethod
46
+ def asname(predicate: Callable[[ast_Identifier | None], TypeGuard[ast_Identifier] | bool]) -> Callable[[ast.alias], TypeGuard[ast.alias] | bool]:
47
+ return lambda node: predicate(node.asname)
48
+ @staticmethod
49
+ def attr(predicate: Callable[[ast_Identifier], TypeGuard[ast_Identifier] | bool]) -> Callable[[ast.Attribute], TypeGuard[ast.Attribute] | bool]:
50
+ return lambda node: predicate(node.attr)
51
+ @staticmethod
52
+ def func(predicate: Callable[[ast.AST], TypeGuard[ast.AST] | bool]) -> Callable[[ast.Call], TypeGuard[ast.Call] | bool]:
53
+ return lambda node: predicate(node.func)
54
+ @staticmethod
55
+ def id(predicate: Callable[[ast_Identifier], TypeGuard[ast_Identifier] | bool]) -> Callable[[ast.Name], TypeGuard[ast.Name] | bool]:
56
+ return lambda node: predicate(node.id)
57
+ @staticmethod
58
+ def module(predicate: Callable[[ast_Identifier | None], TypeGuard[ast_Identifier] | bool]) -> Callable[[ast.ImportFrom], TypeGuard[ast.ImportFrom] | bool]:
59
+ return lambda node: predicate(node.module)
60
+ @staticmethod
61
+ def name(predicate: Callable[[ast_Identifier], TypeGuard[ast_Identifier] | bool]) -> Callable[[astClassHasDOTnameNotName], TypeGuard[astClassHasDOTnameNotName] | bool]:
62
+ return lambda node: predicate(node.name)
63
+ @staticmethod
64
+ def slice(predicate: Callable[[ast_expr_Slice], TypeGuard[ast_expr_Slice] | bool]) -> Callable[[ast.Subscript], TypeGuard[ast.Subscript] | bool]:
65
+ return lambda node: predicate(node.slice)
66
+ @staticmethod
67
+ def target(predicate: Callable[[ast.AST], TypeGuard[ast.AST] | bool]) -> Callable[[astClassHasDOTtarget], TypeGuard[astClassHasDOTtarget] | bool]:
68
+ return lambda node: predicate(node.target)
69
+ @staticmethod
70
+ def value(predicate: Callable[[ast.AST], TypeGuard[ast.AST] | bool]) -> Callable[[astClassHasDOTvalue], TypeGuard[astClassHasDOTvalue] | bool]:
71
+ def workhorse(node: astClassHasDOTvalue) -> TypeGuard[astClassHasDOTvalue] | bool:
72
+ ImaValue = node.value
73
+ if ImaValue is None: return False
74
+ return predicate(ImaValue)
75
+ return workhorse
76
+
77
+ class be:
78
+ @staticmethod
79
+ def _typeCertified(antecedent: type[typeCertified]) -> Callable[[Any | None], TypeGuard[typeCertified]]:
80
+ def workhorse(node: Any | None) -> TypeGuard[typeCertified]:
81
+ return isinstance(node, antecedent)
82
+ return workhorse
83
+ @staticmethod
84
+ def AnnAssign(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.AnnAssign)(node)
85
+ # 'TypeVar "typeCertified" appears only once in generic function signature. Use "object" instead Pylance(reportInvalidTypeVarUse)"' HOW THE FUCK IS THAT INVALID WHEN IT IS WORKING PERFECTLY TO PASS THE TYPE INFORMATION--IN YOUR FUCKING STATIC TYPE CHECKER, PYLANCE!!!! Fuck you, and fuck your pretentious language.
86
+ @staticmethod
87
+ def arg(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.arg)(node)
88
+
89
+ # @staticmethod
90
+ # def Annotation(node: ast.AST) -> TypeGuard[object] | bool:
91
+ # if be.Attribute(node):
92
+ # return be.Attribute(node)
93
+ # elif be.Constant(node):
94
+ # return be.Constant(node)
95
+ # elif be.Name(node):
96
+ # return be.Name(node)
97
+ # elif be.Subscript(node):
98
+ # return be.Subscript(node)
99
+ # else:
100
+ # return False
101
+ # return be.Attribute(node) or be.Constant(node) or be.Name(node) or be.Subscript(node)
102
+
103
+ @staticmethod
104
+ def Assign(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Assign)(node)
105
+ @staticmethod
106
+ def Attribute(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Attribute)(node)
107
+ @staticmethod
108
+ def AugAssign(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.AugAssign)(node)
109
+ @staticmethod
110
+ def BoolOp(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.BoolOp)(node)
111
+ @staticmethod
112
+ def Call(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Call)(node)
113
+ @staticmethod
114
+ def ClassDef(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.ClassDef)(node)
115
+ @staticmethod
116
+ def Compare(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Compare)(node)
117
+ @staticmethod
118
+ def Constant(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Constant)(node)
119
+ @staticmethod
120
+ def Expr(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Expr)(node)
121
+ @staticmethod
122
+ def FunctionDef(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.FunctionDef)(node)
123
+ @staticmethod
124
+ def Import(node: ast.AST) -> TypeGuard[ast.Import]: return be._typeCertified(ast.Import)(node)
125
+ @staticmethod
126
+ def ImportFrom(node: ast.AST) -> TypeGuard[ast.ImportFrom]: return be._typeCertified(ast.ImportFrom)(node)
127
+ @staticmethod
128
+ def keyword(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.keyword)(node)
129
+ @staticmethod
130
+ def Module(node: ast.AST) -> TypeGuard[typeCertified]: return be._typeCertified(ast.Module)(node)
131
+ @staticmethod
132
+ def Name(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Name)(node)
133
+ @staticmethod
134
+ def Return(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Return)(node)
135
+ @staticmethod
136
+ def Starred(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Starred)(node)
137
+ @staticmethod
138
+ def Subscript(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.Subscript)(node)
139
+ @staticmethod
140
+ def UnaryOp(node: ast.AST) -> TypeGuard[object]: return be._typeCertified(ast.UnaryOp)(node)
141
+
142
+ class ifThis:
143
+ @staticmethod
144
+ def equals(this: Any) -> Callable[[Any], TypeGuard[Any] | bool]:
145
+ return lambda node: node == this
146
+ @staticmethod
147
+ def isAssignAndTargets0Is(targets0Predicate: Callable[[ast.AST], bool]) -> Callable[[ast.AST], TypeGuard[object] | bool]:
148
+ """node is Assign and node.targets[0] matches `targets0Predicate`."""
149
+ return lambda node: be.Assign(node) and targets0Predicate(node.targets[0])
150
+ @staticmethod
151
+ def isAssignAndValueIs(valuePredicate: Callable[[ast.AST], bool]) -> Callable[[ast.AST], TypeGuard[object] | bool]:
152
+ """node is ast.Assign and node.value matches `valuePredicate`.
153
+ Parameters:
154
+ valuePredicate: Function that evaluates the value of the assignment
155
+ Returns:
156
+ predicate: matches assignments with values meeting the criteria
157
+ """
158
+ return lambda node: be.Assign(node) and 又.value(valuePredicate)(node)
159
+ @staticmethod
160
+ def isFunctionDef_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
161
+ return lambda node: be.FunctionDef(node) and 又.name(ifThis._Identifier(identifier))(node)
162
+ @staticmethod
163
+ def isArgument_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
164
+ return lambda node: (be.arg(node) or be.keyword(node)) and 又.arg(ifThis._Identifier(identifier))(node)
165
+ @staticmethod
166
+ def is_keyword_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
167
+ """see also `isArgument_Identifier`"""
168
+ return lambda node: be.keyword(node) and 又.arg(ifThis._Identifier(identifier))(node)
169
+ @staticmethod
170
+ def is_arg_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
171
+ """see also `isArgument_Identifier`"""
172
+ return lambda node: be.arg(node) and 又.arg(ifThis._Identifier(identifier))(node)
173
+ @staticmethod
174
+ def isClassDef_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
175
+ return lambda node: be.ClassDef(node) and 又.name(ifThis._Identifier(identifier))(node)
176
+ @staticmethod
177
+ def isAssignAndValueIsCall_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
178
+ return lambda node: be.Assign(node) and 又.value(ifThis.isCall_Identifier(identifier))(node)
179
+ @staticmethod
180
+ def isAssignAndValueIsCallAttributeNamespace_Identifier(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
181
+ return ifThis.isAssignAndValueIs(ifThis.isCallAttributeNamespace_Identifier(namespace, identifier))
182
+ @staticmethod
183
+ def is_keywordAndValueIsConstant(node: ast.AST) -> TypeGuard[object]:
184
+ return be.keyword(node) and 又.value(be.Constant)(node)
185
+ @staticmethod
186
+ def is_keyword_IdentifierEqualsConstantValue(identifier: ast_Identifier, ConstantValue: Any) -> Callable[[ast.AST], TypeGuard[object] | bool]:
187
+ return lambda node: ifThis.is_keyword_Identifier(identifier)(node) and ifThis.is_keywordAndValueIsConstant(node) and 又.value(ifThis.isConstantEquals(ConstantValue))(node)
188
+ """
189
+ Argument of type "typeCertified@isAnnAssign_targetIs" cannot be assigned to parameter of type "astClassHasDOTtarget"
190
+ Type "typeCertified@isAnnAssign_targetIs" is not assignable to type "astClassHasDOTtarget"
191
+ "object*" is not assignable to "AnnAssign"
192
+ "object*" is not assignable to "AsyncFor"
193
+ "object*" is not assignable to "AugAssign"
194
+ "object*" is not assignable to "comprehension"
195
+ "object*" is not assignable to "For"
196
+ "object*" is not assignable to "NamedExpr"
197
+ """
198
+ @staticmethod
199
+ def isAnnAssign_targetIs(targetPredicate: Callable[[Ima_targetType], TypeGuard[Ima_targetType] | bool]) -> Callable[[ast.AST], TypeGuard[object] | bool]:
200
+ def workhorse(node: ast.AST) -> TypeGuard[object] | bool:
201
+ return be.AnnAssign(node) and 又.target(targetPredicate)(node)
202
+ return workhorse
203
+ @staticmethod
204
+ def isAnnAssignAndAnnotationIsName(node: ast.AST) -> TypeGuard[object] | bool:
205
+ return be.AnnAssign(node) and 又.annotation(be.Name)(node)
206
+ @staticmethod
207
+ def isAugAssign_targetIs(targetPredicate: Callable[[Ima_targetType], TypeGuard[Ima_targetType] | bool]) -> Callable[[ast.AST], TypeGuard[typeCertified] | bool]:
208
+ def workhorse(node: ast.AST) -> TypeGuard[typeCertified] | bool:
209
+ return be.AugAssign(node) and 又.target(targetPredicate)(node)
210
+ return workhorse
211
+
212
+ @staticmethod
213
+ def isAnyCompare(node: ast.AST) -> TypeGuard[object]:
214
+ return be.Compare(node) or be.BoolOp(node)
215
+ @staticmethod
216
+ def isConstantEquals(value: Any) -> Callable[[ast.AST], TypeGuard[object] | bool]:
217
+ return lambda node: be.Constant(node) and 又.value(ifThis.equals(value))(node)
218
+ @staticmethod
219
+ def isReturnAnyCompare(node: ast.AST) -> TypeGuard[object] | bool:
220
+ return be.Return(node) and 又.value(ifThis.isAnyCompare)(node)
221
+ @staticmethod
222
+ def isReturnUnaryOp(node: ast.AST) -> TypeGuard[object] | bool:
223
+ return be.Return(node) and 又.value(be.UnaryOp)(node)
224
+
225
+ # ================================================================
226
+ # Nested identifier
227
+ @staticmethod
228
+ def _nestedJunction_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
229
+ def workhorse(node: ast.AST) -> TypeGuard[object] | bool:
230
+ return ifThis.isName_Identifier(identifier)(node) or ifThis.isAttribute_Identifier(identifier)(node) or ifThis.isSubscript_Identifier(identifier)(node) or ifThis.isStarred_Identifier(identifier)(node)
231
+ return workhorse
232
+ @staticmethod
233
+ def isAttribute_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
234
+ """node is `ast.Attribute` and the top-level `ast.Name` is `identifier`"""
235
+ def workhorse(node: ast.AST) -> TypeGuard[object]:
236
+ return be.Attribute(node) and 又.value(ifThis._nestedJunction_Identifier(identifier))(node)
237
+ return workhorse
238
+ @staticmethod
239
+ def isStarred_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
240
+ """node is `ast.Starred` and the top-level `ast.Name` is `identifier`"""
241
+ def workhorse(node: ast.AST) -> TypeGuard[object]:
242
+ return be.Starred(node) and 又.value(ifThis._nestedJunction_Identifier(identifier))(node)
243
+ return workhorse
244
+ @staticmethod
245
+ def isSubscript_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
246
+ """node is `ast.Subscript` and the top-level `ast.Name` is `identifier`"""
247
+ def workhorse(node: ast.AST) -> TypeGuard[object]:
248
+ return be.Subscript(node) and 又.value(ifThis._nestedJunction_Identifier(identifier))(node)
249
+ return workhorse
250
+ # ================================================================
251
+
252
+ @staticmethod
253
+ def Z0Z_unparseIs(astAST: ast.AST) -> Callable[[ast.AST], bool]:
254
+ def workhorse(node: ast.AST) -> bool: return ast.unparse(node) == ast.unparse(astAST)
255
+ return workhorse
256
+
257
+ # ================================================================
258
+ # NOT used
259
+ # TODO Does this work?
260
+ @staticmethod
261
+ def Z0Z_matchesAtLeast1Descendant(predicate: Callable[[ast.AST], bool]) -> Callable[[ast.AST], bool]:
262
+ """Create a predicate that returns True if any descendant of the node matches the given predicate."""
263
+ return lambda node: not ifThis.matchesNoDescendant(predicate)(node)
264
+ # ================================================================
265
+ # MORE function inlining
266
+ @staticmethod
267
+ def onlyReturnAnyCompare(astFunctionDef: ast.AST) -> TypeGuard[object]:
268
+ return be.FunctionDef(astFunctionDef) and len(astFunctionDef.body) == 1 and ifThis.isReturnAnyCompare(astFunctionDef.body[0])
269
+ # For function inlining
270
+ @staticmethod
271
+ def onlyReturnUnaryOp(astFunctionDef: ast.AST) -> TypeGuard[object]:
272
+ return be.FunctionDef(astFunctionDef) and len(astFunctionDef.body) == 1 and ifThis.isReturnUnaryOp(astFunctionDef.body[0])
273
+ # ================================================================
274
+ # These are used by other functions
275
+ @staticmethod
276
+ def isCallAttributeNamespace_Identifier(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
277
+ return lambda node: be.Call(node) and 又.func(ifThis.isAttributeNamespace_Identifier(namespace, identifier))(node)
278
+ @staticmethod
279
+ def isName_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
280
+ return lambda node: be.Name(node) and 又.id(ifThis._Identifier(identifier))(node)
281
+ @staticmethod
282
+ def isCall_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
283
+ return lambda node: be.Call(node) and 又.func(ifThis.isName_Identifier(identifier))(node)
284
+ # ================================================================
285
+ @staticmethod
286
+ def matchesMeButNotAnyDescendant(predicate: Callable[[ast.AST], bool]) -> Callable[[ast.AST], bool]:
287
+ """Create a predicate that returns True if the node matches but none of its descendants match the predicate."""
288
+ return lambda node: predicate(node) and ifThis.matchesNoDescendant(predicate)(node)
289
+ @staticmethod
290
+ def matchesNoDescendant(predicate: Callable[[ast.AST], bool]) -> Callable[[ast.AST], bool]:
291
+ """Create a predicate that returns True if no descendant of the node matches the given predicate."""
292
+ def workhorse(node: ast.AST) -> bool:
293
+ for descendant in ast.walk(node):
294
+ if descendant is not node and predicate(descendant):
295
+ return False
296
+ return True
297
+ return workhorse
298
+
299
+ @staticmethod
300
+ def CallDoesNotCallItself(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
301
+ """If `namespace` is not applicable to your case, then call with `namespace=""`."""
302
+ return lambda node: ifThis.matchesMeButNotAnyDescendant(ifThis.CallReallyIs(namespace, identifier))(node)
303
+ @staticmethod
304
+ def CallReallyIs(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
305
+ return ifThis.isCall_Identifier(identifier) or ifThis.isCallAttributeNamespace_Identifier(namespace, identifier)
306
+ @staticmethod
307
+ def isAttributeNamespace_Identifier(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[object] | bool]:
308
+ return lambda node: ifThis.isAttributeName(node) and 又.value(ifThis.isName_Identifier(namespace))(node) and 又.attr(ifThis._Identifier(identifier))(node)
309
+ @staticmethod
310
+ def _Identifier(identifier: ast_Identifier) -> Callable[[ast_Identifier | None], TypeGuard[ast_Identifier] | bool]:
311
+ return lambda node: node == identifier
312
+ @staticmethod
313
+ def isAttributeName(node: ast.AST) -> TypeGuard[object]:
314
+ """ Displayed as Name.attribute."""
315
+ return be.Attribute(node) and 又.value(be.Name)(node)
316
+
317
+ @staticmethod
318
+ def isCallToName(node: ast.AST) -> TypeGuard[object]:
319
+ return be.Call(node) and 又.func(be.Name)(node)
320
+ @staticmethod
321
+ def ast_IdentifierIn(container: Container[ast_Identifier]) -> Callable[[ast_Identifier], TypeGuard[ast_Identifier] | bool]:
322
+ return lambda node: node in container
323
+ # This bullshit is for the crappy function inliner I made.
324
+ @staticmethod
325
+ def CallDoesNotCallItselfAndNameDOTidIsIn(container: Container[ast_Identifier]) -> Callable[[ast.AST], TypeGuard[object] | bool]:
326
+ return lambda node: ifThis.isCallToName(node) and 又.func(又.id(ifThis.ast_IdentifierIn(container)))(node) and ifThis.CallDoesNotCallItself("", node.func.id)(node)