astToolkit 0.1.4__tar.gz → 0.2.1__tar.gz
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.
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/PKG-INFO +1 -1
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit/__init__.py +1 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit/_toolBe.py +33 -27
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit/_toolIfThis.py +0 -16
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit/_toolkitNodeVisitor.py +8 -8
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit/_types.py +8 -7
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit/transformationTools.py +12 -4
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit.egg-info/PKG-INFO +1 -1
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit.egg-info/SOURCES.txt +6 -3
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/pyproject.toml +1 -1
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/toolFactory/Z0Z_hardcoded.py +16 -7
- asttoolkit-0.2.1/toolFactory/Z0Z_makeAstTools.py +42 -0
- asttoolkit-0.2.1/toolFactory/__init__.py +27 -0
- asttoolkit-0.2.1/toolFactory/_snippets.py +6 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/toolFactory/astFactory.py +45 -44
- asttoolkit-0.2.1/toolFactory/databaseASTCreation.py +154 -0
- asttoolkit-0.2.1/toolFactory/datacenter.py +131 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/toolFactory/docstrings.py +20 -7
- asttoolkit-0.2.1/toolFactory/factory3.py +319 -0
- asttoolkit-0.1.4/toolFactory/astFactory_annex.py → asttoolkit-0.2.1/toolFactory/factory_annex.py +2 -1
- asttoolkit-0.1.4/toolFactory/Z0Z_makeAstTools.py +0 -36
- asttoolkit-0.1.4/toolFactory/__init__.py +0 -16
- asttoolkit-0.1.4/toolFactory/startHere.py +0 -11
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/LICENSE +0 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/README.md +0 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit/_astTypes.py +0 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit/_toolClassIsAndAttribute.py +0 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit/_toolDOT.py +0 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit/_toolGrab.py +0 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit/_toolMake.py +0 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit/_toolThen.py +0 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit/_toolkitAST.py +0 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit/_toolkitContainers.py +0 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit/_typesSpecial.py +0 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit/py.typed +0 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit/theSSOT.py +0 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit.egg-info/dependency_links.txt +0 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit.egg-info/requires.txt +0 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/astToolkit.egg-info/top_level.txt +0 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/setup.cfg +0 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/tests/test_basic.py +0 -0
- {asttoolkit-0.1.4 → asttoolkit-0.2.1}/toolFactory/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: astToolkit
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: A powerfully composable, type-safe toolkit for Python abstract syntax tree (AST) manipulation, analysis, transformation, and code generation with a layered architecture designed for building sophisticated code processing assembly-lines.
|
|
5
5
|
Author-email: Hunter Hogan <HunterHogan@pm.me>
|
|
6
6
|
License: CC-BY-NC-4.0
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""This file is generated automatically, so changes to this file will be lost."""
|
|
2
|
-
from astToolkit import astDOTTryStar, astDOTParamSpec, astDOTtype_param, astDOTTypeAlias, astDOTTypeVar, astDOTTypeVarTuple
|
|
3
2
|
from typing import TypeGuard
|
|
4
3
|
import ast
|
|
4
|
+
import sys
|
|
5
5
|
|
|
6
6
|
class Be:
|
|
7
7
|
"""
|
|
@@ -159,14 +159,14 @@ class Be:
|
|
|
159
159
|
def Eq(node: ast.AST) -> TypeGuard[ast.Eq]:
|
|
160
160
|
return isinstance(node, ast.Eq)
|
|
161
161
|
|
|
162
|
-
@staticmethod
|
|
163
|
-
def excepthandler(node: ast.AST) -> TypeGuard[ast.excepthandler]:
|
|
164
|
-
return isinstance(node, ast.excepthandler)
|
|
165
|
-
|
|
166
162
|
@staticmethod
|
|
167
163
|
def ExceptHandler(node: ast.AST) -> TypeGuard[ast.ExceptHandler]:
|
|
168
164
|
return isinstance(node, ast.ExceptHandler)
|
|
169
165
|
|
|
166
|
+
@staticmethod
|
|
167
|
+
def excepthandler(node: ast.AST) -> TypeGuard[ast.excepthandler]:
|
|
168
|
+
return isinstance(node, ast.excepthandler)
|
|
169
|
+
|
|
170
170
|
@staticmethod
|
|
171
171
|
def Expr(node: ast.AST) -> TypeGuard[ast.Expr]:
|
|
172
172
|
return isinstance(node, ast.Expr)
|
|
@@ -335,14 +335,14 @@ class Be:
|
|
|
335
335
|
def MatMult(node: ast.AST) -> TypeGuard[ast.MatMult]:
|
|
336
336
|
return isinstance(node, ast.MatMult)
|
|
337
337
|
|
|
338
|
-
@staticmethod
|
|
339
|
-
def mod(node: ast.AST) -> TypeGuard[ast.mod]:
|
|
340
|
-
return isinstance(node, ast.mod)
|
|
341
|
-
|
|
342
338
|
@staticmethod
|
|
343
339
|
def Mod(node: ast.AST) -> TypeGuard[ast.Mod]:
|
|
344
340
|
return isinstance(node, ast.Mod)
|
|
345
341
|
|
|
342
|
+
@staticmethod
|
|
343
|
+
def mod(node: ast.AST) -> TypeGuard[ast.mod]:
|
|
344
|
+
return isinstance(node, ast.mod)
|
|
345
|
+
|
|
346
346
|
@staticmethod
|
|
347
347
|
def Module(node: ast.AST) -> TypeGuard[ast.Module]:
|
|
348
348
|
return isinstance(node, ast.Module)
|
|
@@ -382,10 +382,11 @@ class Be:
|
|
|
382
382
|
@staticmethod
|
|
383
383
|
def Or(node: ast.AST) -> TypeGuard[ast.Or]:
|
|
384
384
|
return isinstance(node, ast.Or)
|
|
385
|
+
if sys.version_info >= (3, 12):
|
|
385
386
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
387
|
+
@staticmethod
|
|
388
|
+
def ParamSpec(node: ast.AST) -> TypeGuard[ast.ParamSpec]:
|
|
389
|
+
return isinstance(node, ast.ParamSpec)
|
|
389
390
|
|
|
390
391
|
@staticmethod
|
|
391
392
|
def Pass(node: ast.AST) -> TypeGuard[ast.Pass]:
|
|
@@ -446,10 +447,11 @@ class Be:
|
|
|
446
447
|
@staticmethod
|
|
447
448
|
def Try(node: ast.AST) -> TypeGuard[ast.Try]:
|
|
448
449
|
return isinstance(node, ast.Try)
|
|
450
|
+
if sys.version_info >= (3, 11):
|
|
449
451
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
452
|
+
@staticmethod
|
|
453
|
+
def TryStar(node: ast.AST) -> TypeGuard[ast.TryStar]:
|
|
454
|
+
return isinstance(node, ast.TryStar)
|
|
453
455
|
|
|
454
456
|
@staticmethod
|
|
455
457
|
def Tuple(node: ast.AST) -> TypeGuard[ast.Tuple]:
|
|
@@ -458,26 +460,30 @@ class Be:
|
|
|
458
460
|
@staticmethod
|
|
459
461
|
def type_ignore(node: ast.AST) -> TypeGuard[ast.type_ignore]:
|
|
460
462
|
return isinstance(node, ast.type_ignore)
|
|
463
|
+
if sys.version_info >= (3, 12):
|
|
461
464
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
+
@staticmethod
|
|
466
|
+
def type_param(node: ast.AST) -> TypeGuard[ast.type_param]:
|
|
467
|
+
return isinstance(node, ast.type_param)
|
|
468
|
+
if sys.version_info >= (3, 12):
|
|
465
469
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
470
|
+
@staticmethod
|
|
471
|
+
def TypeAlias(node: ast.AST) -> TypeGuard[ast.TypeAlias]:
|
|
472
|
+
return isinstance(node, ast.TypeAlias)
|
|
469
473
|
|
|
470
474
|
@staticmethod
|
|
471
475
|
def TypeIgnore(node: ast.AST) -> TypeGuard[ast.TypeIgnore]:
|
|
472
476
|
return isinstance(node, ast.TypeIgnore)
|
|
477
|
+
if sys.version_info >= (3, 12):
|
|
473
478
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
479
|
+
@staticmethod
|
|
480
|
+
def TypeVar(node: ast.AST) -> TypeGuard[ast.TypeVar]:
|
|
481
|
+
return isinstance(node, ast.TypeVar)
|
|
482
|
+
if sys.version_info >= (3, 12):
|
|
477
483
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
484
|
+
@staticmethod
|
|
485
|
+
def TypeVarTuple(node: ast.AST) -> TypeGuard[ast.TypeVarTuple]:
|
|
486
|
+
return isinstance(node, ast.TypeVarTuple)
|
|
481
487
|
|
|
482
488
|
@staticmethod
|
|
483
489
|
def UAdd(node: ast.AST) -> TypeGuard[ast.UAdd]:
|
|
@@ -44,12 +44,6 @@ class IfThis:
|
|
|
44
44
|
"""see also `isArgument_Identifier`"""
|
|
45
45
|
return lambda node: Be.keyword(node) and IfThis.isIdentifier(identifier)(DOT.arg(node))
|
|
46
46
|
|
|
47
|
-
@staticmethod
|
|
48
|
-
def isAnnAssign_targetIs(targetPredicate: Callable[[ast.expr], TypeGuard[ast.expr] | bool]) -> Callable[[ast.AST], TypeGuard[ast.AnnAssign] | bool]:
|
|
49
|
-
def workhorse(node: ast.AST) -> TypeGuard[ast.AnnAssign] | bool:
|
|
50
|
-
return Be.AnnAssign(node) and targetPredicate(DOT.target(node))
|
|
51
|
-
return workhorse
|
|
52
|
-
|
|
53
47
|
@staticmethod
|
|
54
48
|
def isArgument_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.arg | ast.keyword] | bool]:
|
|
55
49
|
return lambda node: (Be.arg(node) or Be.keyword(node)) and IfThis.isIdentifier(identifier)(DOT.arg(node))
|
|
@@ -58,10 +52,6 @@ class IfThis:
|
|
|
58
52
|
def isAssignAndTargets0Is(targets0Predicate: Callable[[ast.AST], bool]) -> Callable[[ast.AST], TypeGuard[ast.AnnAssign] | bool]:
|
|
59
53
|
""" `node` is `ast.Assign` and `node.targets[0]` matches `targets0Predicate`."""
|
|
60
54
|
return lambda node: Be.Assign(node) and targets0Predicate(node.targets[0])
|
|
61
|
-
@staticmethod
|
|
62
|
-
def isAssignAndValueIs(valuePredicate: Callable[[ast.AST], bool]) -> Callable[[ast.AST], TypeGuard[ast.Assign] | bool]:
|
|
63
|
-
""" `node` is `ast.Assign` and `node.value` matches `valuePredicate`. """
|
|
64
|
-
return lambda node: Be.Assign(node) and valuePredicate(DOT.value(node))
|
|
65
55
|
|
|
66
56
|
@staticmethod
|
|
67
57
|
def isAttribute_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.Attribute] | bool]:
|
|
@@ -82,12 +72,6 @@ class IfThis:
|
|
|
82
72
|
def isAttributeNamespace_Identifier(namespace: ast_Identifier, identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.Attribute] | bool]:
|
|
83
73
|
return lambda node: IfThis.isAttributeName(node) and IfThis.isName_Identifier(namespace)(DOT.value(node)) and IfThis.isIdentifier(identifier)(DOT.attr(node))
|
|
84
74
|
|
|
85
|
-
@staticmethod
|
|
86
|
-
def isAugAssignAndTargetIs(targetPredicate: Callable[[ast.expr], TypeGuard[ast.expr] | bool]) -> Callable[[ast.AST], TypeGuard[ast.AugAssign] | bool]:
|
|
87
|
-
def workhorse(node: ast.AST) -> TypeGuard[ast.AugAssign] | bool:
|
|
88
|
-
return Be.AugAssign(node) and targetPredicate(DOT.target(node))
|
|
89
|
-
return workhorse
|
|
90
|
-
|
|
91
75
|
@staticmethod
|
|
92
76
|
def isCall_Identifier(identifier: ast_Identifier) -> Callable[[ast.AST], TypeGuard[ast.Call] | bool]:
|
|
93
77
|
def workhorse(node: ast.AST) -> TypeGuard[ast.Call] | bool:
|
|
@@ -15,12 +15,13 @@ structures, creating a complete workflow for code analysis and transformation.
|
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
17
|
from collections.abc import Callable
|
|
18
|
-
from typing import Any
|
|
18
|
+
from typing import Any, cast, Generic, TypeGuard, TypeVar
|
|
19
19
|
import ast
|
|
20
|
+
from astToolkit import NodeORattribute, 个, 个return
|
|
20
21
|
|
|
21
22
|
# TODO Identify the logic that narrows the type and can help the user during static type checking.
|
|
22
23
|
|
|
23
|
-
class NodeTourist(ast.NodeVisitor):
|
|
24
|
+
class NodeTourist(ast.NodeVisitor, Generic[个, 个return]):
|
|
24
25
|
"""
|
|
25
26
|
Visit and extract information from AST nodes that match a predicate.
|
|
26
27
|
|
|
@@ -31,19 +32,18 @@ class NodeTourist(ast.NodeVisitor):
|
|
|
31
32
|
This class is particularly useful for analyzing AST structures, extracting specific nodes or node properties, and
|
|
32
33
|
gathering information about code patterns.
|
|
33
34
|
"""
|
|
34
|
-
def __init__(self, findThis: Callable[
|
|
35
|
+
def __init__(self, findThis: Callable[[ast.AST], TypeGuard[个] | bool], doThat: Callable[[个], 个return]) -> None:
|
|
35
36
|
self.findThis = findThis
|
|
36
37
|
self.doThat = doThat
|
|
37
|
-
self.nodeCaptured:
|
|
38
|
+
self.nodeCaptured: 个return | None = None
|
|
38
39
|
|
|
39
40
|
def visit(self, node: ast.AST) -> None:
|
|
40
41
|
if self.findThis(node):
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
self.nodeCaptured = nodeActionReturn
|
|
42
|
+
node = cast(个, node)
|
|
43
|
+
self.nodeCaptured = self.doThat(node)
|
|
44
44
|
self.generic_visit(node)
|
|
45
45
|
|
|
46
|
-
def captureLastMatch(self, node: ast.AST) ->
|
|
46
|
+
def captureLastMatch(self, node: ast.AST) -> 个return | None:
|
|
47
47
|
self.nodeCaptured = None
|
|
48
48
|
self.visit(node)
|
|
49
49
|
return self.nodeCaptured
|
|
@@ -4,12 +4,6 @@ import ast
|
|
|
4
4
|
|
|
5
5
|
# TODO understand typing.
|
|
6
6
|
|
|
7
|
-
# NOTE Prototype of an idea to subclass composable methods so that typing information
|
|
8
|
-
# can extend beyond the top level of the ast node.
|
|
9
|
-
# To cover all cases, quantity of necessary classes = sum of (for each class: for each attribute: attribute * number of valid types). If an attribute has type ast.expr, for example, then there are 27 valid types just for that attribute. There would be thousands of subclasses like ImaCallToName.
|
|
10
|
-
# class ImaCallToName(ast.Call):
|
|
11
|
-
# func: ast.Name # pyright: ignore[reportIncompatibleVariableOverride]
|
|
12
|
-
|
|
13
7
|
# Type hints through TypeAlias or type "hints" through the identifier name.
|
|
14
8
|
ast_expr_Slice: typing_TypeAlias = ast.expr
|
|
15
9
|
ast_Identifier: typing_TypeAlias = str
|
|
@@ -17,7 +11,8 @@ str_nameDOTname: typing_TypeAlias = str
|
|
|
17
11
|
|
|
18
12
|
# Limited success with TypeVar.
|
|
19
13
|
个 = typing_TypeVar('个', bound = ast.AST, covariant = True)
|
|
20
|
-
|
|
14
|
+
个return = typing_TypeVar('个return', covariant = True)
|
|
15
|
+
NodeORattribute = typing_TypeVar('NodeORattribute', bound = ast.AST | ast_Identifier | str_nameDOTname | bool | Any | None, covariant = True)
|
|
21
16
|
|
|
22
17
|
# For my reference, all ast classes by subgroup:
|
|
23
18
|
Ima_ast_boolop: typing_TypeAlias = ast.boolop | ast.And | ast.Or
|
|
@@ -34,3 +29,9 @@ Ima_ast_type_param: typing_TypeAlias = astDOTtype_param | astDOTParamSpec | astD
|
|
|
34
29
|
Ima_ast_unaryop: typing_TypeAlias = ast.unaryop | ast.Invert | ast.Not | ast.UAdd | ast.USub
|
|
35
30
|
|
|
36
31
|
Ima_ast_orphan = ast.alias | ast.arg | ast.arguments | ast.comprehension | ast.keyword | ast.match_case | ast.withitem
|
|
32
|
+
|
|
33
|
+
# NOTE Prototype of an old idea to subclass composable methods so that typing information
|
|
34
|
+
# can extend beyond the top level of the ast node.
|
|
35
|
+
# To cover all cases, quantity of necessary classes = sum of (for each class: for each attribute: attribute * number of valid types). If an attribute has type ast.expr, for example, then there are 27 valid types just for that attribute. There would be thousands of subclasses like ImaCallToName.
|
|
36
|
+
# class ImaCallToName(ast.Call):
|
|
37
|
+
# func: ast.Name # pyright: ignore[reportIncompatibleVariableOverride]
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from astToolkit import (
|
|
2
2
|
ast_Identifier,
|
|
3
3
|
Be,
|
|
4
|
+
ClassIsAndAttribute,
|
|
4
5
|
DOT,
|
|
5
6
|
FREAKOUT,
|
|
6
7
|
Grab,
|
|
@@ -18,7 +19,7 @@ from collections.abc import Callable, Mapping
|
|
|
18
19
|
from copy import deepcopy
|
|
19
20
|
from os import PathLike
|
|
20
21
|
from pathlib import PurePath
|
|
21
|
-
from typing import Any, cast
|
|
22
|
+
from typing import Any, cast, overload
|
|
22
23
|
from Z0Z_tools import writeStringToHere
|
|
23
24
|
import ast
|
|
24
25
|
|
|
@@ -65,7 +66,8 @@ def inlineFunctionDef(identifierToInline: ast_Identifier, module: ast.Module) ->
|
|
|
65
66
|
raise ValueError(f"FunctionDefToInline not found in dictionaryIdentifier2FunctionDef: {identifierToInline = }") from ERRORmessage
|
|
66
67
|
|
|
67
68
|
listIdentifiersCalledFunctions: list[ast_Identifier] = []
|
|
68
|
-
findIdentifiersToInline = NodeTourist(findThis = IfThis.isCallToName
|
|
69
|
+
findIdentifiersToInline = NodeTourist(findThis = IfThis.isCallToName
|
|
70
|
+
, doThat = Grab.funcAttribute(cast(Callable[[ast.expr], ast.expr], Grab.idAttribute(cast(Callable[[ast_Identifier], ast_Identifier], Then.appendTo(listIdentifiersCalledFunctions))))))
|
|
69
71
|
findIdentifiersToInline.visit(FunctionDefToInline)
|
|
70
72
|
|
|
71
73
|
dictionary4Inlining: dict[ast_Identifier, ast.FunctionDef] = {}
|
|
@@ -94,7 +96,7 @@ def inlineFunctionDef(identifierToInline: ast_Identifier, module: ast.Module) ->
|
|
|
94
96
|
for astFunctionDef in dictionary4Inlining.values():
|
|
95
97
|
inliner.visit(astFunctionDef)
|
|
96
98
|
else:
|
|
97
|
-
inliner = NodeChanger(
|
|
99
|
+
inliner = NodeChanger(ClassIsAndAttribute.valueIs(ast.Assign, IfThis.isCall_Identifier(identifier)),Then.replaceWith(FunctionDefTarget.body[0:-1]))
|
|
98
100
|
for astFunctionDef in dictionary4Inlining.values():
|
|
99
101
|
inliner.visit(astFunctionDef)
|
|
100
102
|
|
|
@@ -104,7 +106,7 @@ def inlineFunctionDef(identifierToInline: ast_Identifier, module: ast.Module) ->
|
|
|
104
106
|
inliner = NodeChanger(IfThis.isCall_Identifier(identifier), Then.replaceWith(replacement))
|
|
105
107
|
inliner.visit(FunctionDefToInline)
|
|
106
108
|
else:
|
|
107
|
-
inliner = NodeChanger(
|
|
109
|
+
inliner = NodeChanger(ClassIsAndAttribute.valueIs(ast.Assign, IfThis.isCall_Identifier(identifier)),Then.replaceWith(FunctionDefTarget.body[0:-1]))
|
|
108
110
|
inliner.visit(FunctionDefToInline)
|
|
109
111
|
ast.fix_missing_locations(FunctionDefToInline)
|
|
110
112
|
return FunctionDefToInline
|
|
@@ -189,6 +191,10 @@ def unparseFindReplace(astTree: 个, mappingFindReplaceNodes: Mapping[ast.AST, a
|
|
|
189
191
|
astTree = deepcopy(newTree)
|
|
190
192
|
return newTree
|
|
191
193
|
|
|
194
|
+
# @overload
|
|
195
|
+
# def write_astModule(astModule: ast.AST, pathFilename: PathLike[Any] | PurePath, packageName: ast_Identifier | None = None) -> None:...
|
|
196
|
+
# @overload
|
|
197
|
+
# def write_astModule(ingredients: IngredientsModule, pathFilename: PathLike[Any] | PurePath, packageName: ast_Identifier | None = None) -> None:...
|
|
192
198
|
def write_astModule(ingredients: IngredientsModule, pathFilename: PathLike[Any] | PurePath, packageName: ast_Identifier | None = None) -> None:
|
|
193
199
|
"""
|
|
194
200
|
Convert an IngredientsModule to Python source code and write it to a file.
|
|
@@ -215,6 +221,8 @@ def write_astModule(ingredients: IngredientsModule, pathFilename: PathLike[Any]
|
|
|
215
221
|
Raises:
|
|
216
222
|
FREAKOUT: If the generated source code is empty.
|
|
217
223
|
"""
|
|
224
|
+
# if ingredients:
|
|
225
|
+
# astModule = Make.Module(ingredients.body, ingredients.type_ignores)
|
|
218
226
|
astModule = Make.Module(ingredients.body, ingredients.type_ignores)
|
|
219
227
|
ast.fix_missing_locations(astModule)
|
|
220
228
|
pythonSource: str = ast.unparse(astModule)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: astToolkit
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: A powerfully composable, type-safe toolkit for Python abstract syntax tree (AST) manipulation, analysis, transformation, and code generation with a layered architecture designed for building sophisticated code processing assembly-lines.
|
|
5
5
|
Author-email: Hunter Hogan <HunterHogan@pm.me>
|
|
6
6
|
License: CC-BY-NC-4.0
|
|
@@ -27,8 +27,11 @@ tests/test_basic.py
|
|
|
27
27
|
toolFactory/Z0Z_hardcoded.py
|
|
28
28
|
toolFactory/Z0Z_makeAstTools.py
|
|
29
29
|
toolFactory/__init__.py
|
|
30
|
+
toolFactory/_snippets.py
|
|
30
31
|
toolFactory/astFactory.py
|
|
31
|
-
toolFactory/
|
|
32
|
+
toolFactory/databaseASTCreation.py
|
|
33
|
+
toolFactory/datacenter.py
|
|
32
34
|
toolFactory/docstrings.py
|
|
33
|
-
toolFactory/py
|
|
34
|
-
toolFactory/
|
|
35
|
+
toolFactory/factory3.py
|
|
36
|
+
toolFactory/factory_annex.py
|
|
37
|
+
toolFactory/py.typed
|
|
@@ -36,7 +36,7 @@ optional-dependencies = { testing = [
|
|
|
36
36
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
37
37
|
requires-python = ">=3.10"
|
|
38
38
|
urls = { Donate = "https://www.patreon.com/integrated", Homepage = "https://github.com/hunterhogan/astToolkit", Issues = "https://github.com/hunterhogan/astToolkit/issues", Repository = "https://github.com/hunterhogan/astToolkit.git" }
|
|
39
|
-
version = "0.1
|
|
39
|
+
version = "0.2.1"
|
|
40
40
|
|
|
41
41
|
[tool.coverage]
|
|
42
42
|
report = { exclude_lines = [
|
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
from typing import TypeAlias as typing_TypeAlias
|
|
3
|
+
import ast
|
|
3
4
|
|
|
4
5
|
ast_Identifier: typing_TypeAlias = str
|
|
5
|
-
|
|
6
|
+
str_nameDOTname: typing_TypeAlias = str
|
|
7
|
+
|
|
8
|
+
pythonVersionMinorMinimum: int = 10
|
|
9
|
+
sys_version_infoMinimum: tuple[int, int] = (3, 10)
|
|
10
|
+
sys_version_infoTarget: tuple[int, int] = (3, 13)
|
|
11
|
+
|
|
12
|
+
class FREAKOUT(Exception): pass
|
|
13
|
+
|
|
14
|
+
# filesystem and namespace ===============================================
|
|
6
15
|
packageName: ast_Identifier = 'astToolkit'
|
|
16
|
+
moduleIdentifierPrefix: str = '_tool'
|
|
17
|
+
keywordArgumentsIdentifier: ast_Identifier = 'keywordArguments'
|
|
18
|
+
|
|
7
19
|
pathRoot = Path('/apps') / packageName
|
|
8
20
|
pathPackage = pathRoot / packageName
|
|
21
|
+
pathToolFactory = pathRoot / 'toolFactory'
|
|
9
22
|
pathTypeshed = pathRoot / 'typeshed' / 'stdlib'
|
|
10
|
-
str_nameDOTname: typing_TypeAlias = str
|
|
11
|
-
sys_version_infoMinimum: tuple[int, int] = (3, 10)
|
|
12
|
-
sys_version_infoTarget: tuple[int, int] = (3, 13)
|
|
13
23
|
|
|
14
|
-
|
|
24
|
+
pathFilenameDatabaseAST = pathToolFactory / 'databaseAST.csv'
|
|
15
25
|
|
|
16
|
-
|
|
17
|
-
pass
|
|
26
|
+
fileExtension: str = '.py'
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from collections.abc import Callable, Sequence
|
|
2
|
+
import typeshed_client.finder
|
|
3
|
+
from toolFactory import FREAKOUT, pathTypeshed, makeTools
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any, TypeAlias as typing_TypeAlias, TypeVar as typing_TypeVar
|
|
6
|
+
import ast
|
|
7
|
+
|
|
8
|
+
ast_expr_Slice: typing_TypeAlias = ast.expr
|
|
9
|
+
ast_Identifier: typing_TypeAlias = str
|
|
10
|
+
str_nameDOTname: typing_TypeAlias = str
|
|
11
|
+
|
|
12
|
+
个 = typing_TypeVar('个', bound = ast.AST, covariant = True)
|
|
13
|
+
NodeORattribute = typing_TypeVar('NodeORattribute', bound = ast.AST | ast_expr_Slice | ast_Identifier | str_nameDOTname | bool | Any | None, covariant = True)
|
|
14
|
+
|
|
15
|
+
# TODO Some `DOT` methods return lists, notably DOT.targets, which is an attribute of ast.Assign.
|
|
16
|
+
# But, none or almost none of the other functions and methods accept a list as input.
|
|
17
|
+
# This is most obviously a problem in `ClassIsAndAttribute.targetsIs` because the user needs to pass
|
|
18
|
+
# a function that can take list[ast.expr] as a parameter.
|
|
19
|
+
# I don't know if the following works, but it is interesting.
|
|
20
|
+
# ClassIsAndAttribute.targetsIs(ast.Assign, lambda list_expr: any([IfThis.isSubscript_Identifier('foldGroups')(node) for node in list_expr]))
|
|
21
|
+
|
|
22
|
+
class cleverName:
|
|
23
|
+
@staticmethod
|
|
24
|
+
def index(at: int) -> Callable[[Sequence[NodeORattribute]], NodeORattribute]:
|
|
25
|
+
def workhorse(zzz: Sequence[NodeORattribute]) -> NodeORattribute:
|
|
26
|
+
node = zzz[at]
|
|
27
|
+
return node
|
|
28
|
+
return workhorse
|
|
29
|
+
|
|
30
|
+
if __name__ == "__main__":
|
|
31
|
+
search_context = typeshed_client.finder.get_search_context(typeshed=pathTypeshed if pathTypeshed.exists() else None)
|
|
32
|
+
|
|
33
|
+
# pathFilenameStubFile: Path | None = typeshed_client.finder.get_stub_file("_ast", search_context=search_context)
|
|
34
|
+
# if pathFilenameStubFile is None: raise FREAKOUT
|
|
35
|
+
# astStubFile: ast.Module = ast.parse(pathFilenameStubFile.read_text())
|
|
36
|
+
# Z0Z_typesSpecial(astStubFile)
|
|
37
|
+
|
|
38
|
+
pathFilenameStubFile: Path | None = typeshed_client.finder.get_stub_file("ast", search_context=search_context)
|
|
39
|
+
if pathFilenameStubFile is None: raise FREAKOUT
|
|
40
|
+
astStubFile: ast.Module = ast.parse(pathFilenameStubFile.read_text())
|
|
41
|
+
|
|
42
|
+
makeTools(astStubFile)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from toolFactory.Z0Z_hardcoded import (
|
|
2
|
+
ast_Identifier as ast_Identifier,
|
|
3
|
+
fileExtension as fileExtension,
|
|
4
|
+
FREAKOUT as FREAKOUT,
|
|
5
|
+
keywordArgumentsIdentifier as keywordArgumentsIdentifier,
|
|
6
|
+
moduleIdentifierPrefix as moduleIdentifierPrefix,
|
|
7
|
+
packageName as packageName,
|
|
8
|
+
pathFilenameDatabaseAST as pathFilenameDatabaseAST,
|
|
9
|
+
pathPackage as pathPackage,
|
|
10
|
+
pathTypeshed as pathTypeshed,
|
|
11
|
+
pythonVersionMinorMinimum as pythonVersionMinorMinimum,
|
|
12
|
+
str_nameDOTname as str_nameDOTname,
|
|
13
|
+
sys_version_infoMinimum as sys_version_infoMinimum,
|
|
14
|
+
sys_version_infoTarget as sys_version_infoTarget,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
from toolFactory._snippets import (
|
|
18
|
+
astName_overload as astName_overload,
|
|
19
|
+
astName_staticmethod as astName_staticmethod,
|
|
20
|
+
astName_typing_TypeAlias as astName_typing_TypeAlias,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
from toolFactory.datacenter import (
|
|
24
|
+
getElementsBe as getElementsBe,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
from toolFactory.astFactory import makeTools as makeTools
|