This package introduces Option and Result, which are basic functional monad types, to your project!
pip install rustipy
check the test file for more examples
from rustipy.result import Result, Ok, Err def square(x: int) -> int: return x * x def ok_if_positive(x: int) -> Result[int, str]: if x > 0: return Ok(x) else: return Err("Not positive") def err_to_default_ok(e: str) -> Result[int, str]: return Ok(DEFAULT_VALUE) def len_str(s: str) -> int: return len(s) OK_VALUE = 100 DEFAULT_VALUE = 0 def test_flatten(): ok_ok: Result[Result[int, str], str] = Ok(Ok(OK_VALUE)) ok_err: Result[Result[int, str], str] = Ok(Err(ERR_VALUE)) err_outer: Result[Result[int, str], str] = Err(OTHER_ERR_VALUE) ok_not_result: Result[int, str] = Ok(123) assert ok_ok.flatten() == Ok(OK_VALUE) assert ok_err.flatten() == Err(ERR_VALUE) assert err_outer.flatten() == Err(OTHER_ERR_VALUE) with pytest.raises(TypeError): ok_not_result.flatten() def test_chaining_err_path(): res = ( Ok(-5) .map(square) .and_then(ok_if_positive) # Ok(25) .and_then(err_if_negative) # Ok(25) .and_then(lambda x: Err("Force Err")) # Err("Force Err") .or_else(err_to_default_ok) # Ok(DEFAULT_VALUE) .unwrap() ) assert res == DEFAULT_VALUE
check the test file for more examples
from rustipy.option import Option, Some, Nothing from tests.test_result import OK_VALUE def int_to_some_str(x: int) -> Option[str]: return Some(str(x)) def int_to_nothing_if_odd(x: int) -> Option[int]: return Nothing if x % 2 != 0 else Some(x) def int_to_some_str(x: int) -> Option[str]: return Some(str(x)) def int_to_nothing_if_odd(x: int) -> Option[int]: return Nothing if x % 2 != 0 else Some(x) SOME_VALUE = 123 def test_and_then(): some_even: Option[int] = Some(10) some_odd: Option[int] = Some(5) nothing: Option[int] = NOTHING assert some_even.and_then(int_to_some_str) == Some("10") assert some_odd.and_then(int_to_some_str) == Some("5") assert nothing.and_then(int_to_some_str) == NOTHING assert some_even.and_then(int_to_nothing_if_odd) == Some(10) assert some_odd.and_then(int_to_nothing_if_odd) == NOTHING assert nothing.and_then(int_to_nothing_if_odd) == NOTHING def test_inspect(): inspected_val = None def inspector(x: int): nonlocal inspected_val inspected_val = x * 2 some: Option[int] = Some(SOME_VALUE) nothing: Option[int] = NOTHING assert some.inspect(inspector) is some # Returns self assert inspected_val == SOME_VALUE * 2 inspected_val = None # Reset assert nothing.inspect(inspector) is nothing # Returns self assert inspected_val is None def test_type_guards(): some: Option[int] = Some(OK_VALUE) nothing: Option[int] = NOTHING if is_some(some): assert some.unwrap() == OK_VALUE else: pytest.fail("is_some failed for Some value") if is_nothing(some): pytest.fail("is_nothing succeeded for Some value") if is_some(nothing): pytest.fail("is_some succeeded for Nothing value") if is_nothing(nothing): # Can't unwrap Nothing, just check identity assert nothing is NOTHING else: pytest.fail("is_nothing failed for Nothing value")
- Make some changes
- Increment the version at
[project]section in[pyproject.toml] - Commit the changes
- Build the package
$ uv build
- Tag the release
$ git tag -vX.X.X
$ git push origin vX.X.X
Done