CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-hyperframe

Pure-Python HTTP/2 framing library providing comprehensive frame type support for creating, serializing, and parsing HTTP/2 frames.

Pending
Overview
Eval results
Files

frame-operations.mddocs/

Frame Operations

Core functionality for parsing HTTP/2 frames from binary data and creating new frames with proper validation and serialization support. This forms the foundation of all HTTP/2 frame handling in hyperframe.

Capabilities

Frame Base Class

The base Frame class provides common functionality for all HTTP/2 frame types including stream ID management, flag handling, and serialization/parsing infrastructure.

class Frame:
    def __init__(self, stream_id: int, flags: Iterable[str] = ()) -> None:
        """
        Initialize a frame with stream ID and optional flags.
        
        Parameters:
        - stream_id (int): Stream identifier (0 for connection-level frames)
        - flags (Iterable[str]): Initial flags to set on the frame
        
        Raises:
        - InvalidDataError: If stream_id validation fails based on stream_association
        """
    
    @property
    def stream_id(self) -> int: ...
    
    @property
    def flags(self) -> Flags: ...
    
    @property
    def body_len(self) -> int: ...
    
    def serialize(self) -> bytes:
        """
        Convert frame into binary representation.
        
        Returns:
        bytes: Complete frame including 9-byte header and body
        """
    
    def serialize_body(self) -> bytes:
        """
        Serialize frame body data. Must be implemented by subclasses.
        
        Returns:
        bytes: Frame body data
        
        Raises:
        NotImplementedError: If called on base Frame class
        """
    
    def parse_body(self, data: memoryview) -> None:
        """
        Parse frame body from binary data. Must be implemented by subclasses.
        
        Parameters:
        - data (memoryview): Body data to parse
        
        Raises:
        NotImplementedError: If called on base Frame class
        """
    
    def parse_flags(self, flag_byte: int) -> Flags:
        """
        Parse flag byte and set appropriate flags.
        
        Parameters:
        - flag_byte (int): 8-bit flag value from frame header
        
        Returns:
        Flags: Updated flags object
        """

Frame Header Parsing

Static methods for parsing frame headers and handling frame discovery from binary streams.

@staticmethod
def parse_frame_header(header: memoryview, strict: bool = False) -> tuple[Frame, int]:
    """
    Parse 9-byte frame header and return appropriate Frame object.
    
    Parameters:
    - header (memoryview): Exactly 9 bytes of frame header data
    - strict (bool): If True, raise exception for unknown frame types
    
    Returns:
    tuple[Frame, int]: Frame object and body length to read
    
    Raises:
    - InvalidFrameError: If header data is malformed
    - UnknownFrameError: If frame type unknown and strict=True
    """

@staticmethod
def explain(data: memoryview) -> tuple[Frame, int]:
    """
    Debug helper that parses and prints a complete frame.
    
    Parameters:
    - data (memoryview): Complete frame data (header + body)
    
    Returns:
    tuple[Frame, int]: Parsed frame and body length
    """

Mixin Classes

Base functionality that can be inherited by frame types supporting padding or priority information.

class Padding:
    def __init__(self, stream_id: int, pad_length: int = 0, **kwargs) -> None:
        """
        Initialize padding support.
        
        Parameters:
        - stream_id (int): Stream identifier
        - pad_length (int): Number of padding bytes to add
        - **kwargs: Additional arguments passed to parent class
        """
    
    @property
    def pad_length(self) -> int: ...
    
    def serialize_padding_data(self) -> bytes:
        """
        Serialize padding length field if PADDED flag is set.
        
        Returns:
        bytes: Padding length byte or empty if not padded
        """
    
    def parse_padding_data(self, data: memoryview) -> int:
        """
        Parse padding length from frame data if PADDED flag is set.
        
        Parameters:
        - data (memoryview): Frame body data starting with padding info
        
        Returns:
        int: Number of bytes consumed (1 if padded, 0 if not)
        
        Raises:
        - InvalidFrameError: If padding data is malformed
        """

class Priority:
    def __init__(self, stream_id: int, depends_on: int = 0, stream_weight: int = 0, 
                 exclusive: bool = False, **kwargs) -> None:
        """
        Initialize priority support.
        
        Parameters:
        - stream_id (int): Stream identifier
        - depends_on (int): Stream ID this stream depends on
        - stream_weight (int): Stream weight (0-255)
        - exclusive (bool): Whether this stream has exclusive dependency
        - **kwargs: Additional arguments passed to parent class
        """
    
    @property
    def depends_on(self) -> int: ...
    
    @property
    def stream_weight(self) -> int: ...
    
    @property
    def exclusive(self) -> bool: ...
    
    def serialize_priority_data(self) -> bytes:
        """
        Serialize 5-byte priority information.
        
        Returns:
        bytes: Priority data (4 bytes stream dependency + 1 byte weight)
        """
    
    def parse_priority_data(self, data: memoryview) -> int:
        """
        Parse priority information from frame data.
        
        Parameters:
        - data (memoryview): Frame body data starting with priority info
        
        Returns:
        int: Number of bytes consumed (always 5)
        
        Raises:
        - InvalidFrameError: If priority data is malformed
        """

Usage Examples

Basic Frame Parsing

from hyperframe.frame import Frame

# Parse frame from binary data
frame_data = b'\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x01Hello'
frame, body_length = Frame.parse_frame_header(frame_data[:9])
frame.parse_body(memoryview(frame_data[9:9 + body_length]))

print(f"Frame type: {frame.type}")
print(f"Stream ID: {frame.stream_id}")
print(f"Body length: {body_length}")

Creating Custom Frames

from hyperframe.frame import DataFrame

# Create DATA frame with padding
frame = DataFrame(
    stream_id=1,
    data=b"Hello, HTTP/2!",
    pad_length=8,
    flags=["END_STREAM", "PADDED"]
)

# Serialize to binary
binary_data = frame.serialize()
print(f"Serialized frame: {len(binary_data)} bytes")

Handling Unknown Frame Types

from hyperframe.frame import Frame, ExtensionFrame
from hyperframe.exceptions import UnknownFrameError

# Parse with strict=False to handle unknown frames
frame_data = b'\\x00\\x00\\x05\\xFF\\x00\\x00\\x00\\x00\\x01Hello'  # Type 0xFF
frame, length = Frame.parse_frame_header(frame_data[:9], strict=False)

if isinstance(frame, ExtensionFrame):
    print(f"Unknown frame type: 0x{frame.type:02X}")
    frame.parse_body(memoryview(frame_data[9:9 + length]))
    print(f"Frame body: {frame.body}")

# Parse with strict=True raises exception
try:
    Frame.parse_frame_header(frame_data[:9], strict=True)
except UnknownFrameError as e:
    print(f"Unknown frame: type=0x{e.frame_type:02X}, length={e.length}")

Install with Tessl CLI

npx tessl i tessl/pypi-hyperframe

docs

advanced-features.md

control-frames.md

data-headers.md

frame-operations.md

index.md

tile.json