A library for stubbing in Python
npx @tessl/cli install tessl/pypi-pretend@1.0.0A lightweight and simple stubbing library for Python testing that focuses on creating pre-canned responses rather than complex mocking behavior. It offers a clean API for creating objects with predefined attributes and methods, includes exception stubbing utilities, and provides optional call recording functionality.
pip install pretendfrom pretend import stub, raiser, call, call_recorderFor version checking and constants:
from pretend import PY3K, MAGIC_METHODSfrom pretend import stub, raiser, call_recorder, call
# Create a simple stub with attributes
user = stub(name="Alice", country_code="US")
print(user.name) # "Alice"
print(user.country_code) # "US"
# Create a stub with methods (pre-canned responses)
api_client = stub(
get_user=lambda user_id: {"id": user_id, "name": "Alice"},
delete_user=lambda user_id: True
)
result = api_client.get_user(123)
print(result) # {"id": 123, "name": "Alice"}
# Stub methods that raise exceptions
failing_service = stub(
connect=raiser(ConnectionError("Service unavailable"))
)
# failing_service.connect() # Raises ConnectionError
# Record calls made to functions
recorded_func = call_recorder(lambda x, y: x + y)
result = recorded_func(1, 2) # Returns 3
print(recorded_func.calls) # [call(1, 2)]Create stub objects with arbitrary attributes and methods that return pre-canned values.
class stub:
"""
Creates a stub object with the provided keyword arguments as attributes.
Supports all Python magic methods (dunder methods) for advanced stubbing.
Functions on stubs do not take a 'self' argument as they return pre-canned values.
"""
def __init__(self, **kwargs):
"""
Initialize stub with arbitrary attributes.
Parameters:
- **kwargs: Arbitrary keyword arguments to set as attributes
"""
def __repr__(self):
"""String representation showing all attributes."""Usage Examples:
# Basic attribute stubbing
user = stub(id=123, name="Alice", active=True)
# Method stubbing with lambda functions
calculator = stub(
add=lambda x, y: x + y,
multiply=lambda x, y: x * y
)
# Magic method stubbing for container behavior
fake_list = stub(
__len__=lambda: 5,
__getitem__=lambda idx: f"item_{idx}",
__contains__=lambda item: item == "special"
)
print(len(fake_list)) # 5
print(fake_list[0]) # "item_0"
print("special" in fake_list) # True
# Context manager stubbing
fake_context = stub(
__enter__=lambda: "entered",
__exit__=lambda exc_type, exc_val, exc_tb: None
)
with fake_context as value:
print(value) # "entered"Create functions that raise specific exceptions when called.
def raiser(exc):
"""
Create a function that raises the specified exception when called.
Parameters:
- exc: Exception instance or exception class to raise
Returns:
Callable that raises the exception when invoked
Raises:
- TypeError: If exc is not an exception instance or class
"""Usage Examples:
# Raise exception instances
error_func = raiser(ValueError("Invalid input"))
# error_func() # Raises ValueError("Invalid input")
# Raise exception classes
timeout_func = raiser(TimeoutError)
# timeout_func() # Raises TimeoutError()
# Use with stubs for failing methods
failing_api = stub(
connect=raiser(ConnectionError("Network unreachable")),
authenticate=raiser(PermissionError("Invalid credentials"))
)Record all calls made to a function while preserving its original behavior.
def call_recorder(func):
"""
Decorator that records all calls made to a function.
Parameters:
- func: Function to wrap and record calls for
Returns:
Wrapped function with 'calls' attribute containing list of call objects
The wrapped function preserves the original function's behavior and metadata.
"""
class call:
"""
Represents a function call with its arguments and keyword arguments.
Used to track calls made to functions wrapped with call_recorder.
"""
def __init__(self, *args, **kwargs):
"""
Initialize call record.
Parameters:
- *args: Positional arguments from the call
- **kwargs: Keyword arguments from the call
"""
def __eq__(self, other):
"""Compare two call objects for equality."""
def __ne__(self, other):
"""Compare two call objects for inequality."""
def __hash__(self):
"""Hash support for use in sets and dictionaries."""
def __repr__(self):
"""String representation of the call."""Usage Examples:
# Record calls to a function
@call_recorder
def add(x, y):
return x + y
result1 = add(1, 2) # Returns 3
result2 = add(x=5, y=10) # Returns 15
print(add.calls) # [call(1, 2), call(x=5, y=10)]
# Compare calls
call1 = call(1, 2)
call2 = call(1, 2)
call3 = call(2, 1)
print(call1 == call2) # True
print(call1 == call3) # False
# Use calls in assertions (common testing pattern)
assert add.calls == [call(1, 2), call(x=5, y=10)]Check Python version for compatibility handling.
PY3K: bool
"""
Boolean constant indicating if running on Python 3.x.
Value is True for Python 3.x, False for Python 2.x.
"""Usage Example:
from pretend import PY3K
if PY3K:
# Python 3 specific behavior
print("Running on Python 3")
else:
# Python 2 specific behavior
print("Running on Python 2")Access to the set of magic methods supported by stub objects.
MAGIC_METHODS: frozenset
"""
Frozenset containing all magic method names supported by stub objects.
Includes container methods, comparison operators, arithmetic operators,
and special methods like __call__, __repr__, __enter__, __exit__.
This constant is primarily used internally but may be useful for
advanced introspection or extending stub functionality.
"""Usage Example:
from pretend import MAGIC_METHODS
# Check which magic methods are supported
print("__len__" in MAGIC_METHODS) # True
print("__call__" in MAGIC_METHODS) # True
print("__custom__" in MAGIC_METHODS) # False
# See all supported magic methods
print(sorted(MAGIC_METHODS))class stub:
"""
A flexible stub object that can have arbitrary attributes and methods.
Supports all Python magic methods for advanced behavior stubbing.
"""
def __init__(self, **kwargs): ...
def __repr__(self): ...
class call:
"""
Represents a recorded function call with arguments and keyword arguments.
"""
args: tuple
kwargs: dict
def __init__(self, *args, **kwargs): ...
def __eq__(self, other): ...
def __ne__(self, other): ...
def __hash__(self): ...
def __repr__(self): ...
# Type annotations for function signatures
from typing import Callable, Any, List, Union
def raiser(exc: Union[Exception, type]) -> Callable[..., None]: ...
def call_recorder(func: Callable[..., Any]) -> Callable[..., Any]:
# The returned function has an additional 'calls' attribute
...
PY3K: bool
MAGIC_METHODS: frozensetThe stub class supports all Python magic methods (dunder methods) for comprehensive behavior stubbing:
Container Methods:
__len__, __getitem__, __setitem__, __delitem__, __contains__, __iter__, __next__ (Python 3)Comparison Operators:
__lt__, __le__, __eq__, __ne__, __gt__, __ge__Arithmetic Operators:
__add__, __sub__, __mul__, __truediv__, __div__ (Python 2), __floordiv__, __mod__, __pow____and__, __or__, __xor__, __lshift__, __rshift__, __divmod__Special Methods:
__call__ (make stub callable), __repr__, __bool__ (Python 3), __nonzero__ (Python 2)__enter__, __exit__ (context manager support)These magic methods enable stubs to behave like any Python object type, making them suitable for testing complex interactions and protocols.