Skip to content
Pyrula
Pre-release: the packages are not on PyPI yet, so pip install does not resolve. Build from source to try it today.

Try

Try[T] is Success(value) or Failure(exc). It moves an exception from control flow into a value.

from pyrula import Try, Success, Failure
Try.apply(lambda: int("42")) # Success(42)
Try.apply(lambda: int("nope")) # Failure(ValueError(...))
result = Try.apply(lambda: int("42"))
result.map(lambda n: n * 2).get_or_else(0)
result.fold(lambda exc: f"bad input: {exc}", lambda n: f"got {n}")
result.recover(lambda exc: 0) # Failure becomes Success(0)

recover_with(fn) recovers with another Try; or_else(fn) swaps in a fallback Try. get_or_else evaluates its argument eagerly; get_or_else_with(factory) calls the factory once, only on Failure.

to_either() gives Ok(value) or Err(exception). Chain .map_err(...) on the Either to turn the exception into an application error (Try itself has no map_err).

Try.apply, Try.traverse, map and flat_map capture Exception. KeyboardInterrupt and SystemExit propagate. tap and tap_failure are observers: their exceptions propagate instead of becoming a Failure.

def broken(value: int) -> int:
raise ValueError("callback failed")
assert isinstance(Success(1).map(broken), Failure)
try:
Success(1).tap(broken)
except ValueError:
pass # observer errors are not captured

traverse(values, fn) stops at the first Failure; sequence(values) collects existing Try values. Both return a list inside Success.

def parse(raw: str) -> Try[int]:
return Try.apply(lambda: int(raw))
Try.traverse(["1", "2"], parse) # Success([1, 2])
Try.traverse(["1", "nope", "3"], parse) # Failure(ValueError(...))
Try.sequence([Success(1), Success(2)]) # Success([1, 2])

traverse captures Exception from iteration or the callback as a Failure. A callback that returns a non-Try raises TypeError.

match Try.apply(lambda: int("42")):
case Success(value):
message = f"parsed: {value}"
case Failure(error):
message = f"rejected: {error}"
assert message == "parsed: 42"
Success(Success(5)).flatten() # Success(5)

flatten raises TypeError if the Success does not hold a Try.

@do chains dependent Try calls. The JSON form is in JSON form.

View this page as Markdown