CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-astor

Read/rewrite/write Python ASTs

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

operator-utilities.mddocs/

Operator Utilities

Utilities for working with Python operators, including symbol extraction and precedence handling for proper expression formatting. This module provides comprehensive support for AST operator nodes and ensures correct parenthesization in generated source code.

Capabilities

Operator Symbol Extraction

Extract string representations of Python operators from AST operator nodes.

def get_op_symbol(obj, fmt='%s'):
    """
    Return symbol string for an AST operator node.
    
    Parameters:
    - obj: AST operator node (BinOp, UnaryOp, BoolOp, Compare, etc.)
    - fmt: str, format string for the symbol (default: '%s')
    
    Returns:
    str: String containing the operator symbol
    
    Raises:
    KeyError: If the operator type is not recognized
    """

Usage Example:

import ast
import astor

# Parse expression with various operators
code = "a + b * c - d / e and f or g"
tree = ast.parse(code, mode='eval')

# Extract operator symbols
for node in ast.walk(tree):
    if hasattr(node, 'op'):
        symbol = astor.get_op_symbol(node.op)
        print(f"{type(node.op).__name__}: {symbol}")
    elif hasattr(node, 'ops'):
        for op in node.ops:
            symbol = astor.get_op_symbol(op)
            print(f"{type(op).__name__}: {symbol}")

# Custom formatting
code = "x ** y"
tree = ast.parse(code, mode='eval')
binop_node = tree.body

symbol = astor.get_op_symbol(binop_node.op, fmt='[%s]')
print(f"Formatted symbol: {symbol}")  # [**]

Operator Precedence

Get precedence values for Python operators to ensure correct parenthesization in generated code.

def get_op_precedence(obj):
    """
    Return precedence value for an AST operator node.
    
    Parameters:
    - obj: AST operator node
    
    Returns:
    int: Integer precedence value (higher numbers = higher precedence)
    
    Raises:
    KeyError: If the operator type is not recognized
    """

Usage Example:

import ast
import astor

# Parse complex expression
code = "a + b * c"
tree = ast.parse(code, mode='eval')

# Check precedence to understand grouping
binop = tree.body  # BinOp for 'a + (b * c)'
add_prec = astor.get_op_precedence(binop.op)  # Add
mult_prec = astor.get_op_precedence(binop.right.op)  # Mult

print(f"Addition precedence: {add_prec}")
print(f"Multiplication precedence: {mult_prec}")
print(f"Multiplication has higher precedence: {mult_prec > add_prec}")

Operator Symbol Data

Complete mapping from AST operator types to their string symbols.

symbol_data: dict

This dictionary contains the complete mapping of all Python operators:

import astor

# Explore all available operators
print("Binary operators:")
for op_type, symbol in astor.symbol_data.items():
    if 'op' in op_type.__name__.lower():
        print(f"  {op_type.__name__}: {symbol}")

# Check specific operators
import ast
print(f"Add symbol: {astor.symbol_data[ast.Add]}")      # +
print(f"Mult symbol: {astor.symbol_data[ast.Mult]}")    # *
print(f"And symbol: {astor.symbol_data[ast.And]}")      # and
print(f"Or symbol: {astor.symbol_data[ast.Or]}")        # or

Precedence Constants

Class containing precedence values for all Python operators.

class Precedence:
    """
    Container for operator precedence constants.
    
    Contains precedence values for all Python operators following
    Python's operator precedence rules.
    """

Available Precedence Constants:

import astor

# Access precedence constants
print(f"Comma precedence: {astor.Precedence.Comma}")      # Lowest
print(f"Or precedence: {astor.Precedence.Or}")
print(f"And precedence: {astor.Precedence.And}")
print(f"Not precedence: {astor.Precedence.Not}")
print(f"In precedence: {astor.Precedence.In}")
print(f"Compare precedence: {astor.Precedence.Comp}")
print(f"BitOr precedence: {astor.Precedence.BitOr}")
print(f"BitXor precedence: {astor.Precedence.BitXor}")
print(f"BitAnd precedence: {astor.Precedence.BitAnd}")
print(f"Shift precedence: {astor.Precedence.Shift}")
print(f"Add precedence: {astor.Precedence.Add}")
print(f"Mult precedence: {astor.Precedence.Mult}")
print(f"UAdd precedence: {astor.Precedence.UAdd}")
print(f"Power precedence: {astor.Precedence.Pow}")        # Highest

Advanced Operator Handling

Expression Parenthesization

Using operator precedence to determine when parentheses are needed in generated expressions.

Usage Example:

import ast
import astor

def needs_parens(parent_op, child_op, is_right=False):
    """Check if child operation needs parentheses."""
    parent_prec = astor.get_op_precedence(parent_op)
    child_prec = astor.get_op_precedence(child_op)
    
    # Lower precedence needs parentheses
    if child_prec < parent_prec:
        return True
    
    # Same precedence on right side of non-associative operators
    if child_prec == parent_prec and is_right:
        # Check for right-associative operators (like **)
        return type(parent_op).__name__ not in ['Pow']
    
    return False

# Example usage
code = "a - b + c"  # Parsed as (a - b) + c
tree = ast.parse(code, mode='eval')
binop = tree.body

# Check if we need parentheses for sub-expressions
left_needs_parens = needs_parens(binop.op, binop.left.op, is_right=False)
print(f"Left side needs parentheses: {left_needs_parens}")

Custom Operator Formatting

Using the formatting capabilities for specialized code generation.

Usage Example:

import ast
import astor

def format_operator_with_spaces(op_node):
    """Format operator with surrounding spaces."""
    symbol = astor.get_op_symbol(op_node, fmt=' %s ')
    return symbol

# Parse and format expression
code = "a+b*c"
tree = ast.parse(code, mode='eval')

# Manually format with spacing
def add_spaces_to_binops(node):
    if isinstance(node, ast.BinOp):
        left = add_spaces_to_binops(node.left) 
        right = add_spaces_to_binops(node.right)
        op_symbol = format_operator_with_spaces(node.op)
        return f"{left}{op_symbol}{right}"
    elif isinstance(node, ast.Name):
        return node.id
    elif isinstance(node, ast.Constant):
        return str(node.value)
    return str(node)

formatted = add_spaces_to_binops(tree.body)
print(formatted)  # "a + b * c"

Deprecated Operator Functions

For backward compatibility, astor provides deprecated aliases for operator functions:

# Deprecated aliases (use get_op_symbol instead)
def get_boolop(obj): ...    # → get_op_symbol
def get_binop(obj): ...     # → get_op_symbol  
def get_cmpop(obj): ...     # → get_op_symbol
def get_unaryop(obj): ...   # → get_op_symbol
def get_anyop(obj): ...     # → get_op_symbol

# Deprecated alias (use symbol_data instead)
all_symbols: dict  # → symbol_data

These functions are maintained for compatibility but should not be used in new code. Use get_op_symbol() and symbol_data instead.

Install with Tessl CLI

npx tessl i tessl/pypi-astor

docs

ast-to-source.md

file-operations.md

index.md

operator-utilities.md

tree-manipulation.md

tile.json