or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/pypi-executing

Get the currently executing AST node of a frame, and other information

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/executing@2.2.x

To install, run

npx @tessl/cli install tessl/pypi-executing@2.2.0

index.mddocs/

Executing

Get information about what a frame is currently doing, particularly the AST node being executed. This mini-library enables Python developers to determine which AST node is currently executing in a frame, obtain the source code of that node, and get the qualname of the current function. Designed for debugging tools, development utilities, and introspection libraries.

Package Information

  • Package Name: executing
  • Package Type: pypi
  • Language: Python
  • Installation: pip install executing

Core Imports

import executing

For pytest compatibility checking:

from executing import is_pytest_compatible

Basic Usage

import executing
import inspect

def example_function():
    # Get the currently executing AST node
    frame = inspect.currentframe()
    node = executing.Source.executing(frame).node
    
    if node:
        # Get the source code of the executing node
        source_text = executing.Source.executing(frame).text()
        print(f"Currently executing: {source_text}")
        
        # Get the qualified name of the current function
        qualname = executing.Source.executing(frame).code_qualname()
        print(f"Function qualname: {qualname}")
    else:
        print("Could not identify the executing node")

# Usage with traceback objects
try:
    some_function()
except Exception:
    import sys
    tb = sys.exc_info()[2]
    node = executing.Source.executing(tb).node
    if node:
        print(f"Exception occurred at: {executing.Source.executing(tb).text()}")

Architecture

The executing library works by analyzing bytecode instructions and matching them to AST nodes through compilation tricks:

  • Source: Manages source code files and their AST representations, caching instances by filename
  • Executing: Represents information about what operation a frame is currently executing
  • Node Matching: Uses bytecode analysis with sentinel transformations to identify which AST node corresponds to the current instruction
  • AST Enhancement: Adds parent references to AST nodes for navigation and analysis

The library supports identifying Call, Attribute, Subscript, BinOp, UnaryOp, and Compare AST node types through clever bytecode inspection and AST modification techniques.

Capabilities

Frame Analysis

Get information about what a frame is currently executing, including the AST node being executed and associated metadata.

class Source:
    @classmethod
    def executing(cls, frame_or_tb) -> "Executing":
        """
        Returns an Executing object representing the operation
        currently executing in the given frame or traceback object.
        
        Parameters:
        - frame_or_tb: types.FrameType or types.TracebackType
        
        Returns:
        Executing object with node, source, and metadata
        """
    
    @classmethod
    def for_frame(cls, frame, use_cache=True) -> "Source":
        """
        Returns the Source object corresponding to the file the frame is executing in.
        
        Parameters:
        - frame: types.FrameType - the frame to analyze
        - use_cache: bool - whether to use cached Source instances
        
        Returns:
        Source object for the frame's file
        """
    
    @classmethod  
    def for_filename(cls, filename, module_globals=None, use_cache=True) -> "Source":
        """
        Returns Source object for a specific filename.
        
        Parameters:
        - filename: str or Path - path to the source file
        - module_globals: dict, optional - module globals for linecache
        - use_cache: bool - whether to use cached instances
        
        Returns:
        Source object for the specified file
        """

Source Code Analysis

Analyze source files and extract information about AST nodes, statements, and code structure.

class Source:
    def statements_at_line(self, lineno) -> Set[ast.stmt]:
        """
        Returns the statement nodes overlapping the given line.
        
        Parameters:
        - lineno: int - line number to analyze
        
        Returns:
        Set of AST statement nodes at the specified line
        """
    
    def asttokens(self) -> "ASTTokens":
        """
        Returns an ASTTokens object for getting the source of specific AST nodes.
        Requires asttokens library to be installed separately.
        
        Returns:
        ASTTokens object for source code analysis
        """
    
    def asttext(self) -> "ASTText":  
        """
        Returns an ASTText object for getting the source of specific AST nodes.
        Requires asttokens library to be installed separately.
        
        Returns:
        ASTText object for source code analysis
        """
    
    def code_qualname(self, code) -> str:
        """
        Imitates the __qualname__ attribute of functions for code objects.
        
        Parameters:
        - code: types.CodeType - code object to analyze
        
        Returns:
        Qualified name string for the code object
        """

Execution Information

Access detailed information about the currently executing operation, including source text and qualified names.

class Executing:
    def code_qualname(self) -> str:
        """
        Returns the qualified name of the function being executed.
        
        Returns:
        String representing the function's qualified name
        """
    
    def text(self) -> str:
        """
        Returns the source code text of the executing node.
        Requires asttokens library to be installed separately.
        
        Returns:
        Source code string of the executing AST node
        """
    
    def text_range(self) -> Tuple[int, int]:
        """
        Returns the character range of the executing node in the source.
        Requires asttokens library to be installed separately.
        
        Returns:
        Tuple of (start_pos, end_pos) character positions
        """

Utility Functions

Helper functions for working with iterables and checking compatibility with testing frameworks.

def only(it: Iterable[T]) -> T:
    """
    Extract single value from iterable, raising NotOneValueFound if not exactly one.
    
    Parameters:
    - it: Iterable[T] - iterable to extract value from
    
    Returns:
    T - The single value from the iterable
    
    Raises:
    NotOneValueFound - if iterable contains zero or multiple values
    """

def is_pytest_compatible() -> bool:
    """
    Returns True if executing can be used for expressions inside assert statements
    which are rewritten by pytest. Requires Python 3.11+ and pytest 8.3.4+.
    
    Returns:
    Boolean indicating pytest compatibility
    """

cache = lru_cache(maxsize=None)
"""LRU cache with no size limit for performance optimization."""

future_flags: int
"""
Sum of all __future__ compiler flags.

This is calculated as:
sum(getattr(__future__, fname).compiler_flag for fname in __future__.all_feature_names)

Used internally for compiling code with the same future imports as the original code.
"""

Source Utilities

Static methods for handling source code encoding and text processing.

class Source:
    @staticmethod
    def decode_source(source) -> str:
        """
        Decode source code from bytes or return string as-is.
        
        Parameters:
        - source: str or bytes - source code to decode
        
        Returns:
        Decoded source code as string
        """
    
    @staticmethod
    def detect_encoding(source) -> str:
        """
        Detect encoding of source code bytes.
        
        Parameters:
        - source: bytes - source code bytes
        
        Returns:
        Encoding name as string
        """

Types

class Executing:
    """
    Information about the operation a frame is currently executing.
    
    Attributes:
    - frame: types.FrameType - the frame being analyzed
    - source: Source - Source object for the frame's file  
    - node: ast.AST or None - AST node being executed
    - statements: Set[ast.stmt] - set of statement nodes
    - decorator: ast.AST or None - decorator expression being called (if applicable)
    """

class Source:
    """
    The source code of a single file and associated metadata.
    
    Attributes:
    - filename: str - source filename
    - text: str - complete source text
    - lines: List[str] - list of source lines
    - tree: ast.Module or None - AST parsed from text (None if invalid Python)
    """

class NotOneValueFound(Exception):
    """
    Raised when expected exactly one value but got zero or multiple.
    
    Attributes:
    - values: Sequence - values found when multiple (empty when zero)
    """

class KnownIssue(Exception):
    """
    Raised in case of a known problem, mostly because of CPython bugs.
    Executing.node gets set to None in this case.
    """

class VerifierFailure(Exception):
    """
    Thrown for an unexpected mapping from instruction to AST node.
    Executing.node gets set to None in this case.
    
    Attributes:
    - node: object - the AST node that failed verification
    - instruction: object - the bytecode instruction that failed verification
    """

Error Handling

The executing library handles various edge cases and potential issues:

  • Invalid Python code: Returns None for tree attribute in Source objects
  • Unidentifiable nodes: Returns None for node attribute in Executing objects
  • Missing dependencies: Methods requiring asttokens will raise ImportError if not installed
  • Bytecode analysis failures: Gracefully handles cases where AST-to-bytecode matching fails

Always check if the returned node is not None before using it, as node identification may fail in complex cases or with certain bytecode optimizations.

Supported AST Node Types

The executing library can currently identify these AST node types:

  • Call: Function and method calls (e.g., func(), obj.method())
  • Attribute: Attribute access (e.g., obj.attr)
  • Subscript: Indexing and slicing (e.g., lst[0], dict['key'])
  • BinOp: Binary operations (e.g., x + y, a * b) - excludes and/or
  • UnaryOp: Unary operations (e.g., -x, not condition) - not has limited support
  • Compare: Comparison operations (e.g., a < b, x == y) - excludes chained comparisons

The library works by modifying AST nodes with sentinel values and analyzing the resulting bytecode changes to determine which node corresponds to the current instruction.