API Reference

Either Class

The Either type represents a value that can be one of two possibilities:

  • Left: Conventionally used for errors/failures

  • Right: Conventionally used for success values

Creating Either Values

from result_py import Either

# Success values
success = Either.right(42)
success = Either.success(42)  # Alias

# Failure values
failure = Either.left("Error message")
failure = Either.failure("Error message")  # Alias
class result_py.either.Either(_left=None, _right=None)

Bases: Generic[L, R]

A type-safe Either monad for functional error handling.

Either represents a value that can be one of two types: - Left (L): Typically used to represent an error or failure case - Right (R): Typically used to represent a success case

This is a frozen (immutable) dataclass for safety.

Parameters:
  • _left (L | None)

  • _right (R | None)

and_then(f)

Chains an Either-returning function, similar to Rust’s and_then.

This is the monadic bind operation. If this Either is Right, applies the function to the right value and returns the result. If this Either is Left, returns the Left.

Parameters:
  • f (Callable[[R], Either[L2, R2]]) – A function that takes the right value and returns a new Either.

  • self (Either[L, R])

Returns:

The result of applying f if Right, otherwise the original Left.

Return type:

Either[L | L2, R2]

Example

>>> def parse_int(s: str) -> Either[str, int]:
...     try:
...         return Either.right(int(s))
...     except ValueError:
...         return Either.left("not a number")
>>> Either.right("42").and_then(parse_int)
>>> Either(_left=None, _right=42)
counted()

Counts the occurrences of each item in the Iterable contained in the Either.

Parameters:

self (Either[L, Iterable[T1]]) – An Either containing an Iterable of items of type T1.

Returns:

An Either containing a Counter mapping each item to its count, or the left value if present.

Return type:

Either[L, Mapping[T1, int]]

ctx_pipe(f)

Applies a function to the right value of the Either, discards the return value and passes along the right value.

Parameters:
  • f (Callable[[R], Either[T1, T2]]) – A function that takes the right value and returns an Either.

  • self (Either[T1, R])

Returns:

An Either containing the left value from the function if it fails, or the original right value if it succeeds.

Return type:

Either[T1, R]

Example

>>> e = Either.right(5)
>>> e.ctx_pipe(lambda x: logger.info(f"Value: {x}"))
>>> Either(_left="Error", _right=5)
dict_pipe(key, f)
Return type:

Either[TypeVar(L), Mapping[str, TypeVar(T_co, covariant=True)]]

Parameters:
  • self (Either[L, Mapping[str, T_co]])

  • key (str)

  • f (Callable[[T_co], Any])

static failure(l)

Create a Left Either containing an error/failure value.

Return type:

Either[TypeVar(L2), Any]

Parameters:

l (L2)

filter(f, track=False, **tqdm_kwargs)
Return type:

Either[TypeVar(L), Iterable[Any]]

Parameters:
  • self (Either[L, Iterable[Any]])

  • f (Callable[[...], bool])

  • track (bool)

  • tqdm_kwargs (dict[str, Any])

filter_map(f, track=False, **tqdm_kwargs)

Applies a filter-map function to each item in the Iterable contained in the Either.

Parameters:
  • self (Either[L, Iterable[T1]]) – An Either containing a Iterable of items of type T1.

  • f (Callable[[T1], Optional[T2]]) – A function that takes an item of type T1 and returns an optional value of type T2. Items for which the function returns None are filtered out.

  • track (bool, optional) – If True, uses tqdm to track progress.

  • tqdm_kwargs (dict[str, Any], optional) – Additional keyword arguments for tqdm.

Returns:

An Either containing the results of applying the function to each item in the Iterable, excluding items where the function returns None. If the Either is left, it returns the left value.

Return type:

Either[L, Iterable[T2]]

Example

>>> e = Either.right([1, 2, 3, 4, 5])
>>> e.filter_map(lambda x: x * 2 if x % 2 == 0 else None)
>>> Either(_left=None, _right=[4, 8])
flat_map(f)
Return type:

Either[TypeVar(L), Iterable[TypeVar(T2)]]

Parameters:
  • self (Either[L, Iterable])

  • f (Callable[[T1], Iterable])

flatten()

Flattens an Either containing an iterable of iterables into an iterable of items.

Parameters:

self (Either[L, Iterable[Iterable[T1]]]) – An Either containing an iterable of iterables to be flattened.

Returns:

An Either containing a single iterable with all items from the sub-iterables, or the left value if present.

Return type:

Either[L, Iterable[T1]]

property is_left: bool

Returns True if this Either contains a Left value.

property is_right: bool

Returns True if this Either contains a Right value.

iter_to_(t)

Converts the Iterable contained in the Either to a specific type.

Parameters:
  • self (Either[L, Iterable[T1]]) – An Either containing an Iterable of items of type T1.

  • t (type[T2]) – The type to which the items should be converted.

Returns:

An Either containing an Iterable of items of type T2, or the left value if present.

Return type:

Either[L, Iterable[T2]]

static left(l)

Create a Left Either containing an error/failure value.

Return type:

Either[TypeVar(L2), Any]

Parameters:

l (L2)

map(f, track=False, **tqdm_kwargs)
Return type:

Either[TypeVar(L), Iterable[TypeVar(T2)]]

Parameters:
  • self (Either[L, Iterable])

  • f (Callable[[T1], T2])

  • track (bool)

  • tqdm_kwargs (dict[str, Any])

map_left(f)

Applies a function to the left value of the Either if it exists.

Parameters:
  • f (Callable[[L], L2]) – A function that takes the left value and returns a new left value.

  • self (Either[L, R])

Returns:

An Either containing the transformed left value, or the original right value.

Return type:

Either[L2, R]

Example

>>> e = Either.left("error")
>>> e.map_left(lambda s: f"Error: {s}")
>>> Either(_left="Error: error", _right=None)
map_reduce(f, initial, add=<built-in function add>, track=False, **tqdm_kwargs)
Return type:

Either[TypeVar(L), HasAdd[TypeVar(T2)]]

Parameters:
match(left, right=<function ident>)

Matches the Either to either the left or right function based on its state.

Parameters:
  • left (Callable[[L], Out1]) – A function to apply if the Either is Left, taking the left value as an argument.

  • right (Callable[[R], Out2], optional) – A function to apply if the Either is Right, taking the right value as an argument.

Returns:

The result of applying the left function if the Either is Left, or the right function if the Either is Right.

Return type:

Out1 | Out2

n_filter_map(f, track=False, **tqdm_kwargs)

Applies an unpacking filter-map function to each item in the Iterable contained in the Either.

Parameters:
  • self (Either[L, Iterable[tuple[*T1]]]) – An Either containing an Iterable of tuples, where each tuple contains multiple items.

  • f (Callable[[…], Optional[T2]]) – A function that takes multiple arguments and returns an optional value of type T2. Items for which the function returns None are filtered out.

  • track (bool, optional) – If True, uses tqdm to track progress.

  • tqdm_kwargs (dict[str, Any], optional) – Additional keyword arguments for tqdm.

Returns:

An Either containing the results of applying the function to each item in the Iterable, excluding items where the function returns None. If the Either is left, it returns the left value.

Return type:

Either[L, Iterable[T2]]

Example

>>> e = Either.right([(1, 2), (3, 4), (5, 6)])
>>> e.n_filter_map(lambda x, y: x + y if (x + y) > 5 else None)
>>> Either(_left=None, _right=[7, 11])
n_map(f, track=False, **tqdm_kwargs)

Applies an unpacking function to each item in the Iterable contained in the Either.

Parameters:
  • f (Callable[[…], T2]) – A function that takes multiple arguments and returns a value of type T2.

  • track (bool, optional) – If True, uses tqdm to track progress.

  • tqdm_kwargs (dict[str, Any], optional) – Additional keyword arguments for tqdm.

  • self (Either[L, Iterable[tuple[Unpack[T1]]]])

Returns:

An Either containing the results of applying the function to each item in the Iterable. If the Either is left, it returns the left value.

Return type:

Either[L, Iterable[T2]]

Example

>>> e = Either.right([(1, 2), (3, 4)])
>>> e.n_map(lambda x, y: x + y)
>>> Either(_left=None, _right=[3, 7])
n_map_reduce(f, initial, add=<built-in function add>, track=False, **tqdm_kwargs)

Maps each item in the Iterable contained in the Either to a new type using the provided function, and then reduces the resulting Iterable to a single value.

Parameters:
  • self (Either[L, Iterable[tuple[*T1]]]) – An Either containing an Iterable of tuples, where each tuple contains multiple items.

  • f (Callable[[…], T2]) – A function that takes multiple arguments and returns a value of type T2.

  • initial (T2) – The initial value for the reduction.

  • add (Callable[[HasAdd, HasAdd], HasAdd])

  • track (bool)

  • tqdm_kwargs (dict[str, Any])

Returns:

An Either containing the reduced value, or the left value if present.

Return type:

Either[L, T2]

Example

>>> e = Either.right([(1, 2), (3, 4), (5, 6)])
>>> e.n_map_reduce(lambda x, y: x + y, 0)
>>> Either(_left=None, _right=21)
n_partition(f)

Partitions the Iterable contained in the Either into two parts based on a predicate function.

Parameters:
  • self (Either[L, Iterable[Union[*T1] | Union[*T2]]]) – An Either containing an Iterable of items of type T1 or T2.

  • f (Callable[[Union[*T1] | Union[*T2]], TypeIs[T1]]) – A function that takes an item of type T1 or T2 and returns True if the item is of type T1, False otherwise.

Returns:

An Either containing a tuple of two Iterables: - The first Iterable contains items of type T1. - The second Iterable contains items of type T2. If the Either is left, it returns the left value.

Return type:

Either[L, tuple[Iterable[*T1], Iterable[*T2]]]

n_pipe(f)
Return type:

Either[TypeVar(L), TypeVar(T2)]

Parameters:
  • self (Either[L, tuple[Unpack[T1]]])

  • f (Callable[[Unpack[T1]], T2])

or_else(f)

Applies a function to the left value to attempt recovery.

Parameters:
  • f (Callable[[L], Either[L2, R]]) – A function that takes the left value and returns a new Either, potentially recovering from the error.

  • self (Either[L, R])

Returns:

The result of the recovery function if Left, otherwise the original Right.

Return type:

Either[L2, R]

Example

>>> def recover(err: str) -> Either[int, str]:
...     return Either.right("recovered") if err == "recoverable" else Either.left(500)
>>> Either.left("recoverable").or_else(recover)
>>> Either(_left=None, _right="recovered")
partition(f)
Return type:

Either[TypeVar(L), tuple[Iterable[Any], Iterable[Any]]]

Parameters:
  • self (Either[L, Iterable[Any]])

  • f (Callable[[...], bool])

pipe(f)
Return type:

Either[Any, Any]

Parameters:

f (Callable[[R], Any])

reduce(f, initial, track=False, **tqdm_kwargs)

Reduces the Iterable contained in the Either to a single value using the provided function.

Parameters:
  • self (Either[L, Iterable[T1]]) – An Either containing an Iterable of items of type T1.

  • f (Callable[[T2, T1], T2]) – A function that takes an accumulator of type T2 and an item of type T1, and returns a new accumulator of type T2.

  • initial (T2) – The initial value for the reduction.

  • track (bool)

  • tqdm_kwargs (dict[str, Any])

Returns:

An Either containing the reduced value, or the left value if present.

Return type:

Either[L, T2]

Example

>>> e = Either.right([1, 2, 3, 4])
>>> e.reduce(lambda acc, x: acc + x, 0)
>>> Either(_left=None, _right=10)
static right(r)

Create a Right Either containing a success value.

Return type:

Either[Any, TypeVar(R2)]

Parameters:

r (R2)

static success(r)

Create a Right Either containing a success value.

Return type:

Either[Any, TypeVar(R2)]

Parameters:

r (R2)

then(mnd)

Chains another Either operation, returning the new Either if the current one is Right, or the current Left value if it is Left.

Parameters:

mnd (Either[L, T]) – An Either to chain with the current Either.

Returns:

The new Either if the current one is Right, otherwise the current Left value.

Return type:

Either[L, T]

Example

Good for chaining operations that depend on the success of the previous one. >>> e1 = Either.right(5) >>> e2 = Either.right(10) >>> e1.then(e2) >>> Either(_left=None, _right=10)

to_counter()

Converts the Iterable contained in the Either to a Counter (a subclass of dict).

Parameters:

self (Either[L, Iterable[T1]]) – An Either containing an Iterable of items of type T1.

Returns:

An Either containing a Counter mapping each item to its count, or the left value if present.

Return type:

Either[L, Mapping[T1, int]]

to_items()

Converts the Either containing a Mapping to an Iterable of its items.

Parameters:

self (Either[L, Mapping[T1, T2]]) – An Either containing a Mapping with items of type T1 and T2.

Returns:

An Either containing an Iterable of tuples, where each tuple contains a key of type T1 and a value of type T2.

Return type:

Either[L, Iterable[tuple[T1, T2]]]

to_json(**kwargs)

Converts the Either to a JSON string representation. If the Either is left, it returns the left value as a JSON string. If the Either is right, it returns the right value as a JSON string.

Return type:

Either[TypeVar(L), str]

Parameters:

kwargs (Any)

to_list()
Return type:

Either[TypeVar(L), list[TypeVar(T1)]]

Parameters:

self (Either[L, Iterable])

to_root_items()

Converts the Either containing a HasRootMapping to an Iterable of its items.

Parameters:

self (Either[L, HasRootMapping[T]]) – An Either containing a HasRootMapping with items of type T.

Returns:

An Either containing an Iterable of tuples, where each tuple contains a string key and a value of type T.

Return type:

Either[L, Iterable[tuple[str, T]]]

to_set()

Converts the Iterable contained in the Either to a set.

Parameters:

self (Either[L, Iterable[T1]]) – An Either containing an Iterable of items of type T1.

Returns:

An Either containing a set of items from the Iterable, or the left value if present.

Return type:

Either[L, set[T1]]

two_partition(f)

Partitions the Iterable contained in the Either into two parts based on a predicate function.

Parameters:
  • self (Either[L, Iterable[T1 | T2]]) – An Either containing an Iterable of items of type T1 or T2.

  • f (Callable[[T1 | T2], TypeIs[T1]]) – A function that takes an item of type T1 or T2 and returns True if the item is of type T1, False otherwise.

Returns:

An Either containing a tuple of two Iterables: - The first Iterable contains items of type T1. - The second Iterable contains items of type T2. If the Either is left, it returns the left value.

Return type:

Either[L, tuple[Iterable[T1], Iterable[T2]]]

unwrap_or(default)

Returns the right value if present, otherwise returns the default.

Parameters:

default (R) – The default value to return if this Either is Left.

Returns:

The right value if present, otherwise the default.

Return type:

R

Example

>>> Either.right(42).unwrap_or(0)
42
>>> Either.left("error").unwrap_or(0)
0
write_json_out(fp)

Writes the right value of the Either to a JSON file if it is a BaseModel.

Parameters:
  • self (Either[L, T1]) – An Either containing a BaseModel instance as its right value.

  • fp (str) – The file path where the JSON representation of the BaseModel will be written.

Returns:

An Either that is Right with None if the write operation is successful, or Left with the original left value if the Either is Left or if an error occurs during the write operation.

Return type:

Either[L, None]

zip(other)

Combines two Either instances into a single Either containing a tuple of their right values if present.

Parameters:
  • other (Either[L, B]) – Another Either instance to zip with.

  • self (Either[L, R])

Returns:

An Either containing a tuple of right values if both are Right, otherwise the first encountered Left.

Return type:

Either[L, tuple[R, B]]

Helper Functions

as_either

Wraps a value in Either.right:

from result_py import as_either

result = as_either(42)  # Either(_left=None, _right=42)

wrap_external

Wraps a function that might throw exceptions:

from result_py import wrap_external
import json

safe_loads = wrap_external(json.loads, json.JSONDecodeError)

result = safe_loads('{"key": "value"}')  # Right({'key': 'value'})
result = safe_loads('invalid')           # Left(JSONDecodeError(...))

throws Decorator

Decorator to catch specified exceptions and convert them to Either.left:

from result_py import Either, throws

@throws(ValueError, KeyError)
def process(data: dict) -> Either[ValueError | KeyError, int]:
    return Either.right(data["key"] * 2)

result = process({"key": 5})  # Right(10)
result = process({})          # Left(KeyError('key'))

Contracts Module

class result_py.contracts.HasItems(*args, **kwargs)[source]

Bases: Protocol, Generic

items()[source]
Return type:

Iterable[tuple[TypeVar(K), TypeVar(V)]]

class result_py.contracts.HasRootMapping(*args, **kwargs)[source]

Bases: Protocol[T_co]

property root: Mapping[str, T_co]
class result_py.contracts.HasAdd(*args, **kwargs)[source]

Bases: Protocol[T_add]