Result Pattern
A library designed to implement the "Errors as Values" pattern in Python 3.14+. It bridges the gap between pure functional safety and the pragmatic realities of the exception-heavy Python ecosystem.
Installation
# Package name is 'result-pattern', but you import 'result'
$ pip install result-pattern
Help
See documentation for more details.
Core Concept: Result (Sum Type)
A Result is a Sum Type representing a state of being either completely successful (Ok) or completely failed (Err).
1. Basic Usage
from result import Ok, Err, Result, is_ok
def divide(a: int, b: int) -> Result[float, str]:
if b == 0:
return Err("Cannot divide by zero")
return Ok(a / b)
res = divide(10, 2)
if is_ok(res):
# res is narrowed to Ok[float]
print(f"Success: {res.ok()}")
2. Modern Pattern Matching
Leverage Python 3.10+ native matching with optimized __match_args__:
match divide(10, 0):
case Ok(val):
print(f"Value: {val}")
case Err(msg):
print(f"Error: {msg}")
3. Functional Chaining
Avoid nested if statements with linear pipelines:
Ok(10).map(lambda x: x * 2).tap(print).and_then(lambda x: Ok(x + 1))
Interoperability: The Catch System
Bridge the procedural world of exceptions to the functional world of Results.
1. @catch Decorator
Lift exception-throwing code into Result containers with zero boilerplate.
from result import catch
@catch(ValueError)
def parse_int(s: str) -> int:
return int(s)
parse_int("10") # Ok(10)
parse_int("abc") # Err(ValueError(...))
2. Exception Mapping (map_to & Enums)
Immediately sanitize wild exceptions into strictly typed Domain Enums.
from enum import StrEnum
from result import catch
class ErrorCode(StrEnum):
INVALID = "invalid_input"
# Single mapping
@catch(ValueError, map_to=ErrorCode.INVALID)
def risky_op(s: str): ...
# Multiple mapping dictionary
@catch({ValueError: ErrorCode.INVALID, KeyError: "missing"})
def complex_op(x): ...
3. catch_call Inline
Execute standard library functions inline without opening context blocks.
from result import catch_call
import json
res = catch_call(json.JSONDecodeError, json.loads, '{"key": "value"}')
4. catch Context Manager
Lasso an entire block of wild Python code and capture the result safely.
from result import catch
import json
with catch(json.JSONDecodeError) as safe_block:
data = json.loads(payload)
# Perform complex logic...
safe_block.set(data["nested"]["key"])
# result is narrowed to Result[T, JSONDecodeError]
print(safe_block.result)
Monadic Orchestration: Do-Notation
Write procedural-looking code that automatically handles short-circuiting logic.
from result import do_notation, Do
@do_notation
def compile_pipeline(source: str) -> Do[str, Exception]:
tokens = yield tokenize(source) # Returns list[Token] or short-circuits Err
ast = yield parse(tokens) # Returns AST or short-circuits Err
code = yield generate(ast)
return code # Automatically wrapped in Ok
Combinators: Advanced Utilities
| Utility | Description |
|---|---|
validate() |
Applicative: Accumulates all errors instead of failing fast. |
traverse() |
Maps a fallible function over an iterable, failing fast. |
flow() |
A sequential pipeline macro for piped data transformations. |
succeeds() |
Filters a collection of Results, returning only the success values. |
partition_exceptions() |
Splits a mixed list of [Value, Exception] into [Ok, Err]. |
Outcome: Product Type (Go/Odin Style)
While Result is mathematically pure, real-world systems often require fault tolerance. Outcome[T, E] is a Product Type that holds both a partial success value and diagnostic baggage simultaneously.
Advantages:
- Native Unpacking: Inherits from
NamedTupleforval, err = do_work()syntax. - Fault Tolerance: Retain your AST or data payload even if warnings/errors occurred.
- Odin Style: Use
.to_result()inside a@do_notationblock to simulate Odin'sor_return.
Usage:
from result import Outcome
def parse_with_diagnostics(source: str) -> Outcome[AST, list[str]]:
# build AST and accumulate errors...
return Outcome(ast, accumulated_errors)
# 1. Procedural Unpacking (Go/Odin style)
ast, errors = parse_with_diagnostics(src)
if errors:
print(f"Warnings: {errors}")
# 2. Accumulation
new_outcome = Outcome(node, "e1").push_err("e2").merge(other_outcome)
# 3. Transition to Strict (or_return)
@do_notation
def strict_flow():
# .to_result() halts execution if any errors exist
ast = yield parse_with_diagnostics(src).to_result()
return emit(ast)
API Philosophy
Zero-Escape Safety
Panics are isolated in the .unsafe namespace. Direct .unwrap() access is disabled at the root level to encourage safe functional patterns.
res = Err("fail")
res.unsafe.unwrap() # Explicit panic
True Covariance
Full support for inheritance subtyping (e.g., Ok[Dog] is assignable to Result[Animal, Any]).
Metadata
Release files for result-pattern 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| result_pattern-0.2.2.tar.gz | 36.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| result_pattern-0.2.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 76.5 kB
Release files / result_pattern-0.2.2.tar.gz
| Download URL | result_pattern-0.2.2.tar.gz |
|---|---|
| Size | 36.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4a6734114dc76f38d36a98def4c47612ab5e3e51e9293c5177d33ed8b7e2ef5d
|
|
BLAKE2b-256 checksum How to use checksums |
7dbf87645be9c58b51f6d30e64f7e43e76e9f69fa170ddcf276e7187955f9fb8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / result_pattern-0.2.2-py3-none-any.whl
| Download URL | result_pattern-0.2.2-py3-none-any.whl |
|---|---|
| Size | 39.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ee8623a5ece67ed290519de601925ff298f55f858955e0737c5c8e1cb00dc072
|
|
BLAKE2b-256 checksum How to use checksums |
d6e26465db4174736c0ef9fa4731c29ec3aa6ba507b28318b9b54cad3de25bfc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|