astToolkit
Easily and Confidently Transform Python Code Using Unadulterated AST Classes
astToolkit provides composable, typed tools for analyzing, transforming, and generating Python code. Select the nodes you care about, describe an action, and apply it through a visitor.
Compatibility with the standard library's ast is an intentional design goal. astToolkit works directly with the same ast.AST objects. You can parse with ast, transform with astToolkit, and return to ast for inspection, unparsing, or compilation. There is no conversion step or separate tree representation.
import ast
from astToolkit import Grab, IfThis, NodeChanger, Then
astModule: ast.Module = ast.parse('result = value * 2')
NodeChanger(
IfThis.isNameIdentifier('value'),
Grab.idAttribute(Then.replaceWith('amount')),
).visit(astModule)
print(ast.unparse(astModule))
# result = amount * 2
This changes the identifier on the existing ast.Name node. The module and its nodes remain available to your own visitors and other tools that work with stdlib ASTs.
Installation
Requires Python 3.14 or later.
pip install astToolkit
Compose the operation you need
The core pattern is predicate + action + visitor. A predicate identifies a node; an action reads or changes it; a visitor applies that operation throughout a tree.
| Tool | Purpose |
|---|---|
Be |
Check node types with TypeIs guards, such as Be.FunctionDef, and compose conditions on their fields. |
DOT |
Read node attributes through typed getters, such as DOT.name or DOT.value. |
Grab |
Transform an attribute while retaining its containing node. |
Make |
Construct AST nodes with typed parameters and convenient defaults. |
IfThis |
Match identifiers, structure, and combinations of conditions. |
Then |
Collect, extract, insert, replace, or remove matched nodes. |
NodeTourist |
Visit nodes for inspection and collection; captureLastMatch returns the last action result. |
NodeChanger |
Transform matching nodes, including replacing or removing them. |
NodeTourist extends ast.NodeVisitor; NodeChanger extends ast.NodeTransformer. A matching NodeChanger node is handed to its action without automatically visiting that node's children. Compose visitors or attribute actions when a transformation needs to continue inside a match.
Read and collect
Use a DOT getter to retrieve an attribute directly, or Then.appendTo to collect matching nodes:
import ast
from astToolkit import Be, DOT, NodeTourist, Then
astModule: ast.Module = ast.parse('result = value * 2')
identifier: str | None = NodeTourist(
Be.Name, DOT.id,
).captureLastMatch(astModule)
print(identifier)
# value
list_astName: list[ast.Name] = []
NodeTourist(Be.Name, Then.appendTo(list_astName)).visit(astModule)
The collected nodes are the original objects in astModule. Extraction does not copy or wrap them.
Build nodes
Make works with stdlib node types. For example, Make.Name('amount') returns an ast.Name with a Load context:
import ast
from astToolkit import Make
astName: ast.Name = Make.Name('amount')
print(type(astName) is ast.Name)
# True
print(ast.compare(astName, ast.Name(id='amount', ctx=ast.Load())))
# True
Operator joins assemble expressions without manually nesting each binary operation:
import ast
from astToolkit import Make
ast_expr: ast.expr = Make.Add.join([
Make.Name('subtotal'),
Make.Name('tax'),
Make.Name('shipping'),
])
print(ast.unparse(ast_expr))
# subtotal + tax + shipping
astModule: ast.Module = Make.Module([Make.Expr(ast_expr)])
compile(ast.fix_missing_locations(astModule), '<generated>', 'exec')
Some Make operator classes, including Make.Add, subclass their stdlib counterparts to provide join. They work with stdlib AST tools; ast.compare distinguishes those subclasses from the exact stdlib classes. I want to change this.
Match structure
Use IfThis.astIs(referenceNode) for structural matching through ast.compare. Field predicates, such as Be.Assign.valueIs(...), select a containing node by a condition on one of its fields. IfThis.isAllOf(...) applies every condition to the same node; nested visitors search within a selected subtree.
Find the function you need
Utility functions have focused module homes:
| Module | Functions |
|---|---|
astToolkit.changeDef |
extractClassDef, extractFunctionDef, makeDictionaryAsyncFunctionDef, makeDictionaryClassDef, makeDictionaryFunctionDef, makeDictionaryMosDef, inlineFunctionDef, removeUnusedParameters |
astToolkit.filesystem |
parsePathFilename2astModule, parseLogicalPath2astModule, write_astModule |
astToolkit.ohWow |
pythonCode2ast_expr, unjoinBinOP, unparseFindReplace |
- Definitions: extract a named function or class, index definitions by name, inline supported local function calls, or remove unused parameters.
- Files: parse a source file without importing it, parse an importable module's source, or write an
ast.Moduleas formatted Python.parseLogicalPath2astModuleimports the module;write_astModuleremoves unused imports and organizes imports. - Expressions: parse expression text, collect binary-operation operands, or replace nodes by matching their unparsed text.
Import these functions from their modules, for example:
from astToolkit.changeDef import extractFunctionDef, removeUnusedParameters
from astToolkit.filesystem import parsePathFilename2astModule, write_astModule
Type aliases describe AST fields and the node types that contain them. The package includes py.typed for static type checking.
Breaking change in 0.13.0: IngredientsFunction, IngredientsModule, and LedgerOfImports have been removed.
Larger workflows
mapFolding uses astToolkit to transform readable algorithms into specialized variants and generate Python modules.
Most of the core toolkit code is generated by the separate astToolFactory project.
Support my work
If astToolkit saves you time, please sponsor my work on GitHub. Monthly or one-time support helps me survive. You can also choose another way to support me.
Citation and license
Citation metadata is available in CITATION.cff.
Metadata
Release files for astToolkit 0.13.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| asttoolkit-0.13.0.tar.gz | 122.1 kB | Without provenance | Details for asttoolkit-0.13.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| asttoolkit-0.13.0-py3-none-any.whl | Python 3 | none | any | Details for asttoolkit-0.13.0-py3-none-any.whl |
Total release size: 252.3 kB
Release files / asttoolkit-0.13.0.tar.gz
| Download URL | asttoolkit-0.13.0.tar.gz |
|---|---|
| Size | 122.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6fe3d3c943f7b55d887d3deffe9f033f5007cf0b271dd2db629b8a31e71fa421
|
|
BLAKE2b-256 checksum How to use checksums |
673d4d4c0be539d3e1f794fe0db42c21b268810e49abf387a95a5f10bdc660d9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / asttoolkit-0.13.0-py3-none-any.whl
| Download URL | asttoolkit-0.13.0-py3-none-any.whl |
|---|---|
| Size | 130.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
78f54bf7913da9aa154fbf5eeb83809057b25312dfb4b9ca4214ba5cbd1d66ce
|
|
BLAKE2b-256 checksum How to use checksums |
8e55864d9136e0540092f1bdc39059e63b5a2ac23cdaf293998bddd2900f4a37
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Security for astToolkit 0.13.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.