CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-waitress

A production-quality pure-Python WSGI server with robust HTTP protocol support and comprehensive configuration options

Pending
Overview
Eval results
Files

buffer-management.mddocs/

Buffer Management

Efficient memory and file-based buffer system for handling request and response data with automatic overflow management and streaming capabilities.

Capabilities

Buffer Base Class

Foundation class for all buffer implementations providing common interface and operations.

class FileBasedBuffer:
    """
    Base class for file-like buffer implementations.
    
    Provides common buffering operations with support for reading,
    writing, seeking, and efficient data management across different
    storage backends (memory, temporary files).
    """
    
    remain: int = 0  # Number of bytes remaining to be read
    
    def __init__(self, file, from_buffer=None):
        """
        Initialize buffer with file-like object.
        
        Parameters:
        - file: File-like object for data storage
        - from_buffer: Optional existing buffer to copy data from
        """
    
    def __len__(self):
        """
        Get number of bytes remaining in buffer.
        
        Returns:
        int: Number of unread bytes
        """
    
    def __bool__(self):
        """
        Check if buffer exists (always True for FileBasedBuffer).
        
        Returns:
        bool: Always True
        """
    
    def append(self, s):
        """
        Append data to buffer.
        
        Parameters:
        - s (bytes): Data to append to buffer
        
        Notes:
        - Maintains current read position
        - Updates remaining byte count
        """
    
    def get(self, numbytes=-1, skip=False):
        """
        Read data from buffer.
        
        Parameters:
        - numbytes (int): Number of bytes to read (-1 for all)
        - skip (bool): Whether to advance read position
        
        Returns:
        bytes: Read data
        
        Notes:
        - If skip=False, read position unchanged
        - If skip=True, data is consumed from buffer
        """
    
    def skip(self, numbytes, allow_prune=0):
        """
        Skip bytes in buffer without reading.
        
        Parameters:
        - numbytes (int): Number of bytes to skip
        - allow_prune (int): Unused parameter for compatibility
        
        Raises:
        ValueError: If trying to skip more bytes than available
        """
    
    def newfile(self):
        """
        Create new file-like object for buffer.
        
        Returns:
        File-like object
        
        Notes:
        - Must be implemented by subclasses
        - Used during buffer pruning operations
        """
    
    def prune(self):
        """
        Remove consumed data to free memory/disk space.
        
        Creates new file with only unread data, discarding
        data that has already been consumed.
        """
    
    def getfile(self):
        """
        Get underlying file-like object.
        
        Returns:
        File-like object used for storage
        """
    
    def close(self):
        """
        Close buffer and release resources.
        
        Closes underlying file if it has a close method
        and resets remaining byte count to zero.
        """

Memory-Based Buffer

In-memory buffer implementation using BytesIO for small to medium sized data.

class BytesIOBasedBuffer(FileBasedBuffer):
    """
    Memory-based buffer using BytesIO for storage.
    
    Efficient for small to medium sized data that fits
    comfortably in memory. Faster than file-based alternatives
    but limited by available RAM.
    """
    
    def __init__(self, from_buffer=None):
        """
        Initialize memory-based buffer.
        
        Parameters:
        - from_buffer: Optional existing buffer to copy data from
        
        Notes:
        - Uses BytesIO for in-memory storage
        - No file system involvement
        """
    
    def newfile(self):
        """
        Create new BytesIO object.
        
        Returns:
        BytesIO: New in-memory file-like object
        """

Temporary File Buffer

File-based buffer using temporary files for large data that exceeds memory limits.

class TempfileBasedBuffer(FileBasedBuffer):
    """
    File-based buffer using temporary files for storage.
    
    Automatically handles large data by storing it in temporary
    files, providing unlimited capacity limited only by disk space.
    Files are automatically cleaned up when buffer is closed.
    """
    
    def __init__(self, from_buffer=None):
        """
        Initialize temporary file-based buffer.
        
        Parameters:
        - from_buffer: Optional existing buffer to copy data from
        
        Notes:
        - Creates temporary file for storage
        - File is automatically deleted when closed
        """
    
    def newfile(self):
        """
        Create new temporary file.
        
        Returns:
        TemporaryFile: New temporary file object
        
        Notes:
        - File created in binary mode ("w+b")
        - Automatically deleted when closed
        """

Read-Only File Buffer

Specialized buffer for serving static files efficiently with WSGI file_wrapper support.

class ReadOnlyFileBasedBuffer(FileBasedBuffer):
    """
    Read-only buffer for serving existing files efficiently.
    
    Optimized for serving static files as WSGI responses with
    support for range requests and efficient streaming. Used
    as wsgi.file_wrapper for optimal file serving performance.
    """
    
    def __init__(self, file, block_size=32768):
        """
        Initialize read-only file buffer.
        
        Parameters:
        - file: File-like object to read from
        - block_size (int): Block size for iteration (default: 32KB)
        
        Notes:
        - File must be opened in binary read mode
        - Supports seekable and non-seekable files
        """
    
    block_size: int      # Block size for iteration
    seekable: callable   # Seekable check function (if available)
    
    def __iter__(self):
        """
        Iterate over file contents in blocks.
        
        Yields:
        bytes: File data in block_size chunks
        
        Notes:
        - Efficient for WSGI response streaming
        - Automatically handles file positioning
        """
    
    def __next__(self):
        """
        Get next block of file data.
        
        Returns:
        bytes: Next block of data
        
        Raises:
        StopIteration: When end of file reached
        """
    
    def close(self):
        """
        Close the underlying file.
        
        Notes:
        - Only closes if file has close method
        - Safe to call multiple times
        """

Overflowable Buffer

Advanced buffer that automatically switches between memory and file storage based on size.

class OverflowableBuffer:
    """
    Buffer that overflows from memory to temporary files.
    
    Starts with in-memory storage for efficiency and automatically
    switches to temporary file storage when data exceeds the
    configured overflow threshold.
    """
    
    def __init__(self, overflow_threshold):
        """
        Initialize overflowable buffer.
        
        Parameters:
        - overflow_threshold (int): Byte limit before switching to file
        
        Notes:
        - Starts with BytesIOBasedBuffer
        - Switches to TempfileBasedBuffer when threshold exceeded
        """
    
    def append(self, data):
        """
        Append data with automatic overflow handling.
        
        Parameters:
        - data (bytes): Data to append
        
        Notes:
        - Automatically switches to file storage if needed
        - Transparent to caller after overflow
        """
    
    def get(self, numbytes=-1, skip=False):
        """
        Read data from buffer (delegates to underlying buffer).
        
        Parameters:
        - numbytes (int): Number of bytes to read
        - skip (bool): Whether to consume data
        
        Returns:
        bytes: Read data
        """
    
    def __len__(self):
        """Get number of bytes in buffer."""
    
    def close(self):
        """Close buffer and clean up resources."""

Buffer Constants

Important constants controlling buffer behavior and performance characteristics.

# Buffer copy operations
COPY_BYTES: int = 262144  # 256KB - chunk size for copying data between buffers

# String buffer limits  
STRBUF_LIMIT: int = 8192  # 8KB - maximum size for simple string buffers

Buffer Usage Examples

Common patterns for working with waitress buffer system.

Basic Buffer Operations

from waitress.buffers import BytesIOBasedBuffer, TempfileBasedBuffer

# Memory-based buffer for small data
memory_buffer = BytesIOBasedBuffer()
memory_buffer.append(b"Hello, ")
memory_buffer.append(b"World!")

# Read data without consuming
data = memory_buffer.get()
print(data)  # b"Hello, World!"
print(len(memory_buffer))  # 13

# Read and consume data
consumed = memory_buffer.get(5, skip=True)
print(consumed)  # b"Hello"
print(len(memory_buffer))  # 8

# File-based buffer for large data
file_buffer = TempfileBasedBuffer()
large_data = b"x" * 1000000  # 1MB of data
file_buffer.append(large_data)
print(len(file_buffer))  # 1000000

Overflowable Buffer Usage

from waitress.buffers import OverflowableBuffer

# Buffer that overflows at 64KB
buffer = OverflowableBuffer(65536)

# Add small amounts of data (stays in memory)
for i in range(1000):
    buffer.append(f"Line {i}\n".encode())

# Add large amount that triggers overflow to file
large_chunk = b"x" * 100000
buffer.append(large_chunk)  # Now using temporary file

# Usage is transparent after overflow
data = buffer.get(1000)
print(len(data))  # 1000 bytes

File Serving with ReadOnlyFileBuffer

from waitress.buffers import ReadOnlyFileBasedBuffer

def serve_file_app(environ, start_response):
    """WSGI app that serves files efficiently."""
    
    file_path = "/path/to/large/file.dat"
    
    try:
        with open(file_path, 'rb') as f:
            # Create read-only buffer for efficient serving
            file_buffer = ReadOnlyFileBasedBuffer(f, block_size=65536)
            
            status = '200 OK'
            headers = [
                ('Content-Type', 'application/octet-stream'),
                ('Content-Length', str(os.path.getsize(file_path)))
            ]
            start_response(status, headers)
            
            # Return buffer for efficient streaming
            return file_buffer
            
    except FileNotFoundError:
        status = '404 Not Found'
        headers = [('Content-Type', 'text/plain')]
        start_response(status, headers)
        return [b'File not found']

# The WSGI server will iterate over the buffer efficiently

Buffer Copying and Management

from waitress.buffers import BytesIOBasedBuffer, TempfileBasedBuffer

# Create source buffer with data
source = BytesIOBasedBuffer()
source.append(b"Important data that needs to be copied")

# Create destination buffer from source
destination = TempfileBasedBuffer(from_buffer=source)

# Both buffers now contain the same data but are independent
source_data = source.get()
dest_data = destination.get()
assert source_data == dest_data

# Modifications to one don't affect the other
source.append(b" - modified")
assert source.get() != destination.get()

# Clean up
source.close()
destination.close()

Performance Considerations

Guidelines for optimal buffer usage in different scenarios.

# Buffer selection guidelines:
SMALL_DATA = "Use BytesIOBasedBuffer (< 8KB)"       # Fastest, in-memory
MEDIUM_DATA = "Use OverflowableBuffer (8KB-1MB)"    # Adaptive
LARGE_DATA = "Use TempfileBasedBuffer (> 1MB)"      # File-based
STATIC_FILES = "Use ReadOnlyFileBasedBuffer"        # Optimized serving

# Memory usage patterns:
MEMORY_EFFICIENT = "Use file-based buffers for large data"
SPEED_OPTIMIZED = "Use memory buffers for frequently accessed data" 
BALANCED = "Use OverflowableBuffer for variable-size data"

# Buffer lifecycle:
CLEANUP_IMPORTANT = "Always call close() on file-based buffers"
TEMPORARY_FILES = "Automatically cleaned up when closed"
MEMORY_BUFFERS = "Cleaned up by garbage collector"

Integration with HTTP Processing

How buffers integrate with waitress HTTP processing pipeline.

# Request body buffering:
REQUEST_SMALL = "Stored in BytesIOBasedBuffer initially"
REQUEST_LARGE = "Overflows to TempfileBasedBuffer automatically"
REQUEST_STREAMING = "Processed incrementally as data arrives"

# Response buffering:
RESPONSE_HEADERS = "Buffered in memory for efficiency"
RESPONSE_BODY = "Uses appropriate buffer based on size"
RESPONSE_FILES = "Uses ReadOnlyFileBasedBuffer for static files"

# Connection management:
KEEP_ALIVE = "Buffers reused across requests on same connection"
PIPELINING = "Multiple request buffers managed per connection"
CLEANUP = "Buffers automatically cleaned up on connection close"

Install with Tessl CLI

npx tessl i tessl/pypi-waitress

docs

buffer-management.md

command-line.md

configuration.md

error-handling.md

http-processing.md

index.md

proxy-headers.md

server-management.md

task-management.md

tile.json