An abstract syntax tree for Python with inference support.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Central management system for building, caching, and retrieving astroid AST trees from various sources. The manager provides a high-level interface for working with Python modules and handles caching to improve performance.
The main management class that coordinates building, caching, and transform application for astroid AST trees.
class AstroidManager:
"""Central manager for astroid AST trees."""
def __init__(self) -> None:
"""Initialize the manager with default settings."""
def ast_from_file(self, filepath: str, modname: str | None = None, fallback: bool = True, source: bool = False) -> Module:
"""
Build astroid tree from a Python file.
Parameters:
- filepath: Path to the Python file
- modname: Module name (defaults to filename)
- fallback: Try alternative loading methods on failure
- source: Get source code instead of compiled module
Returns:
Module node representing the file
Raises:
AstroidBuildingError: If file cannot be loaded or parsed
"""
def ast_from_string(self, data: str, modname: str = "", filepath: str | None = None) -> Module:
"""
Build astroid tree from source string.
Parameters:
- data: Python source code
- modname: Name for the module
- filepath: Optional file path for error reporting
Returns:
Module node representing the source
Raises:
AstroidSyntaxError: If source contains syntax errors
"""
def ast_from_module_name(self, modname: str | None, context_file: str | None = None, use_cache: bool = True) -> Module:
"""
Build astroid tree from module name.
Parameters:
- modname: Fully qualified module name
- context_file: File requesting the module (for relative imports)
- use_cache: Whether to use cached version if available
Returns:
Module node for the imported module
Raises:
AstroidImportError: If module cannot be imported
"""
def ast_from_module(self, module: Any, modname: str | None = None) -> Module:
"""
Build astroid tree from live Python module.
Parameters:
- module: Python module object
- modname: Name for the astroid module
Returns:
Module node representing the live module
Raises:
AstroidBuildingError: If module cannot be introspected
"""
def ast_from_class(self, klass: type, modname: str | None = None) -> Module:
"""
Build astroid tree from a Python class.
Parameters:
- klass: Python class object
- modname: Module name for the generated tree
Returns:
Module containing the class definition
Raises:
AstroidBuildingError: If class cannot be introspected
"""Control manager behavior through properties and methods.
class AstroidManager:
# Configuration properties
always_load_extensions: bool
"""Whether to always load brain extensions."""
optimize_ast: bool
"""Enable AST optimization during building."""
max_inferable_values: int
"""Maximum number of values to infer for sequences."""
prefer_stubs: bool
"""Prefer .pyi stub files over .py files."""
# Cache management
def clear_cache(self) -> None:
"""Clear all cached AST trees."""
def cache_size(self) -> int:
"""Get number of cached modules."""
# Transform system
def register_transform(self, node_class: type[NodeNG], transform: Callable, predicate: Callable | None = None) -> None:
"""
Register an AST transform function.
Parameters:
- node_class: Node class to transform
- transform: Transform function
- predicate: Optional condition for applying transform
"""
def unregister_transform(self, node_class: type[NodeNG], transform: Callable, predicate: Callable | None = None) -> None:
"""Unregister a previously registered transform."""
# Import hooks
def register_failed_import_hook(self, hook: Callable) -> None:
"""Register hook for handling failed imports."""
def unregister_failed_import_hook(self, hook: Callable) -> None:
"""Unregister a failed import hook."""MANAGER: AstroidManager
"""Global singleton manager instance."""The manager works with builder classes to create AST trees.
class TreeRebuilder:
"""Rebuilds Python AST as astroid AST."""
def __init__(self, manager: AstroidManager) -> None:
"""Initialize with manager instance."""
def visit_module(self, node: ast.Module, parent: NodeNG) -> Module:
"""Convert ast.Module to astroid.Module."""import astroid
# Get the global manager
manager = astroid.MANAGER
# Load module from file
try:
module = manager.ast_from_file('mymodule.py')
print(f"Loaded module: {module.name}")
except astroid.AstroidBuildingError as e:
print(f"Failed to load: {e}")
# Load module by name
try:
os_module = manager.ast_from_module_name('os')
print(f"OS module functions: {len(os_module.keys())}")
except astroid.AstroidImportError as e:
print(f"Import failed: {e}")import astroid
manager = astroid.MANAGER
# First load - builds and caches
module1 = manager.ast_from_module_name('sys')
# Second load - uses cache
module2 = manager.ast_from_module_name('sys')
print(f"Same instance: {module1 is module2}") # True
# Clear cache if needed
manager.clear_cache()
print(f"Cache size: {manager.cache_size()}") # 0import astroid
from astroid import nodes
def remove_pass_statements(node):
"""Transform to remove pass statements."""
if isinstance(node, nodes.Pass):
return None # Remove the node
return node
# Register transform
astroid.MANAGER.register_transform(nodes.Pass, remove_pass_statements)
# Parse code with pass statements
code = '''
def func():
pass # This will be removed
return 42
'''
module = astroid.parse(code)
# Pass statement will be removed from the ASTimport astroid
def handle_failed_import(modname):
"""Handle modules that can't be imported."""
if modname == 'missing_module':
# Create a dummy module
return astroid.parse('# Dummy module', modname)
return None
# Register the hook
astroid.MANAGER.register_failed_import_hook(handle_failed_import)
# Now imports of 'missing_module' will use the dummy
try:
module = astroid.MANAGER.ast_from_module_name('missing_module')
print("Got dummy module")
except astroid.AstroidImportError:
print("Import still failed")import astroid
manager = astroid.MANAGER
# Configure manager behavior
manager.optimize_ast = True
manager.max_inferable_values = 100
manager.prefer_stubs = True
# Load with brain extensions
manager.always_load_extensions = True
module = manager.ast_from_module_name('requests')The manager system raises specific exceptions:
Create custom loaders for special module types:
import astroid
class CustomModuleLoader:
def load_module(self, modname):
# Custom loading logic
return astroid.parse(f'# Custom module {modname}', modname)
# Integration with manager requires modifying the import systemimport astroid
# Optimize for performance
manager = astroid.MANAGER
manager.optimize_ast = True
manager.max_inferable_values = 50 # Limit inference depth
# Bulk loading with caching
modules = []
for name in ['os', 'sys', 'json', 'collections']:
modules.append(manager.ast_from_module_name(name))
print(f"Cached {manager.cache_size()} modules")Install with Tessl CLI
npx tessl i tessl/pypi-astroid