[![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"
}