This package introduces Option and Result, which are basic functional monad types, to your project!
pip install rustipycheck 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_VALUEcheck 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