A library for stubbing in Python
npx @tessl/cli install tessl/pypi-pretend@1.0.00
# Pretend
1
2
A 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.
3
4
## Package Information
5
6
- **Package Name**: pretend
7
- **Language**: Python
8
- **Installation**: `pip install pretend`
9
- **License**: BSD (3-clause)
10
- **Python Support**: 2.6, 2.7, 3.2+
11
12
## Core Imports
13
14
```python
15
from pretend import stub, raiser, call, call_recorder
16
```
17
18
For version checking and constants:
19
20
```python
21
from pretend import PY3K, MAGIC_METHODS
22
```
23
24
## Basic Usage
25
26
```python
27
from pretend import stub, raiser, call_recorder, call
28
29
# Create a simple stub with attributes
30
user = stub(name="Alice", country_code="US")
31
print(user.name) # "Alice"
32
print(user.country_code) # "US"
33
34
# Create a stub with methods (pre-canned responses)
35
api_client = stub(
36
get_user=lambda user_id: {"id": user_id, "name": "Alice"},
37
delete_user=lambda user_id: True
38
)
39
result = api_client.get_user(123)
40
print(result) # {"id": 123, "name": "Alice"}
41
42
# Stub methods that raise exceptions
43
failing_service = stub(
44
connect=raiser(ConnectionError("Service unavailable"))
45
)
46
# failing_service.connect() # Raises ConnectionError
47
48
# Record calls made to functions
49
recorded_func = call_recorder(lambda x, y: x + y)
50
result = recorded_func(1, 2) # Returns 3
51
print(recorded_func.calls) # [call(1, 2)]
52
```
53
54
## Capabilities
55
56
### Basic Stubbing
57
58
Create stub objects with arbitrary attributes and methods that return pre-canned values.
59
60
```python { .api }
61
class stub:
62
"""
63
Creates a stub object with the provided keyword arguments as attributes.
64
65
Supports all Python magic methods (dunder methods) for advanced stubbing.
66
Functions on stubs do not take a 'self' argument as they return pre-canned values.
67
"""
68
def __init__(self, **kwargs):
69
"""
70
Initialize stub with arbitrary attributes.
71
72
Parameters:
73
- **kwargs: Arbitrary keyword arguments to set as attributes
74
"""
75
76
def __repr__(self):
77
"""String representation showing all attributes."""
78
```
79
80
**Usage Examples:**
81
82
```python
83
# Basic attribute stubbing
84
user = stub(id=123, name="Alice", active=True)
85
86
# Method stubbing with lambda functions
87
calculator = stub(
88
add=lambda x, y: x + y,
89
multiply=lambda x, y: x * y
90
)
91
92
# Magic method stubbing for container behavior
93
fake_list = stub(
94
__len__=lambda: 5,
95
__getitem__=lambda idx: f"item_{idx}",
96
__contains__=lambda item: item == "special"
97
)
98
print(len(fake_list)) # 5
99
print(fake_list[0]) # "item_0"
100
print("special" in fake_list) # True
101
102
# Context manager stubbing
103
fake_context = stub(
104
__enter__=lambda: "entered",
105
__exit__=lambda exc_type, exc_val, exc_tb: None
106
)
107
with fake_context as value:
108
print(value) # "entered"
109
```
110
111
### Exception Stubbing
112
113
Create functions that raise specific exceptions when called.
114
115
```python { .api }
116
def raiser(exc):
117
"""
118
Create a function that raises the specified exception when called.
119
120
Parameters:
121
- exc: Exception instance or exception class to raise
122
123
Returns:
124
Callable that raises the exception when invoked
125
126
Raises:
127
- TypeError: If exc is not an exception instance or class
128
"""
129
```
130
131
**Usage Examples:**
132
133
```python
134
# Raise exception instances
135
error_func = raiser(ValueError("Invalid input"))
136
# error_func() # Raises ValueError("Invalid input")
137
138
# Raise exception classes
139
timeout_func = raiser(TimeoutError)
140
# timeout_func() # Raises TimeoutError()
141
142
# Use with stubs for failing methods
143
failing_api = stub(
144
connect=raiser(ConnectionError("Network unreachable")),
145
authenticate=raiser(PermissionError("Invalid credentials"))
146
)
147
```
148
149
### Call Recording
150
151
Record all calls made to a function while preserving its original behavior.
152
153
```python { .api }
154
def call_recorder(func):
155
"""
156
Decorator that records all calls made to a function.
157
158
Parameters:
159
- func: Function to wrap and record calls for
160
161
Returns:
162
Wrapped function with 'calls' attribute containing list of call objects
163
164
The wrapped function preserves the original function's behavior and metadata.
165
"""
166
167
class call:
168
"""
169
Represents a function call with its arguments and keyword arguments.
170
171
Used to track calls made to functions wrapped with call_recorder.
172
"""
173
def __init__(self, *args, **kwargs):
174
"""
175
Initialize call record.
176
177
Parameters:
178
- *args: Positional arguments from the call
179
- **kwargs: Keyword arguments from the call
180
"""
181
182
def __eq__(self, other):
183
"""Compare two call objects for equality."""
184
185
def __ne__(self, other):
186
"""Compare two call objects for inequality."""
187
188
def __hash__(self):
189
"""Hash support for use in sets and dictionaries."""
190
191
def __repr__(self):
192
"""String representation of the call."""
193
```
194
195
**Usage Examples:**
196
197
```python
198
# Record calls to a function
199
@call_recorder
200
def add(x, y):
201
return x + y
202
203
result1 = add(1, 2) # Returns 3
204
result2 = add(x=5, y=10) # Returns 15
205
206
print(add.calls) # [call(1, 2), call(x=5, y=10)]
207
208
# Compare calls
209
call1 = call(1, 2)
210
call2 = call(1, 2)
211
call3 = call(2, 1)
212
print(call1 == call2) # True
213
print(call1 == call3) # False
214
215
# Use calls in assertions (common testing pattern)
216
assert add.calls == [call(1, 2), call(x=5, y=10)]
217
```
218
219
### Version Detection
220
221
Check Python version for compatibility handling.
222
223
```python { .api }
224
PY3K: bool
225
"""
226
Boolean constant indicating if running on Python 3.x.
227
Value is True for Python 3.x, False for Python 2.x.
228
"""
229
```
230
231
**Usage Example:**
232
233
```python
234
from pretend import PY3K
235
236
if PY3K:
237
# Python 3 specific behavior
238
print("Running on Python 3")
239
else:
240
# Python 2 specific behavior
241
print("Running on Python 2")
242
```
243
244
### Magic Methods Constants
245
246
Access to the set of magic methods supported by stub objects.
247
248
```python { .api }
249
MAGIC_METHODS: frozenset
250
"""
251
Frozenset containing all magic method names supported by stub objects.
252
Includes container methods, comparison operators, arithmetic operators,
253
and special methods like __call__, __repr__, __enter__, __exit__.
254
255
This constant is primarily used internally but may be useful for
256
advanced introspection or extending stub functionality.
257
"""
258
```
259
260
**Usage Example:**
261
262
```python
263
from pretend import MAGIC_METHODS
264
265
# Check which magic methods are supported
266
print("__len__" in MAGIC_METHODS) # True
267
print("__call__" in MAGIC_METHODS) # True
268
print("__custom__" in MAGIC_METHODS) # False
269
270
# See all supported magic methods
271
print(sorted(MAGIC_METHODS))
272
```
273
274
## Types
275
276
```python { .api }
277
class stub:
278
"""
279
A flexible stub object that can have arbitrary attributes and methods.
280
Supports all Python magic methods for advanced behavior stubbing.
281
"""
282
def __init__(self, **kwargs): ...
283
def __repr__(self): ...
284
285
class call:
286
"""
287
Represents a recorded function call with arguments and keyword arguments.
288
"""
289
args: tuple
290
kwargs: dict
291
292
def __init__(self, *args, **kwargs): ...
293
def __eq__(self, other): ...
294
def __ne__(self, other): ...
295
def __hash__(self): ...
296
def __repr__(self): ...
297
298
# Type annotations for function signatures
299
from typing import Callable, Any, List, Union
300
301
def raiser(exc: Union[Exception, type]) -> Callable[..., None]: ...
302
303
def call_recorder(func: Callable[..., Any]) -> Callable[..., Any]:
304
# The returned function has an additional 'calls' attribute
305
...
306
307
PY3K: bool
308
MAGIC_METHODS: frozenset
309
```
310
311
## Magic Methods Support
312
313
The stub class supports all Python magic methods (dunder methods) for comprehensive behavior stubbing:
314
315
**Container Methods:**
316
- `__len__`, `__getitem__`, `__setitem__`, `__delitem__`, `__contains__`, `__iter__`, `__next__` (Python 3)
317
318
**Comparison Operators:**
319
- `__lt__`, `__le__`, `__eq__`, `__ne__`, `__gt__`, `__ge__`
320
321
**Arithmetic Operators:**
322
- `__add__`, `__sub__`, `__mul__`, `__truediv__`, `__div__` (Python 2), `__floordiv__`, `__mod__`, `__pow__`
323
- `__and__`, `__or__`, `__xor__`, `__lshift__`, `__rshift__`, `__divmod__`
324
325
**Special Methods:**
326
- `__call__` (make stub callable), `__repr__`, `__bool__` (Python 3), `__nonzero__` (Python 2)
327
- `__enter__`, `__exit__` (context manager support)
328
329
These magic methods enable stubs to behave like any Python object type, making them suitable for testing complex interactions and protocols.