Result monad for Python using Ok, Err and safe decorators
Project description
paraboloski-monad
An error handling decorator for Python that leverages the monadic design pattern. It represents operations that run on two parallel tracks: they can either succeed (Ok) or fail (Err), without raising exceptions.
Installation
PyPI
uv add paraboloski-monad
pip install paraboloski-monad
GitHub
uv add git+https://github.com/paraboloski/snippet-toolbox/python#subdirectory=snippet/monad
When to use it
Ideal for operations that can fail predictably: HTTP calls, data parsing, filesystem access, database queries. Instead of scattering try/except blocks throughout your code, failure becomes an explicit part of the return type.
Usage
from monad import Ok, Err, monad, safe, safe_async
@safe
def parse_user(data: dict) -> User:
return User(
id=data["id"],
name=data["name"],
email=data["email"],
)
@safe_async
async def fetch_user(user_id: int) -> dict:
async with aiohttp.ClientSession() as session:
async with session.get(f"/api/users/{user_id}") as response:
return await response.json()
Handle results with match
match parse_user(data):
case Ok(user):
print(f"Welcome, {user.name}")
case Err(error):
print(f"Invalid user data: {error}")
Operation pipelines
Failures propagate automatically without nested try/except blocks:
@safe
def read_file(path: str) -> str:
with open(path) as f:
return f.read()
@safe
def parse_json(content: str) -> dict:
return json.loads(content)
@safe
def parse_user(data: dict) -> User:
if "name" not in data:
raise ValueError("missing 'name' field")
return User(**data)
match read_file("user.json"):
case Ok(content):
match parse_json(content):
case Ok(data):
match parse_user(data):
case Ok(user):
print(f"Hello, {user.name}")
case Err(e):
print(f"Invalid user: {e}")
case Err(e):
print(f"Malformed JSON: {e}")
case Err(e):
print(f"File not found: {e}")
Or provide a default value with unwrap_or
When failure is acceptable and you want a fallback value:
user = parse_user(data).unwrap_or(
User(id=0, name="anonymous", email="")
)
users = (await fetch_user(user_id)).unwrap_or([])
Italiano
Un decoratore per l'error handling per Python che sfrutta il design pattern monadico. Rappresenta operazioni che seguono due binari paralleli: possono avere successo (Ok) o fallire (Err), senza sollevare eccezioni.
Installazione
PyPI
uv add paraboloski-monad
pip install paraboloski-monad
GitHub
uv add git+https://github.com/paraboloski/snippet-toolbox/python#subdirectory=snippet/monad
Quando usarla
Ideale per operazioni che possono fallire in modo prevedibile: chiamate HTTP, parsing di dati, accesso al filesystem, query a database. Invece di disseminare try/except nel codice, il fallimento diventa parte esplicita del tipo di ritorno.
Utilizzo
from monad import Ok, Err, monad, safe, safe_async
@safe
def parse_user(data: dict) -> User:
return User(
id=data["id"],
name=data["name"],
email=data["email"],
)
@safe_async
async def fetch_user(user_id: int) -> dict:
async with aiohttp.ClientSession() as session:
async with session.get(f"/api/users/{user_id}") as response:
return await response.json()
Gestisci il risultato con match
match parse_user(data):
case Ok(user):
print(f"Benvenuto, {user.name}")
case Err(error):
print(f"Dati utente non validi: {error}")
Pipeline di operazioni
Il fallimento si propaga automaticamente senza blocchi try/except annidati:
@safe
def read_file(path: str) -> str:
with open(path) as f:
return f.read()
@safe
def parse_json(content: str) -> dict:
return json.loads(content)
@safe
def parse_user(data: dict) -> User:
if "name" not in data:
raise ValueError("campo 'name' mancante")
return User(**data)
match read_file("user.json"):
case Ok(content):
match parse_json(content):
case Ok(data):
match parse_user(data):
case Ok(user):
print(f"Ciao, {user.name}")
case Err(e):
print(f"Utente non valido: {e}")
case Err(e):
print(f"JSON malformato: {e}")
case Err(e):
print(f"File non trovato: {e}")
Oppure fornisci un valore di default con unwrap_or
Quando il fallimento è accettabile e hai un valore di fallback:
user = parse_user(data).unwrap_or(
User(id=0, name="anonimo", email="")
)
users = (await fetch_user(user_id)).unwrap_or([])
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file paraboloski_monad-1.0.0.tar.gz.
File metadata
- Download URL: paraboloski_monad-1.0.0.tar.gz
- Upload date:
- Size: 4.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8bd322a3d9d8d60229d5e698c5e1af021e997779f3c1b002b5fb7dcb6b483c90
|
|
| MD5 |
64d6075b2ea4925b6ece70eb3df6bd84
|
|
| BLAKE2b-256 |
2d58731391d3613709591f8c47d91916c1b9a1d1bc3d997b6844cde2c20514f9
|
File details
Details for the file paraboloski_monad-1.0.0-py3-none-any.whl.
File metadata
- Download URL: paraboloski_monad-1.0.0-py3-none-any.whl
- Upload date:
- Size: 3.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e27c1317ce12430a9e1df30434f1573d2cf3ff905ea142f7755156c4a3afb84a
|
|
| MD5 |
4da3b66ececf82edcfca65d2b0baae6e
|
|
| BLAKE2b-256 |
ff8e0f1f703c2fb8702eb5effc18e52bc18e65b10247a7dbf5d6d9fe327a4d52
|