Option and Result types for Python.
Project description
isos
isos is a lightweight Python library that brings the Result Pattern to your code.
It introduces two core types — Option and Result — which behave as sum types (also known as tagged unions or discriminated unions) that make handling missing values and errors explicit, safe, and expressive.
Sum types allow you to represent values that can be one of several variants, where each variant can hold different types of data. This is particularly useful for modeling scenarios where a value can be in different states, like presence/absence (Option) or success/failure (Result).
Why use the Result pattern?
In Python, a function can return Optional[T] — either a value of type T or None.
But unless you enforce strict type checking, there’s no clear indication that the value may be absent.
This often leads to AttributeError or TypeError when None sneaks through.
Similarly, Python uses exceptions to signal errors, but you don’t always know when a function might raise one.
You either have to read the source or wrap everything in a try/except.
By returning a Result or Option instead, you:
- Make absence and errors visible in the type system.
- Force explicit handling of failure cases.
- Pass, transform, and compose results safely.
- Write code that is more predictable, robust, and self-documenting.
Examples
Option
from isos import Some, Null, Option
def find_user(user_id: int) -> Option[str]:
users = {1: "Alice", 2: "Bob"}
return Some(users[user_id]) if user_id in users else Null()
# Handling the result:
user = find_user(1)
if user.is_some():
print(f"Found user: {user.unwrap()}")
else:
print("User not found")
# You can also provide a default:
name = find_user(42).unwrap_or("Guest")
print(name) # -> "Guest"
Result
from isos import Ok, Err, Error, Result
from typing import final
# Define a custom error
@final
class DivisionByZero(Error):
MESSAGE = "Cannot divide by zero"
def safe_divide(a: float, b: float) -> Result[float]:
def safe_divide(a: float, b: float) -> Result[float]:
if b == 0:
return Err(DivisionByZero())
return Ok(a / b)
result = safe_divide(10, 2)
if result.is_ok():
print(f"Result is {result.unwrap()}")
else:
print(f"Error: {result.unwrap_error()}")
# Transforming results
result = safe_divide(10, 0).map(lambda x: x * 2)
# Still Err(DivisionByZero)
# Chaining
result = safe_divide(20, 2).and_then(lambda x: safe_divide(x, 2))
print(result) # -> Ok(5.0)
Pattern Matching
Python 3.10 introduced pattern matching, which works great with Option and Result:
from isos import Some, Null, Ok, Err
# Pattern matching with Option
def describe_user(user_opt: Option[str]) -> str:
match user_opt:
case Some(name):
return f"User found: {name}"
case Null():
return "No user found"
case _:
raise TypeError("user_opt is not an Option")
print(describe_user(Some("Alice"))) # -> "User found: Alice"
print(describe_user(Null())) # -> "No user found"
# Pattern matching with Result
def handle_division(result: Result[float]) -> str:
match result:
case Ok(value):
return f"Success: {value}"
case Err(error):
return f"Failed: {error.MESSAGE}"
case _:
raise TypeError("result is not a Result")
print(handle_division(safe_divide(10, 2))) # -> "Success: 5.0"
print(handle_division(safe_divide(1, 0))) # -> "Failed: Cannot divide by zero"
Comparison Methods
isos does not implement the standard comparison operators (<, <=, >, >=) for Option[T] and Result[T] types
This is because the contained values (T) might not always implement these operators, which could lead to runtime errors.
Instead, isos provides explicit "unsafe" comparison methods:
from isos import Some, Null, Ok, Err
# Option comparisons
assert Some(10).less_than_unsafe(Some(20)) # True
assert Null().less_than_unsafe(Some(10)) # True - Null is always less than Some
assert Some(20).less_than_unsafe(Some(10)) # False
# Result comparisons
result1 = safe_divide(10, 2) # Ok(5.0)
result2 = safe_divide(20, 2) # Ok(10.0)
assert result1.less_than_unsafe(result2) # True
assert not result2.less_than_unsafe(result1) # False
# Other comparison methods
assert Some(10).less_or_equal_unsafe(Some(10))
assert Some(10).greater_than_unsafe(Some(5))
assert Some(10).greater_or_equal_unsafe(Some(10))
These methods are marked as "unsafe" because they require the contained values to implement the < operator. If you try to compare values that don't support comparison, you'll get a TypeError:
# This will raise TypeError because complex numbers don't support < operator
Some(1+2j).less_than_unsafe(Some(2+3j))
Project details
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 isos-0.3.2.tar.gz.
File metadata
- Download URL: isos-0.3.2.tar.gz
- Upload date:
- Size: 10.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a01a90c6476b079922e801b22e44f6e3a357150dac02c05b90dc52dc2fa096cc
|
|
| MD5 |
7935b08a072c5a66db7ed47e4be245ce
|
|
| BLAKE2b-256 |
a0382a6f0c42032bb73ec6852d3439652fadc1909807d103fdfb91d9ab00694b
|
Provenance
The following attestation bundles were made for isos-0.3.2.tar.gz:
Publisher:
release.yaml on gsmyridis/isos
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
isos-0.3.2.tar.gz -
Subject digest:
a01a90c6476b079922e801b22e44f6e3a357150dac02c05b90dc52dc2fa096cc - Sigstore transparency entry: 543776197
- Sigstore integration time:
-
Permalink:
gsmyridis/isos@fc7b2fcfca6b12cca6306297c10dc909e2d8e704 -
Branch / Tag:
refs/tags/0.3.2 - Owner: https://github.com/gsmyridis
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@fc7b2fcfca6b12cca6306297c10dc909e2d8e704 -
Trigger Event:
push
-
Statement type:
File details
Details for the file isos-0.3.2-py3-none-any.whl.
File metadata
- Download URL: isos-0.3.2-py3-none-any.whl
- Upload date:
- Size: 8.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
337ea9b352b7e4beed3d9989e3aadf11cf407ab54e0cf2ec3b25c1cddffcb7a7
|
|
| MD5 |
ce3df052f08ffba2b7780a207c1d5926
|
|
| BLAKE2b-256 |
bd1d6767aead82390d300ae1dd830b59f2444c02356420b44b958fd2b9b0d5f7
|
Provenance
The following attestation bundles were made for isos-0.3.2-py3-none-any.whl:
Publisher:
release.yaml on gsmyridis/isos
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
isos-0.3.2-py3-none-any.whl -
Subject digest:
337ea9b352b7e4beed3d9989e3aadf11cf407ab54e0cf2ec3b25c1cddffcb7a7 - Sigstore transparency entry: 543776200
- Sigstore integration time:
-
Permalink:
gsmyridis/isos@fc7b2fcfca6b12cca6306297c10dc909e2d8e704 -
Branch / Tag:
refs/tags/0.3.2 - Owner: https://github.com/gsmyridis
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yaml@fc7b2fcfca6b12cca6306297c10dc909e2d8e704 -
Trigger Event:
push
-
Statement type: