CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-multipledispatch

Multiple dispatch implementation for Python that enables function dispatching based on types of all non-keyword arguments

Pending
Overview
Eval results
Files

advanced-features.mddocs/

Advanced Features

Advanced dispatching capabilities including conflict resolution, variadic dispatch, custom namespaces, signature analysis, and specialized tools for complex dispatch scenarios.

Capabilities

Variadic Dispatch

Support for functions that accept variable numbers of arguments with type constraints, enabling dispatch on argument count and types simultaneously.

class VariadicSignatureMeta(type):
    """
    Metaclass that overrides __getitem__ to generate variadic signature types.
    Used internally by the Variadic class.
    """

class Variadic(metaclass=VariadicSignatureMeta):
    """
    A class whose getitem method generates new types representing variadic signatures.
    
    Usage:
    - Variadic[int] for any number of int arguments  
    - Variadic[(int, str)] for any number of arguments that are int or str
    
    Note: Most users should use list notation instead: [int] or [(int, str)]
    
    Examples:
    >>> Variadic[int]  # any number of int arguments
    <class 'multipledispatch.variadic.Variadic[int]'>
    >>> Variadic[(int, str)]  # any number of int or str arguments
    <class 'multipledispatch.variadic.Variadic[(int, str)]'>
    """

class VariadicSignatureType(type):
    """
    Type class for variadic signatures created by VariadicSignatureMeta.
    Handles subclass checking and equality for variadic signature types.
    """
    
    def __subclasscheck__(self, subclass):
        """
        Check if subclass is compatible with this variadic signature.
        
        Parameters:
        - subclass: type - Type to check
        
        Returns:
        bool: True if subclass matches variadic signature
        """
    
    def __eq__(self, other):
        """
        Check equality with another variadic signature type.
        
        Parameters:
        - other: object - Object to compare with
        
        Returns:
        bool: True if both have same variadic type
        """

def isvariadic(obj):
    """
    Check whether the type obj is variadic.
    
    Parameters:
    - obj: type - The type to check
    
    Returns:
    bool: True if type represents a variadic signature
    """

Usage Examples:

from multipledispatch import dispatch

# Variable number of integers (using list notation)
@dispatch([int])
def sum_ints(*args):
    return sum(args)

# Variable number of strings
@dispatch([str])
def concat_strings(*args):
    return ''.join(args)

# Mixed: float followed by any number of int or str
@dispatch(float, [(int, str)])
def process_mixed(x, *args):
    # Convert all args to numbers and sum with x
    return x + sum(int(arg) for arg in args)

# Usage  
sum_ints(1, 2, 3, 4)                    # -> 10
concat_strings("a", "b", "c")           # -> "abc"
process_mixed(1.0, 2, '3', 4)          # -> 10.0
process_mixed(2.0, '4', 6, 8)          # -> 20.0

# The Variadic class is used internally but can be accessed:
from multipledispatch import Variadic

# This is equivalent to @dispatch([int]):
@dispatch(Variadic[int])  
def internal_sum(*args):
    return sum(args)

Namespace Management

Custom namespaces for dispatch isolation, enabling multiple independent dispatch systems and avoiding conflicts between different parts of an application.

# Global namespace (default)
global_namespace = dict  # Automatically used when no namespace specified

# Custom namespace creation
def dispatch(*types, namespace=None):
    """
    Dispatch decorator with namespace support.
    
    Parameters:
    - *types: Type signatures
    - namespace: dict (optional) - Custom namespace for isolation
    """

Usage Examples:

# Create isolated namespaces
math_namespace = {}
string_namespace = {}

# Math operations in isolated namespace
@dispatch(int, int, namespace=math_namespace)
def combine(x, y):
    return x + y

# String operations in different namespace  
@dispatch(str, str, namespace=string_namespace)
def combine(x, y):
    return x + y

# Each namespace resolves independently
math_combine = math_namespace['combine']
string_combine = string_namespace['combine']

Conflict Resolution and Ordering

Sophisticated conflict detection and resolution system that ensures deterministic dispatch behavior through topological ordering of type signatures.

def halt_ordering():
    """
    Temporarily disable signature ordering (DEPRECATED).
    Used for performance during bulk registration.
    """

def restart_ordering(on_ambiguity=None):
    """
    Re-enable signature ordering with ambiguity handling (DEPRECATED).
    
    Parameters:
    - on_ambiguity: callable (optional) - Handler for ambiguous signatures
    """

# Signature analysis functions
def supercedes(a, b):
    """
    Check if signature A is more specific than signature B.
    
    Parameters:
    - a: tuple - First signature
    - b: tuple - Second signature
    
    Returns:
    bool: True if A supercedes B
    """

def ambiguous(a, b):
    """
    Check if two signatures are ambiguous (neither supercedes the other).
    
    Parameters:
    - a: tuple - First signature  
    - b: tuple - Second signature
    
    Returns:
    bool: True if signatures are ambiguous
    """

def ambiguities(signatures):
    """
    Find all ambiguous signature pairs in a collection.
    
    Parameters:
    - signatures: iterable - Collection of type signatures
    
    Returns:
    set: Pairs of ambiguous signatures
    """

def super_signature(signatures):
    """
    Generate a signature that would break ambiguities between given signatures.
    
    Parameters:
    - signatures: list - List of ambiguous signatures
    
    Returns:
    list: Super signature that disambiguates the inputs
    """

class AmbiguityWarning(UserWarning):
    """
    Warning issued when ambiguous type signatures are detected during dispatch registration.
    """

Usage Examples:

from multipledispatch.conflict import supercedes, ambiguous

# Check signature relationships
sig1 = (int, int)
sig2 = (object, object)

print(supercedes(sig1, sig2))  # True - int is more specific than object

# Example of ambiguous signatures that would cause warnings
from multipledispatch import dispatch

@dispatch(int, str)
def process(x, y):
    return f"int-str: {x}-{y}"

@dispatch(str, int)  
def process(x, y):
    return f"str-int: {x}-{y}"

# These are ambiguous - neither is more specific
# The library will warn and establish consistent ordering

Signature Analysis and Utilities

Tools for analyzing type signatures, managing dispatch state, and debugging dispatch behavior.

def typename(type_obj):
    """
    Get readable name for a type or tuple of types.
    
    Parameters:
    - type_obj: type or tuple - Type(s) to get name for
    
    Returns:
    str: Human-readable type name
    """

def str_signature(signature):
    """
    Create string representation of a type signature.
    
    Parameters:
    - signature: tuple - Type signature
    
    Returns:
    str: String representation
    """

def source(func):
    """
    Get source code for a function.
    
    Parameters:
    - func: callable - Function to inspect
    
    Returns:
    str: Source code
    """

class AmbiguityWarning(UserWarning):
    """
    Warning issued when ambiguous signatures are detected.
    """

Dispatcher Introspection

Advanced inspection capabilities for debugging and analyzing dispatch behavior.

class Dispatcher:
    def help(self, *args, **kwargs):
        """
        Display help information for dispatched function.
        
        Parameters:
        - *args: Type signature to get help for (optional)
        """
    
    def source(self, *args, **kwargs):
        """
        Display source code for specific implementation.
        
        Parameters:
        - *args: Type signature to get source for (optional)
        """
    
    def dispatch_iter(self, *types):
        """
        Iterator over all possible implementations for given types.
        
        Parameters:
        - *types: Types to find implementations for
        
        Yields:
        callable: Implementation functions in priority order
        """
    
    @property
    def ordering(self):
        """
        Get the current signature ordering for this dispatcher.
        
        Returns:
        list: Ordered list of signatures from most to least specific
        """

Usage Examples:

from multipledispatch import Dispatcher

# Create dispatcher for inspection
calc = Dispatcher('calc')

@calc.register(int, int)
def calc_impl(x, y):
    return x + y

@calc.register(float, float)
def calc_impl(x, y):
    return x + y

# Inspect dispatcher state
calc.help()                    # Show all implementations
calc.help(int, int)           # Show specific implementation
calc.source(int, int)         # Show source code

# Check ordering
print(calc.ordering)          # [(int, int), (float, float), ...]

# Iterate through possible implementations
for impl in calc.dispatch_iter(int, int):
    print(f"Implementation: {impl}")

Performance and Caching

Built-in caching system and performance optimization features for high-frequency dispatch scenarios.

class Dispatcher:
    # Internal caching system
    _cache = dict  # Type signature -> implementation cache
    
    def reorder(self, on_ambiguity=None):
        """
        Recompute signature ordering and clear cache.
        
        Parameters:
        - on_ambiguity: callable (optional) - Ambiguity handler
        """

Performance Characteristics:

  • O(1) dispatch after cache warming for repeated type patterns
  • Static conflict detection at registration time prevents runtime errors
  • Topological ordering ensures consistent, deterministic resolution
  • Inheritance-aware caching handles subclass relationships efficiently

Example:

# High-performance dispatcher with caching
@dispatch(int, int)
def fast_add(x, y):
    return x + y

# First call builds cache
result1 = fast_add(1, 2)  # Slower - cache miss

# Subsequent calls with same types are cached
result2 = fast_add(3, 4)  # Faster - cache hit
result3 = fast_add(5, 6)  # Faster - cache hit

Utility Functions

Core utility functions used internally by the dispatch system and available for advanced use cases.

def typename(type_obj):
    """
    Get readable name for a type or tuple of types.
    
    Parameters:
    - type_obj: type or tuple - Type(s) to get name for
    
    Returns:
    str: Human-readable type name
    """

def str_signature(signature):
    """
    Create string representation of a type signature.
    
    Parameters:
    - signature: tuple - Type signature
    
    Returns:
    str: String representation (e.g., "int, float")
    """

def source(func):
    """
    Get source code for a function with file information.
    
    Parameters:
    - func: callable - Function to inspect
    
    Returns:
    str: Source code with file path header
    """

def warning_text(name, ambiguities):
    """
    Generate warning text for ambiguous signatures.
    
    Parameters:
    - name: str - Function name
    - ambiguities: set - Pairs of ambiguous signatures
    
    Returns:
    str: Formatted warning message with suggested fixes
    """

def expand_tuples(signature_list):
    """
    Expand union types in signature list into individual signatures.
    
    Parameters:
    - signature_list: list - List containing types and union tuples
    
    Returns:
    list: All possible signature combinations
    """

def groupby(func, seq):
    """
    Group a collection by a key function.
    
    Parameters:
    - func: callable - Key function to group by
    - seq: iterable - Sequence to group
    
    Returns:
    dict: Grouped items by key
    """

def reverse_dict(dependency_dict):
    """
    Reverse direction of dependency dictionary.
    
    Parameters:
    - dependency_dict: dict - Dict mapping keys to dependent values
    
    Returns:
    dict: Reversed dependency mapping
    """

def raises(error_type, func):
    """
    Test if function raises specified exception type.
    
    Parameters:
    - error_type: Exception - Exception type to check for
    - func: callable - Function to test
    
    Returns:
    bool: True if function raises the exception
    """

Usage Examples:

from multipledispatch.utils import typename, str_signature
from multipledispatch.conflict import supercedes, ambiguous

# Type name utilities
print(typename(int))           # -> "int"
print(typename((int, float)))  # -> "(int, float)"

# Signature analysis
sig1 = (int, str)
sig2 = (object, str)
print(str_signature(sig1))     # -> "int, str"
print(supercedes(sig1, sig2))  # -> True (int more specific than object)

# Check for ambiguity
sig3 = (str, int)
print(ambiguous(sig1, sig3))   # -> True (neither supercedes the other)

Install with Tessl CLI

npx tessl i tessl/pypi-multipledispatch

docs

advanced-features.md

core-dispatch.md

index.md

tile.json