Skip to main content

A Python library providing a Result type for elegant error handling, inspired by Rust's Result type.

Project description

safe-result

A Python package for elegant error handling, inspired by Rust's Result type.

Installation

uv pip install "git+https://github.com/overflowy/safe-result"

Overview

safe-result provides type-safe objects that represent either success (Ok) or failure (Err). This approach enables more explicit error handling without relying on try/catch blocks, making your code more predictable and easier to reason about.

Key features:

  • Type-safe result handling with generics support
  • Type guards to safely access result values
  • Decorators to automatically wrap function returns in Result objects
  • Pattern matching support for elegant error handling
  • Built-in traceback capture for comprehensive error information

Usage

Basic Usage

from safe_result import Err, Ok, Result, ok


def divide(a: int, b: int) -> Result[float, ZeroDivisionError]:
    if b == 0:
        return Err(ZeroDivisionError("Cannot divide by zero"))  # Failure case
    return Ok(a / b)  # Success case


# Function signature clearly communicates potential failure modes
foo = divide(10, 0)  # -> Result[float, ZeroDivisionError]

# Type checking will prevent unsafe access to the value
bar = 1 + foo.value
#         ^^^^^^^^^ Pylance/mypy indicates error:
# "Operator '+' not supported for types 'Literal[1]' and 'float | None'"

# Safe access pattern using the type guard function
if ok(foo):  # Verifies foo is an Ok result and enables type narrowing
    bar = 1 + foo.value  # Safe! - type system knows the value is a float here
else:
    # Handle error case with full type information about the error
    print(f"Error: {foo.error}")

Using the Decorators

The safe decorator automatically wraps function returns in an Ok or Err object. Any exception is caught and wrapped in an Err result.

from safe_result import Err, Ok, ok, safe


@safe
def divide(a: int, b: int) -> float:
    return a / b


# Return type is inferred as Result[float, Exception]
foo = divide(10, 0)

if ok(foo):
    print(f"Result: {foo.value}")
else:
    print(f"Error: {foo}")  # -> Err(division by zero)
    print(f"Error type: {type(foo.error)}")  # -> <class 'ZeroDivisionError'>

# Python's pattern matching provides elegant error handling
match foo:
    case Ok(value):
        bar = 1 + value
    case Err(ZeroDivisionError):
        print("Cannot divide by zero")
    case Err(TypeError):
        print("Type mismatch in operation")
    case Err(ValueError):
        print("Invalid value provided")
    case _ as e:
        print(f"Unexpected error: {e}")

The safe_with decorator provides more precise control by specifying which exception types to catch, improving type hints and safety.

from safe_result import ok, safe_with


@safe_with(ZeroDivisionError)
def divide(a: int, b: int) -> float:
    return a / b


foo = divide(10, 0)  # -> Result[float, ZeroDivisionError]

if not ok(foo):
    print(f"Error: {foo}")  # -> Err(division by zero)
    print(f"Error type: {type(foo.error)}")  # -> <class 'ZeroDivisionError'>


# Other exceptions are not caught, maintaining expected behavior
# foo = divide(10, "2")  # Will raise a TypeError since it's not handled by the decorator

License

MIT

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

safe_result-3.0.0.tar.gz (13.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

safe_result-3.0.0-py3-none-any.whl (4.9 kB view details)

Uploaded Python 3

File details

Details for the file safe_result-3.0.0.tar.gz.

File metadata

  • Download URL: safe_result-3.0.0.tar.gz
  • Upload date:
  • Size: 13.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.5.13

File hashes

Hashes for safe_result-3.0.0.tar.gz
Algorithm Hash digest
SHA256 484cce47b994497dfe412411aa79bc40fb2afa56e03c67960ee8b2c84a27dfc1
MD5 8533bd298cbef02c7a61a748c5bec6bb
BLAKE2b-256 1301d96dad21754d365ddea329aac24f29bae535fc5a1bd357de2da011e408f0

See more details on using hashes here.

File details

Details for the file safe_result-3.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for safe_result-3.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 11a2731986df4981d34b94e710316790df7fcad314d5c647035e7244466fe2ef
MD5 1888b5f28e1408a04a45508e122b0ced
BLAKE2b-256 ca1211f010ec9566fd7de28edb9a50b88d7baa8d83288883ea26e68bb680eb89

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page