Skip to main content

A high-performance, type-safe Result type for Python, inspired by Rust.

Project description

pyresult

PyPI version License: MIT

A high-performance, type-safe Result type for Python, inspired by Rust.

pyresult provides a robust and ergonomic way to handle operations that can either succeed (Ok) or fail (Err), eliminating the ambiguity of returning None or raising exceptions for expected errors.

This library is built with two core principles:

  • Maximum Performance: The core logic is compiled to a native C extension using Mypyc, removing Python's interpreter overhead and delivering C-level speed.
  • Absolute Type Safety: It is designed to pass mypy --strict checks, ensuring that your error-handling logic is sound and free of type-related bugs.

Core Philosophy

In many functions, errors are an expected possibility. Traditional Python error handling often relies on returning None (which can be ambiguous) or raising exceptions (which can be costly and verbose for control flow). pyresult offers a better way: a function returns a Result object, which is either an Ok containing a success value or an Err containing an error value. This makes the possibility of an error explicit in the function's type signature, forcing the caller to handle it gracefully.

Key Features

  • Blazing Fast: Compiled with Mypyc for performance that rivals native C code.
  • Type-Safe by Design: Fully annotated and validated with mypy --strict.
  • Zero Dependencies: Relies only on the Python standard library.
  • Ergonomic API: Provides a fluent, chainable interface for elegant error handling.
  • Drop-in & Easy to Use: A simple and intuitive API that is easy to adopt in any project.

Installation

You can install pyresult directly from PyPI:

pip install py-pyresult

Or, install it directly from the GitHub repository:

pip install git+https://github.com/imsf04/py-pyresult.git

Quick Start

Here is a simple example of how to use pyresult:

from pyresult.result import Ok, Err, Result

def divide(a: int, b: int) -> Result[float, str]:
    """
    A function that returns a Result: Ok(float) on success, or Err(str) on failure.
    """
    if b == 0:
        return Err("Cannot divide by zero")
    return Ok(a / b)

# --- Example 1: Successful division ---
res1 = divide(10, 2)

if res1.is_ok:
    # The operation was a success, we can safely unwrap the value.
    value = res1.unwrap()
    print(f"Success! Result is {value}")  # Output: Success! Result is 5.0

# --- Example 2: Failed division ---
res2 = divide(10, 0)

if res2.is_err:
    # The operation failed. We can get the error.
    error_message = res2.unwrap_err()
    print(f"Error: {error_message}")  # Output: Error: Cannot divide by zero

# --- Example 3: Using the chainable API ---
result = divide(20, 2)
(result.map(lambda x: x - 5)         # Ok(10.0) -> Ok(5.0)
       .and_then(lambda x: Ok(x * 2)) # Ok(5.0) -> Ok(10.0)
       .map_err(lambda e: f"Error: {e}")
)
print(result.unwrap_or(0.0)) # Output: 10.0

API Reference

Checking for Success or Failure

  • res.is_ok (property): Returns True if the result is Ok.
  • res.is_err (property): Returns True if the result is Err.

Extracting Values

  • res.ok() -> Optional[T]: Returns the value if the result is Ok, otherwise None.
  • res.err() -> Optional[E]: Returns the error if the result is Err, otherwise None.
  • res.unwrap() -> T: Returns the value if Ok, but panics (raises an Exception) if Err. Only use when you are certain of success.
  • res.unwrap_err() -> E: Returns the error if Err, but panics if Ok.
  • res.unwrap_or(default: T) -> T: Returns the value if Ok, or default if Err.
  • res.unwrap_or_else(op: Callable[[E], T]) -> T: Returns the value if Ok, or computes it from a function if Err.

Transforming Values

  • res.map(op: Callable[[T], U]) -> Result[U, E]: Maps a Result[T, E] to Result[U, E] by applying a function to a contained Ok value, leaving an Err value untouched.
  • res.map_err(op: Callable[[E], F]) -> Result[T, F]: Maps a Result[T, E] to Result[T, F] by applying a function to a contained Err value, leaving an Ok value untouched.

Chaining Operations

  • res.and_then(op: Callable[[T], Result[U, E]]) -> Result[U, E]: Calls op if the result is Ok, otherwise returns the Err value of res. This is useful for chaining operations that might fail.
  • res.or_else(op: Callable[[E], Result[T, F]]) -> Result[T, F]: Calls op if the result is Err, otherwise returns the Ok value of res. This is useful for handling an error by trying an alternative operation.

Checking Contents

  • res.contains(value: T) -> bool: Returns True if the result is an Ok value containing the given value.
  • res.contains_err(error_value: E) -> bool: Returns True if the result is an Err value containing the given error.

License

This project is licensed under the MIT License. See the LICENSE file for details.

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

py_pyresult-1.0.0.tar.gz (5.7 kB view details)

Uploaded Source

Built Distribution

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

py_pyresult-1.0.0-cp311-cp311-win_amd64.whl (38.6 kB view details)

Uploaded CPython 3.11Windows x86-64

File details

Details for the file py_pyresult-1.0.0.tar.gz.

File metadata

  • Download URL: py_pyresult-1.0.0.tar.gz
  • Upload date:
  • Size: 5.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.9

File hashes

Hashes for py_pyresult-1.0.0.tar.gz
Algorithm Hash digest
SHA256 7f416a85f9b16caa61a9107a6456a624c8bf6f42132c97488bb281d22113500f
MD5 002c3bfc393f1caaba7689c4d3f01170
BLAKE2b-256 d6108684335147f414f70801e9cb0a1bcf79a8ed1a5a8aebb8345637ffd6f7f9

See more details on using hashes here.

File details

Details for the file py_pyresult-1.0.0-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for py_pyresult-1.0.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 25345e7c42aa3d11255e13c03d5d0053a45ac45e2b54e3bba47dd8c275677d6a
MD5 510f3c4610877a3b4a1ab0c88ca7135b
BLAKE2b-256 5fa8edd021b3cd992726ad014eb7f129290d83aa3fd1b553d3d7f378b10133b5

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