CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-darker

Apply Black formatting only in regions changed since last commit

Pending
Overview
Eval results
Files

verification.mddocs/

AST Verification

AST verification utilities for ensuring code transformations preserve semantic equivalence. These functions validate that reformatting doesn't change the abstract syntax tree structure of Python code.

Capabilities

AST Verification Classes

Core classes for verifying AST equivalence between original and reformatted code.

class ASTVerifier:
    """
    Verify if reformatted TextDocument is AST-equivalent to baseline.
    
    Keeps in-memory data about previous comparisons to improve performance.
    """
    
    def __init__(self, baseline: TextDocument) -> None:
        """
        Initialize verifier with baseline document.
        
        Parameters:
        - baseline: The baseline document to compare against
        """
    
    def is_equivalent_to_baseline(self, document: TextDocument) -> bool:
        """
        Returns true if document is AST-equivalent to baseline.
        
        Parameters:
        - document: Document to compare against baseline
        
        Returns:
        True if documents are AST-equivalent, False otherwise
        """

class BinarySearch:
    """
    Effectively search the first index for which a condition is True.
    
    Used for finding the minimal change that breaks AST equivalence.
    """
    
    def __init__(self, low: int, high: int) -> None:
        """
        Initialize binary search with range bounds.
        
        Parameters:
        - low: Lower bound of search range
        - high: Upper bound of search range
        """
    
    def get_next(self) -> int:
        """Get the next integer index to try."""
    
    def respond(self, value: bool) -> None:
        """
        Provide a False or True answer for the current integer index.
        
        Parameters:
        - value: Response for current index
        """
    
    @property
    def found(self) -> bool:
        """Return True if the lowest True response index has been found."""
    
    @property
    def result(self) -> int:
        """Return the lowest index with a True response."""

AST Parsing and Comparison

Functions for parsing and comparing Python ASTs with error handling.

def parse_ast(src: str) -> ast.AST:
    """
    Parse source code with fallback for type comments.
    
    This function tries multiple Python version feature sets
    and handles both type comments and syntax variations.
    
    Parameters:
    - src: Python source code to parse
    
    Returns:
    Parsed AST node
    
    Raises:
    SyntaxError: If source cannot be parsed with any supported syntax
    """

def stringify_ast(node: ast.AST) -> Iterator[str]:
    """
    Generate strings to compare ASTs by content using a simple visitor.
    
    Parameters:
    - node: Root AST node to stringify
    
    Yields:
    String representations of AST nodes for comparison
    """

Exception Types

Exceptions specific to AST verification operations.

class NotEquivalentError(Exception):
    """Exception to raise if two ASTs being compared are not equivalent."""

Usage Examples

Basic AST Verification

from darker.verification import ASTVerifier
from darkgraylib.utils import TextDocument

# Set up verification with baseline code
original_code = TextDocument.from_str('''
def hello(name):
    print(f"Hello, {name}!")
''')

verifier = ASTVerifier(original_code)

# Check if reformatted code is equivalent
formatted_code = TextDocument.from_str('''
def hello(name):
    print(f"Hello, {name}!")
''')

is_equivalent = verifier.is_equivalent_to_baseline(formatted_code)
print(f"Code is AST-equivalent: {is_equivalent}")

Binary Search for Error Location

from darker.verification import BinarySearch

# Find first line where condition becomes true
search = BinarySearch(0, 100)

while not search.found:
    line_num = search.get_next()
    # Test some condition on line_num
    condition_met = some_test_function(line_num)
    search.respond(condition_met)

print(f"First line where condition is true: {search.result}")

Custom AST Parsing

from darker.verification import parse_ast, stringify_ast

try:
    source = '''
    def example() -> None:
        x: int = 42
        return None
    '''
    
    ast_tree = parse_ast(source)
    ast_strings = list(stringify_ast(ast_tree))
    
    print("AST structure:")
    for line in ast_strings[:10]:  # Show first 10 lines
        print(line)
        
except SyntaxError as e:
    print(f"Could not parse source: {e}")

Install with Tessl CLI

npx tessl i tessl/pypi-darker

docs

chooser.md

command-line.md

configuration.md

diff-utilities.md

file-utilities.md

formatters.md

git-integration.md

index.md

main-functions.md

preprocessors.md

verification.md

tile.json