thresult


Namethresult JSON
Version 0.9.25 PyPI version JSON
download
home_pagehttps://gitlab.com/tangledlabs/thresult
SummaryTangled Result
upload_time2022-12-01 09:08:34
maintainer
docs_urlNone
authorTangled
requires_python>=3.10,<4.0
licenseBSD 3-clause
keywords thresult result tangled tangledgroup tangledhub tangledlabs tangledcloud
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            [![Build][build-image]]()
[![Status][status-image]][pypi-project-url]
[![Stable Version][stable-ver-image]][pypi-project-url]
[![Coverage][coverage-image]]()
[![Python][python-ver-image]][pypi-project-url]
[![License][bsd3-image]][bsd3-url]


# 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

```bash
pip install thresult
```


## Simple Usage

### Traditional `try-except` example

```python
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

```python
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

```python
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`
```python
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`

```python
@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

```python
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

```python
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

```python
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
```bash
docker run --rm -it -v $PWD/thresult:/code -w /code python:3.11-alpine python -B result.py
```


## Testing

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


## Coverage

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


## Building

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


## Licensing

`thresult` is licensed under the BSD 3 license.

Check the [LICENSE](https://opensource.org/licenses/BSD-3-Clause) for details.


<!-- Badges -->
[bsd3-image]: https://img.shields.io/badge/License-BSD_3--Clause-blue.svg
[bsd3-url]: https://opensource.org/licenses/BSD-3-Clause
[build-image]: https://img.shields.io/gitlab/pipeline-status/tangledlabs/thresult?branch=main
[coverage-image]: https://img.shields.io/gitlab/pipeline-coverage/tangledlabs/thresult?branch=main

[pypi-project-url]: https://pypi.org/project/thresult/
[stable-ver-image]: https://img.shields.io/pypi/v/thresult?label=stable
[python-ver-image]: https://img.shields.io/pypi/pyversions/thresult.svg?logo=python&logoColor=FBE072
[status-image]: https://img.shields.io/pypi/status/thresult.svg

            

Raw data

            {
    "_id": null,
    "home_page": "https://gitlab.com/tangledlabs/thresult",
    "name": "thresult",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.10,<4.0",
    "maintainer_email": "",
    "keywords": "thresult,result,tangled,tangledgroup,tangledhub,tangledlabs,tangledcloud",
    "author": "Tangled",
    "author_email": "info@tangledgroup.com",
    "download_url": "https://files.pythonhosted.org/packages/97/93/a13c429a8f2cdcb5433d20985b79e0d618f83bf94e442b0fc7ac7f1f38ee/thresult-0.9.25.tar.gz",
    "platform": null,
    "description": "[![Build][build-image]]()\n[![Status][status-image]][pypi-project-url]\n[![Stable Version][stable-ver-image]][pypi-project-url]\n[![Coverage][coverage-image]]()\n[![Python][python-ver-image]][pypi-project-url]\n[![License][bsd3-image]][bsd3-url]\n\n\n# thresult\n\n*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.\n\nIt is inspired by great *Rust* `Result`, `Ok`, `Err` types.\n\n\n## Installation\n\n```bash\npip install thresult\n```\n\n\n## Simple Usage\n\n### Traditional `try-except` example\n\n```python\ndef div(x: float, y: float) -> float:\n    z: float = x / y\n    return z\n\n\nz0: float = div(1.0, 2.0) # 0.5\nz1: float = div(1.0, 0.0) # raises \"ZeroDivisionError: division by zero\" exception\n```\n\n\n### Unwrapping `Result` as Context Manager\n\n```python\nfrom thresult import Result\n\n\n@Result\ndef div(x: float, y: float) -> float:\n    z: float = x / y\n    return z\n\n\ntry:\n    with div(1.0, 0.0) as z:\n        # unreachable\n        r: float = z\nexcept ZeroDivisionError as e:\n    # exception happened\n    pass\n```\n\n\n### Unwrapping `Result` in `unwrap` Context Manager\n\n```python\nfrom thresult import Result, unwrap\n\n\n@Result\ndef f(x: float, y: float) -> float:\n    z: float = x / y\n    return z\n\n\ntry:\n    with unwrap():\n        # unreachable\n        r: float = f(1, 0)\nexcept ZeroDivisionError as e:\n    # exception happened\n    raise e\n```\n\n\n### Pattern-matching `Result` using `match-case`\n```python\nfrom thresult import Result, Ok, Err\n\n\n@Result\ndef div(x: float, y: float) -> float:\n    # can raise \"ZeroDivisionError: division by zero\" exception\n    z: float = x / y\n    return z\n\n\nr: Result = div(1.0, 2.0) # Ok[float](0.5)\n\nmatch r:\n    case Ok(v):\n        assert v == 0.5\n    case Err(e):\n        # unreachable\n        # \"ZeroDivisionError: division by zero\"\n        assert isinstance(e, ZeroDivisionError)\n```\n\n\n### In-place pattern-matching `Result` using `walrus operator` and `match-case`\n\n```python\n@Result\ndef div(x: float, y: float) -> float:\n    # can raise \"ZeroDivisionError: division by zero\" exception\n    z: float = x / y\n    return z\n\n\nmatch r := div(1.0, 2.0): # Ok[float](0.5)\n    case Ok(v):\n        assert v == 0.5\n    case Err(e):\n        # unreachable\n        # \"ZeroDivisionError: division by zero\"\n        assert isinstance(e, ZeroDivisionError)\n```\n\n\n## Advanced Usage\n\n\n### Unwrapping `Result[float, ZeroDivisionError]` as Context Manager\n\n```python\nfrom thresult import Result, Ok, Err\n\n\n@Result[float, ZeroDivisionError]\ndef div(x: float, y: float) -> float:\n    z: float = x / y\n    return z\n\n\ntry:\n    with div(1.0, 0.0) as z:\n        # unreachable \n        pass\nexcept ZeroDivisionError as e:\n    # exception happened\n    pass\n```\n\n\n### Manually create Result value, and Structural Pattern Matching\n\n```python\nfrom thresult import Result, Ok, Err\n\n\ndef div(x: float, y: float) -> Result[float, ZeroDivisionError]:\n    res: Result[float, ZeroDivisionError]\n\n    try:\n        # can raise \"ZeroDivisionError: division by zero\" exception\n        z: float = x / y\n        res = Ok[float](z)\n    except ZeroDivisionError as e:\n        res = Err[ZeroDivisionError](e)\n\n    return res\n\n\nr0: Result = div(1.0, 2.0) # Ok\nr1: Result = div(1.0, 0.0) # Err\n\nmatch r0:\n    case Ok(v):\n        print('Ok, value:', v)\n    case Err(e):\n        print('Err, error:', e) # \"ZeroDivisionError: division by zero\"\n\nmatch r1:\n    case Ok(v):\n        print('Ok, value:', v)\n    case Err(e):\n        print('Err, error:', e) # \"ZeroDivisionError: division by zero\"\n\nz0: float = r0.unwrap() # 0.5\nz1: float = r1.unwrap_or(float('inf')) # inf\nz1: float = r1.unwrap() # raises \"ZeroDivisionError: division by zero\" exception\n```\n\n\n### Decorate function with Result, and Structural Pattern Matching\n\n```python\nfrom thresult import Result, Ok, Err\n\n\n@Result[float, ZeroDivisionError]\ndef div(x: float, y: float) -> float:\n    # can raise \"ZeroDivisionError: division by zero\" exception\n    z: float = x / y\n    return z\n\n\nr0: Result = div(1.0, 2.0) # Ok\nr1: Result = div(1.0, 0.0) # Err\n\nmatch r0:\n    case Ok(v):\n        print('Ok, value:', v)\n    case Err(e):\n        print('Err, error:', e) # \"ZeroDivisionError: division by zero\"\n\nmatch r1:\n    case Ok(v):\n        print('Ok, value:', v)\n    case Err(e):\n        print('Err, error:', e) # \"ZeroDivisionError: division by zero\"\n\nz0: float = r0.unwrap() # 0.5\nz1: float = r1.unwrap_or(float('inf')) # inf\nz1: float = r1.unwrap() # raises \"ZeroDivisionError: division by zero\" exception\n```\n\n\n## Run / Develop Cycle\n```bash\ndocker run --rm -it -v $PWD/thresult:/code -w /code python:3.11-alpine python -B result.py\n```\n\n\n## Testing\n\n```bash\ndocker-compose build thresult-test ; docker-compose run --rm -v $PWD:/test thresult-test\n```\n\n\n## Coverage\n\n```bash\ndocker-compose build thresult-coverage ; docker-compose run --rm -v $PWD:/test thresult-coverage\n```\n\n\n## Building\n\n```bash\ndocker-compose build thresult-build ; docker-compose run --rm thresult-build\n```\n\n\n## Licensing\n\n`thresult` is licensed under the BSD 3 license.\n\nCheck the [LICENSE](https://opensource.org/licenses/BSD-3-Clause) for details.\n\n\n<!-- Badges -->\n[bsd3-image]: https://img.shields.io/badge/License-BSD_3--Clause-blue.svg\n[bsd3-url]: https://opensource.org/licenses/BSD-3-Clause\n[build-image]: https://img.shields.io/gitlab/pipeline-status/tangledlabs/thresult?branch=main\n[coverage-image]: https://img.shields.io/gitlab/pipeline-coverage/tangledlabs/thresult?branch=main\n\n[pypi-project-url]: https://pypi.org/project/thresult/\n[stable-ver-image]: https://img.shields.io/pypi/v/thresult?label=stable\n[python-ver-image]: https://img.shields.io/pypi/pyversions/thresult.svg?logo=python&logoColor=FBE072\n[status-image]: https://img.shields.io/pypi/status/thresult.svg\n",
    "bugtrack_url": null,
    "license": "BSD 3-clause",
    "summary": "Tangled Result",
    "version": "0.9.25",
    "split_keywords": [
        "thresult",
        "result",
        "tangled",
        "tangledgroup",
        "tangledhub",
        "tangledlabs",
        "tangledcloud"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "md5": "41f69ac1a3a6529956111ba7d2593628",
                "sha256": "763a30824a32aa62b30c0418e4c91b2c8391be259c3b6fce2bbb0781483d91ff"
            },
            "downloads": -1,
            "filename": "thresult-0.9.25-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "41f69ac1a3a6529956111ba7d2593628",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10,<4.0",
            "size": 6738,
            "upload_time": "2022-12-01T09:08:33",
            "upload_time_iso_8601": "2022-12-01T09:08:33.273702Z",
            "url": "https://files.pythonhosted.org/packages/4d/e1/b73408fdb352d97c162d030f23c17c105b09eead9e41020ac45c2c483f5b/thresult-0.9.25-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "md5": "195ea0abcd51f63135a546924568a3c5",
                "sha256": "eb2e8a6b169c2fc7b70965e08d3ea8737296a62f4008a656de866ef0820a95c7"
            },
            "downloads": -1,
            "filename": "thresult-0.9.25.tar.gz",
            "has_sig": false,
            "md5_digest": "195ea0abcd51f63135a546924568a3c5",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10,<4.0",
            "size": 7073,
            "upload_time": "2022-12-01T09:08:34",
            "upload_time_iso_8601": "2022-12-01T09:08:34.912033Z",
            "url": "https://files.pythonhosted.org/packages/97/93/a13c429a8f2cdcb5433d20985b79e0d618f83bf94e442b0fc7ac7f1f38ee/thresult-0.9.25.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2022-12-01 09:08:34",
    "github": false,
    "gitlab": true,
    "bitbucket": false,
    "gitlab_user": "tangledlabs",
    "gitlab_project": "thresult",
    "lcname": "thresult"
}
        
Elapsed time: 1.07931s