# rustshed
[![Python 3.10](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/release/python-3100/)
[![codecov](https://codecov.io/gh/pawelrubin/rustshed/branch/main/graph/badge.svg?token=LV5XXHDSF5)](https://codecov.io/gh/pawelrubin/rustshed)
[![license](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/pawelrubin/rustshed/blob/main/LICENSE)
A collection of Rust types in Python with complete type annotations.
### Supported Types
- Option
- Result
## Install
```shell
pip install rustshed
```
## Examples
### Option
The `Option` type represents an optional value: every `Option[T]` is either `Some[T]` and contains a value of type `T`, or `Null` (`None` in Rust), and does not.
```Python
from typing import SupportsIndex, TypeVar
from rustshed import Null, Option, Some
T = TypeVar("T")
class SafeList(list[T]):
def get(self, index: SupportsIndex) -> Option[T]:
try:
return Some(self[index])
except IndexError:
return Null
a_list = SafeList([2, 1, 3, 7])
print(a_list.get(1)) # Some(value=1)
print(a_list.get(420)) # Null
```
### Result
The `Result` is the type used for returning and propagating errors: every `Result[T, E]` is either `Ok[T]`, representing success and containing a value of type `T`, or `Err[E]`, representing failure and containing an error of type `E`.
```python
from rustshed import to_result, Result
@to_result[ValueError]
def parse(x: str) -> int:
return int(x)
def multiply(a: str, b: str) -> Result[int, str]:
# try to parse two strings and multiply them
# map a possible error to str
return parse(a).and_then(lambda n: parse(b).map(lambda m: n * m)).map_err(str)
print(multiply("21", "2")) # Ok(value=42)
print(multiply("2!", "2")) # Err(error="invalid literal for int() with base 10: '2!'")
```
### Rust's question mark (?) operator
The question mark (`?`) operator in Rust hides some of the boilerplate of propagating errors up the call stack. Implementing this operator in Python would require changes to the language grammar, hence in **rustshed** it had to be implemented differently.
### Q property
The question mark's functionality has been implemented via the `Q` property (for both `Option` and `Result` types) combined with the `rustshed.result_shortcut` or `rustshed.option_shortcut` decorator.
```python
from rustshed import Ok, Result, to_result, result_shortcut
@to_result[ValueError]
def parse(x: str) -> int:
return int(x)
# explicit early error return with match statements
def try_to_parse_early_return(a: str, b: str) -> Result[int, ValueError]:
match parse(a):
case Ok(value):
x = value
case err:
return err
match parse(b):
case Ok(value):
y = value
case err:
return err
return Ok(x + y)
# early error return using the Q property
@result_shortcut
def try_to_parse(a: str, b: str) -> Result[int, ValueError]:
x = parse(a).Q
y = parse(b).Q
return Ok(x + y)
```
Raw data
{
"_id": null,
"home_page": "https://github.com/pawelrubin/rustshed",
"name": "rustshed",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.10,<4.0",
"maintainer_email": "",
"keywords": "rust,result,option",
"author": "Pawe\u0142 Rubin",
"author_email": "pawelrubindev@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/76/63/b262eb6219e6a175c55a4e56c13a056d0d1397e4546c34206ac3104667d1/rustshed-0.5.0.tar.gz",
"platform": null,
"description": "# rustshed\n\n[![Python 3.10](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/release/python-3100/)\n[![codecov](https://codecov.io/gh/pawelrubin/rustshed/branch/main/graph/badge.svg?token=LV5XXHDSF5)](https://codecov.io/gh/pawelrubin/rustshed)\n[![license](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/pawelrubin/rustshed/blob/main/LICENSE)\n\nA collection of Rust types in Python with complete type annotations.\n\n### Supported Types\n\n- Option\n- Result\n\n## Install\n\n```shell\npip install rustshed\n```\n\n\n## Examples\n\n### Option\n\nThe `Option` type represents an optional value: every `Option[T]` is either `Some[T]` and contains a value of type `T`, or `Null` (`None` in Rust), and does not.\n\n```Python\nfrom typing import SupportsIndex, TypeVar\n\nfrom rustshed import Null, Option, Some\n\nT = TypeVar(\"T\")\n\n\nclass SafeList(list[T]):\n def get(self, index: SupportsIndex) -> Option[T]:\n try:\n return Some(self[index])\n except IndexError:\n return Null\n\na_list = SafeList([2, 1, 3, 7])\nprint(a_list.get(1)) # Some(value=1)\nprint(a_list.get(420)) # Null\n```\n\n### Result\n\nThe `Result` is the type used for returning and propagating errors: every `Result[T, E]` is either `Ok[T]`, representing success and containing a value of type `T`, or `Err[E]`, representing failure and containing an error of type `E`.\n\n```python\nfrom rustshed import to_result, Result\n\n\n@to_result[ValueError]\ndef parse(x: str) -> int:\n return int(x)\n\n\ndef multiply(a: str, b: str) -> Result[int, str]:\n # try to parse two strings and multiply them\n # map a possible error to str\n return parse(a).and_then(lambda n: parse(b).map(lambda m: n * m)).map_err(str)\n\n\nprint(multiply(\"21\", \"2\")) # Ok(value=42)\nprint(multiply(\"2!\", \"2\")) # Err(error=\"invalid literal for int() with base 10: '2!'\")\n```\n\n### Rust's question mark (?) operator\n\nThe question mark (`?`) operator in Rust hides some of the boilerplate of propagating errors up the call stack. Implementing this operator in Python would require changes to the language grammar, hence in **rustshed** it had to be implemented differently.\n\n### Q property\n\nThe question mark's functionality has been implemented via the `Q` property (for both `Option` and `Result` types) combined with the `rustshed.result_shortcut` or `rustshed.option_shortcut` decorator.\n\n\n```python\nfrom rustshed import Ok, Result, to_result, result_shortcut\n\n\n@to_result[ValueError]\ndef parse(x: str) -> int:\n return int(x)\n\n\n# explicit early error return with match statements\ndef try_to_parse_early_return(a: str, b: str) -> Result[int, ValueError]:\n match parse(a):\n case Ok(value):\n x = value\n case err:\n return err\n\n match parse(b):\n case Ok(value):\n y = value\n case err:\n return err\n\n return Ok(x + y)\n\n\n# early error return using the Q property\n@result_shortcut\ndef try_to_parse(a: str, b: str) -> Result[int, ValueError]:\n x = parse(a).Q\n y = parse(b).Q\n return Ok(x + y)\n\n```\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Rust types in Python.",
"version": "0.5.0",
"split_keywords": [
"rust",
"result",
"option"
],
"urls": [
{
"comment_text": "",
"digests": {
"md5": "162806cf37398aacce25c5dcc405ca70",
"sha256": "90545bc8a32fc46cbe93cdddc659c1b51cca0eba65863c90dbc31e0fdd1012c6"
},
"downloads": -1,
"filename": "rustshed-0.5.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "162806cf37398aacce25c5dcc405ca70",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10,<4.0",
"size": 10955,
"upload_time": "2022-12-22T18:37:54",
"upload_time_iso_8601": "2022-12-22T18:37:54.105299Z",
"url": "https://files.pythonhosted.org/packages/17/44/97759d5a1d604aab464f4f90f0f21cc9c801f66fda175616505a14ce50dd/rustshed-0.5.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"md5": "c82cd22aa163aae2ad9513fc498c8caa",
"sha256": "27bf1da6ee635864e94cdea83b2d514562585c28b5a94b3829e45952b6de4bf9"
},
"downloads": -1,
"filename": "rustshed-0.5.0.tar.gz",
"has_sig": false,
"md5_digest": "c82cd22aa163aae2ad9513fc498c8caa",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10,<4.0",
"size": 10251,
"upload_time": "2022-12-22T18:37:55",
"upload_time_iso_8601": "2022-12-22T18:37:55.677463Z",
"url": "https://files.pythonhosted.org/packages/76/63/b262eb6219e6a175c55a4e56c13a056d0d1397e4546c34206ac3104667d1/rustshed-0.5.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2022-12-22 18:37:55",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "pawelrubin",
"github_project": "rustshed",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "rustshed"
}