Adapters
Bulk lifting and integration utilities for the Result Pattern.
result.adapters
Adapters: Bulk lifting and integration utilities for the Result Pattern.
This module provides tools to bridge the gap between third-party imperative APIs and the functional world of Results. This includes class-level decorators, instance proxies, and fault-tolerant iteration.
Note
Most utilities in this module use dynamic proxying or bulk decoration, which can lead to Type Erasure in some static analysis tools.
collecting
module-attribute
Utility for collecting errors from multiple exception handlers.
Examples:
Collector
Imperative error accumulator for non-short-circuiting logic.
Source code in src/result/adapters.py
SafeStream
SafeStream(gen: Iterator[Result[T, E]])
Bases: Iterable['Result[T, E]']
A wrapper around a fallible generator that provides functional transposition.
SafeStream captures exceptions during iteration and converts them into Err variants. It provides methods to transpose the entire stream into a single Result or Outcome.
Note
Like generators, a SafeStream can only be iterated once.
Initialize a SafeStream with a Result-yielding iterator.
Source code in src/result/adapters.py
__iter__
__iter__() -> Iterator[Result[T, E]]
Iterate over the stream.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the stream is iterated more than once. |
Source code in src/result/adapters.py
to_outcome
to_outcome() -> Outcome[list[T], list[E]]
Transpose the stream into a fault-tolerant Outcome (Partial Success).
Collects all success values and all error values into a single Outcome.
Source code in src/result/adapters.py
to_result
to_result() -> Result[list[T], E]
Transpose the stream into a single Result (All-or-Nothing).
If any item in the stream is an Err, the first Err encountered is returned. Otherwise, returns Ok(list) containing all success values.
Source code in src/result/adapters.py
SafeStreamAsync
SafeStreamAsync(gen: AsyncIterator[Result[T, E]])
Bases: AsyncIterable['Result[T, E]']
Async version of SafeStream for fallible asynchronous generators.
Initialize a SafeStreamAsync with a Result-yielding async iterator.
Source code in src/result/adapters.py
__aiter__
async
__aiter__() -> AsyncIterator[Result[T, E]]
Iterate over the async stream.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the stream is iterated more than once. |
Source code in src/result/adapters.py
to_outcome
async
to_outcome() -> Outcome[list[T], list[E]]
Transpose the async stream into a fault-tolerant Outcome (Partial Success).
Source code in src/result/adapters.py
to_result
async
to_result() -> Result[list[T], E]
ScopedCatch
Multi-exception type routing context manager.
Source code in src/result/adapters.py
on
Register a mapping for a specific exception type.
catch_boundary
catch_boundary(
exceptions: type[Exception]
| tuple[type[Exception], ...]
| Mapping[type[Exception], Any],
*,
map_to: Any = None,
) -> Callable[[T_cls], T_cls]
Wrap all public methods of a class with the @catch decorator.
This is an 'Entry Adapter' that allows lifting an entire external SDK or client class into the Result world in a single declaration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
exceptions
|
type[Exception] | tuple[type[Exception], ...] | Mapping[type[Exception], Any]
|
The exceptions to catch on all methods. |
required |
map_to
|
Any
|
Optional constant error value. |
None
|
Returns:
| Type | Description |
|---|---|
Callable[[T_cls], T_cls]
|
A class decorator. |
Static Analysis Note (Type Erasure):
Using this decorator causes Type Erasure. Most Python type checkers
(Mypy, Pyright) cannot currently track that the return types of all
methods have been transformed from T to Result[T, E].
Source code in src/result/adapters.py
catch_each_iter
catch_each_iter(
exceptions: type[E_local]
| tuple[type[E_local], ...]
| Mapping[type[E_local], Any],
*,
map_to: Any = None,
) -> Callable[
[Callable[P_local, Iterator[T_local]]],
Callable[P_local, SafeStream[T_local, Any]],
]
Wrap a generator function to capture iteration-level exceptions into a SafeStream.
This decorator ensures that if an exception is raised during the iteration
of the generator, it is caught and yielded as an Err variant.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
exceptions
|
type[E_local] | tuple[type[E_local], ...] | Mapping[type[E_local], Any]
|
One or more exception types to catch, or a mapping of exception types to error values. |
required |
map_to
|
Any
|
Optional constant value to use as the error if an exception
matches (only used if |
None
|
Returns:
| Type | Description |
|---|---|
Callable[[Callable[P_local, Iterator[T_local]]], Callable[P_local, SafeStream[T_local, Any]]]
|
A decorator that transforms Generator[T] -> SafeStream[T, E]. |
Examples:
>>> # 1. Simple catch (returns the caught instance)
>>> @catch_each_iter(ValueError)
... def pump(n):
... for i in range(n):
... if i == 2:
... raise ValueError("fail")
... yield i
>>> list(pump(3))
[Ok(0), Ok(1), Err(ValueError('fail'))]
Source code in src/result/adapters.py
catch_each_iter_async
catch_each_iter_async(
exceptions: type[E_local]
| tuple[type[E_local], ...]
| Mapping[type[E_local], Any],
*,
map_to: Any = None,
) -> Callable[
[Callable[P_local, AsyncIterator[T_local]]],
Callable[P_local, SafeStreamAsync[T_local, Any]],
]
Wrap an async generator function to capture iteration-level exceptions into a SafeStreamAsync.
This is the asynchronous version of @catch_each_iter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
exceptions
|
type[E_local] | tuple[type[E_local], ...] | Mapping[type[E_local], Any]
|
One or more exception types to catch, or a mapping of exception types to error values. |
required |
map_to
|
Any
|
Optional constant value to use as the error if an exception
matches (only used if |
None
|
Returns:
| Type | Description |
|---|---|
Callable[[Callable[P_local, AsyncIterator[T_local]]], Callable[P_local, SafeStreamAsync[T_local, Any]]]
|
A decorator that transforms AsyncGenerator[T] -> SafeStreamAsync[T, E]. |
Source code in src/result/adapters.py
catch_instance
Wrap a specific object instance so all method calls return Results.
Ideal for third-party objects returned from factories that you don't control the class of.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
Any
|
The instance to wrap. |
required |
exceptions
|
Any
|
The exceptions to catch. |
required |
map_to
|
Any
|
Optional constant error value. |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
A proxy object that behaves like the original but wraps methods in @catch. |
Static Analysis Note (Type Erasure):
Using this proxy causes Type Erasure. Most Python type checkers
will believe the returned object is of type T_obj.
Source code in src/result/adapters.py
safe_resource
Wrap a standard context manager so that failures in enter yield an Err.
This ensures that the 'with' block is always entered, but the target is a Result variant.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cm
|
Any
|
A standard context manager (e.g., from open()). |
required |
Returns:
| Type | Description |
|---|---|
_SafeResourceContext[T]
|
A context manager that yields Result[T, Exception]. |
Examples:
>>> with safe_resource(open("missing.txt")) as res:
... match res:
... case Ok(f):
... print(f.read())
... case Err(e):
... print(f"Error: {e}")