AST Grep Python Bindings
ast-grep-py provides Python bindings for ast-grep, a powerful structural code search and rewrite engine. It enables developers to query and transform code using abstract syntax tree (AST) patterns, supporting multiple programming languages. The current version is 0.42.1, and the library maintains a rapid release cadence with frequent minor and patch updates, often multiple times a month.
Warnings
- gotcha The pattern matching syntax used by ast-grep-py (e.g., `$VAR`, `$$$`) is specific to ast-grep and differs significantly from standard regular expressions or typical AST traversal libraries. Users must learn this syntax to effectively utilize the library.
- gotcha When analyzing code written in languages other than Python, it is crucial to explicitly specify the `lang` parameter during `SgRoot` initialization (e.g., `SgRoot(code=my_js_code, lang='javascript')`). The default language is Python.
- gotcha Methods like `SgRoot.replace()` do not modify the original `SgRoot` instance in-place. Instead, they return a *new* `SgRoot` object containing the modified code. Users expecting mutable behavior might inadvertently ignore the returned value.
- gotcha While ast-grep is implemented in Rust for performance, the Python bindings introduce a layer of overhead. For extremely large codebases or highly performance-critical scenarios involving frequent AST operations, users should benchmark the Python bindings against the native Rust CLI to ensure it meets their performance requirements.
Install
-
pip install ast-grep-py
Imports
- SgRoot
from ast_grep_py import SgRoot
- SgNode
from ast_grep_py import SgNode
- SgMatch
from ast_grep_py import SgMatch
- SgPattern
from ast_grep_py import SgPattern
Quickstart
from ast_grep_py import SgRoot
python_code = """
def my_function(a, b):
result = a + b
print(f"Result: {result}")
return result
"""
# Create an SgRoot instance. Language defaults to Python.
root = SgRoot(code=python_code)
# Find all function definitions using an ast-grep pattern
# '$FUN' and '$$$' are metavariables matching identifiers and multiple statements/expressions respectively.
matches = root.find_all("def $FUN($$$):")
print("Found functions:")
for m in matches:
print(f"- {m.text()}")
# Replace print statements with a logger.info call
# SgRoot.replace returns a new SgRoot instance with the changes.
new_code_root = root.replace(
pattern='print($$$)',
replacement='logger.info($$$)'
)
print("\nCode after replacement:")
print(new_code_root.text())