Skip to main content

trye

Ergonomic exception handling for Python.

Inspired by the ECMAScript Try Operator proposal. Instead of try/except blocks, wrap any callable in trye() and get back a typed Result — either Ok(val) or Err(err).

Requires Python 3.14+ (uses generic syntax and type aliases).

Install

uv add trye

Usage

from trye import trye, atrye, is_ok, is_err, Ok, Err

Wrapping a function call

Pass the function and its arguments directly:

result = trye(json.loads, '{"foo": "bar"}')

Or use a lambda for more complex expressions:

result = trye(lambda: db.query("SELECT * FROM users"))

For async functions, use atrye:

result = await atrye(fetch_user, user_id)

Checking and narrowing

is_ok() and is_err() check the result and narrow the type for your type checker:

result = trye(json.loads, '{"foo": "bar"}')
if is_ok(result):
    print(result.val)    # dict
else:
    print(result.err)    # Exception
result = trye(some_function, arg1, arg2)
if is_err(result):
    log_error(result.err)
    return
# result is narrowed to Ok here
use_value(result.val)

unwrap

If you just want the value or to re-raise the exception:

value = trye(json.loads, data).unwrap()

unwrap() returns the value from Ok, or raises the exception from Err.

match/case

result = trye(int, user_input)
match result:
    case Ok(val=v):
        print(f"parsed: {v}")
    case Err(err=e):
        print(f"failed: {e}")

Sentinel fields

Both Ok and Err have sentinel fields so you can always safely check either side:

result = trye(some_function, arg)
if result.err is not None:
    handle_error(result.err)
if result.val is not None:
    use_value(result.val)

Creating results manually

You can create Ok and Err objects directly:

from trye import Ok, Err

success = Ok(42)
failure = Err(ValueError("something went wrong"))

This is useful for bridging non-trye code, writing tests, or returning results from your own functions:

def parse_config(path: str) -> Result[Config]:
    if not path.endswith(".toml"):
        return Err(ValueError(f"unsupported format: {path}"))
    return Ok(load_toml(path))

API

Name Description
trye(f, *args, **kwargs) Call f with args, return Ok(result) or Err(exception)
atrye(f, *args, **kwargs) Async version — await f, return Ok(result) or Err(exception)
is_ok(result) TypeIs narrowing to Ok[T]
is_err(result) TypeIs narrowing to Err
Ok[T] Success wrapper. .val: T, .err: None, .unwrap() -> T
Err Error wrapper. .err: Exception, .val: None, .unwrap() -> Never
Result[T] Type alias for Ok[T] | Err

Arguments are fully typed via ParamSpec, so type checkers will catch incorrect arguments to the wrapped function.

Development

Install uv, then:

uv sync

This project uses poethepoet for tasks:

uv run poe fmt       # format
uv run poe lint      # lint
uv run poe check     # type check (basedpyright + ty)
uv run poe test      # test

uv run poe all       # all of the above

License

MIT

Metadata

Release files for trye 0.1.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for trye 0.1.5
File Size Uploaded
trye-0.1.5.tar.gz 19.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for trye 0.1.5
File Interpreter ABI Platform
trye-0.1.5-py3-none-any.whl Python 3 none any Details

Total release size: 23.5 kB

Release files / trye-0.1.5.tar.gz

Download URL trye-0.1.5.tar.gz
Size 19.0 kB
Tags Source
SHA-256 checksum
How to use checksums
a22e67904c85b214b0ba39d050fe56445d061a02288db05d1062ea9a063854f6
BLAKE2b-256 checksum
How to use checksums
03961665302c21cc7d2b92ccc183fd467ef562f44c03f8ad28be22705a82c1de
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 5, 2026.

Transparency log

Release files / trye-0.1.5-py3-none-any.whl

Download URL trye-0.1.5-py3-none-any.whl
Size 4.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4c86b1eda45477f2f5c01d1af2c595dbff287df686c6adade80754f81dd068bc
BLAKE2b-256 checksum
How to use checksums
57c52a62c3f9748d1a3cf0ab22a6a555822571a23e2ad2ddfdb95b5d64fc9b75
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 5, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.5 This release

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page