Skip to main content

Tangled Result

Project description

Build Status Stable Version Coverage Python License

thresult

Python Result library for handling returned values (Result, Ok, Err) from functions/methods and handling errors. It is error handling library which is alternative to try/except style of programming.

It is inspired by great Rust Result, Ok, Err types.

Installation

pip install thresult

Simple Usage

Traditional try-except example

def div(x: float, y: float) -> float:
    z: float = x / y
    return z


z0: float = div(1.0, 2.0) # 0.5
z1: float = div(1.0, 0.0) # raises "ZeroDivisionError: division by zero" exception

Unwrapping Result as Context Manager

from thresult import Result


@Result
def div(x: float, y: float) -> float:
    z: float = x / y
    return z


try:
    with div(1.0, 0.0) as z:
        # unreachable
        r: float = z
except ZeroDivisionError as e:
    # exception happened
    pass

Unwrapping Result in unwrap Context Manager

from thresult import Result, unwrap


@Result
def f(x: float, y: float) -> float:
    z: float = x / y
    return z


try:
    with unwrap():
        # unreachable
        r: float = f(1, 0)
except ZeroDivisionError as e:
    # exception happened
    raise e

Pattern-matching Result using match-case

from thresult import Result, Ok, Err


@Result
def div(x: float, y: float) -> float:
    # can raise "ZeroDivisionError: division by zero" exception
    z: float = x / y
    return z


r: Result = div(1.0, 2.0) # Ok[float](0.5)

match r:
    case Ok(v):
        assert v == 0.5
    case Err(e):
        # unreachable
        # "ZeroDivisionError: division by zero"
        assert isinstance(e, ZeroDivisionError)

In-place pattern-matching Result using walrus operator and match-case

@Result
def div(x: float, y: float) -> float:
    # can raise "ZeroDivisionError: division by zero" exception
    z: float = x / y
    return z


match r := div(1.0, 2.0): # Ok[float](0.5)
    case Ok(v):
        assert v == 0.5
    case Err(e):
        # unreachable
        # "ZeroDivisionError: division by zero"
        assert isinstance(e, ZeroDivisionError)

Advanced Usage

Unwrapping Result[float, ZeroDivisionError] as Context Manager

from thresult import Result, Ok, Err


@Result[float, ZeroDivisionError]
def div(x: float, y: float) -> float:
    z: float = x / y
    return z


try:
    with div(1.0, 0.0) as z:
        # unreachable 
        pass
except ZeroDivisionError as e:
    # exception happened
    pass

Manually create Result value, and Structural Pattern Matching

from thresult import Result, Ok, Err


def div(x: float, y: float) -> Result[float, ZeroDivisionError]:
    res: Result[float, ZeroDivisionError]

    try:
        # can raise "ZeroDivisionError: division by zero" exception
        z: float = x / y
        res = Ok[float](z)
    except ZeroDivisionError as e:
        res = Err[ZeroDivisionError](e)

    return res


r0: Result = div(1.0, 2.0) # Ok
r1: Result = div(1.0, 0.0) # Err

match r0:
    case Ok(v):
        print('Ok, value:', v)
    case Err(e):
        print('Err, error:', e) # "ZeroDivisionError: division by zero"

match r1:
    case Ok(v):
        print('Ok, value:', v)
    case Err(e):
        print('Err, error:', e) # "ZeroDivisionError: division by zero"

z0: float = r0.unwrap() # 0.5
z1: float = r1.unwrap_or(float('inf')) # inf
z1: float = r1.unwrap() # raises "ZeroDivisionError: division by zero" exception

Decorate function with Result, and Structural Pattern Matching

from thresult import Result, Ok, Err


@Result[float, ZeroDivisionError]
def div(x: float, y: float) -> float:
    # can raise "ZeroDivisionError: division by zero" exception
    z: float = x / y
    return z


r0: Result = div(1.0, 2.0) # Ok
r1: Result = div(1.0, 0.0) # Err

match r0:
    case Ok(v):
        print('Ok, value:', v)
    case Err(e):
        print('Err, error:', e) # "ZeroDivisionError: division by zero"

match r1:
    case Ok(v):
        print('Ok, value:', v)
    case Err(e):
        print('Err, error:', e) # "ZeroDivisionError: division by zero"

z0: float = r0.unwrap() # 0.5
z1: float = r1.unwrap_or(float('inf')) # inf
z1: float = r1.unwrap() # raises "ZeroDivisionError: division by zero" exception

Run / Develop Cycle

docker run --rm -it -v $PWD/thresult:/code -w /code python:3.11-alpine python -B result.py

Testing

docker-compose build thresult-test ; docker-compose run --rm -v $PWD:/test thresult-test

Coverage

docker-compose build thresult-coverage ; docker-compose run --rm -v $PWD:/test thresult-coverage

Building

docker-compose build thresult-build ; docker-compose run --rm thresult-build

Licensing

thresult is licensed under the BSD 3 license.

Check the LICENSE 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

thresult-0.9.25.tar.gz (7.1 kB view details)

Uploaded Source

Built Distribution

thresult-0.9.25-py3-none-any.whl (6.7 kB view details)

Uploaded Python 3

File details

Details for the file thresult-0.9.25.tar.gz.

File metadata

  • Download URL: thresult-0.9.25.tar.gz
  • Upload date:
  • Size: 7.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.2.2 CPython/3.11.0 Linux/5.4.109+

File hashes

Hashes for thresult-0.9.25.tar.gz
Algorithm Hash digest
SHA256 eb2e8a6b169c2fc7b70965e08d3ea8737296a62f4008a656de866ef0820a95c7
MD5 195ea0abcd51f63135a546924568a3c5
BLAKE2b-256 9793a13c429a8f2cdcb5433d20985b79e0d618f83bf94e442b0fc7ac7f1f38ee

See more details on using hashes here.

File details

Details for the file thresult-0.9.25-py3-none-any.whl.

File metadata

  • Download URL: thresult-0.9.25-py3-none-any.whl
  • Upload date:
  • Size: 6.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.2.2 CPython/3.11.0 Linux/5.4.109+

File hashes

Hashes for thresult-0.9.25-py3-none-any.whl
Algorithm Hash digest
SHA256 763a30824a32aa62b30c0418e4c91b2c8391be259c3b6fce2bbb0781483d91ff
MD5 41f69ac1a3a6529956111ba7d2593628
BLAKE2b-256 4de1b73408fdb352d97c162d030f23c17c105b09eead9e41020ac45c2c483f5b

See more details on using hashes here.

Supported by

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