with-err
with-err is a python library that converts try-except pattern into Go-like result, err pattern. I feel result, err pattern easier to maintain in large projects.
Getting Started
Install
pip install with-err
(with uv)
uv pip install with-err
Use as Function
import json
from with_err import with_err
json_loads_e = with_err(json.loads)
data, err = json_loads_e('{"a": 1}')
assert err is None
assert data == {"a": 1}
data, err = json_loads_e('{"a": }')
assert isinstance(err, json.decoder.JSONDecodeError)
assert data is None
Use as Decorator
import json
from with_err import with_err
@with_err
def json_loads_e(a: str):
return json.loads(a)
data, err = json_loads_e('{"a": 1}')
assert err is None
assert data == {"a": 1}
data, err = json_loads_e('{"a": }')
assert isinstance(err, json.decoder.JSONDecodeError)
assert data is None
with_err with Specified Exceptions
Return err only with specified exceptions and raise other exceptions.
import json
from with_err import with_err
@with_err(json.decoder.JSONDecodeError)
def json_loads_e(a: str):
return json.loads(a)
data, err = json_loads_e('{"a": 1}')
assert err is None
assert data == {"a": 1}
data, err = json_loads_e('{"a": }')
assert isinstance(err, json.decoder.JSONDecodeError)
assert data is None
# raise json.decoder.JSONDecodeError
import json
import re
from with_err import with_err
@with_err(re.PatternError)
def json_loads_e(a: str):
return json.loads(a)
data, err = json_loads_e('{"a": }')
# function
import json
from with_err import with_err
json_loads_e = with_err(json.decoder.JSONDecodeError)(json.loads)
data, err = json_loads_e('{"a": 1}')
assert err is None
assert data == {"a": 1}
data, err = json_loads_e('{"a": }')
assert isinstance(err, json.decoder.JSONDecodeError)
assert data is None
# empty: return all Exceptions
import json
from with_err import with_err
json_loads_e = with_err()(json.loads)
data, err = json_loads_e('{"a": 1}')
assert err is None
assert data == {"a": 1}
data, err = json_loads_e('{"a": }')
assert isinstance(err, json.decoder.JSONDecodeError)
assert data is None
Async Functions
from with_err import with_err
async def async_fetch_data(endpoint: str) -> dict[str, str]:
if endpoint == "bad":
raise ValueError("Failed to reach endpoint")
return {"status": "ok"}
async_fetch_data_e = with_err(async_fetch_data)
res, err = await async_fetch_data_e("bad")
assert isinstance(err, ValueError)
assert res is None
Generators
from with_err import with_err
@with_err
def my_stream():
yield 1
raise ValueError('invalid')
for idx, (each, err) in enumerate(my_stream()):
if idx == 0:
assert each == 1
assert err is None
else:
assert each is None
assert isinstance(err, ValueError)
Async Generators
from with_err import with_err
@with_err
async def my_async_stream():
yield 1
raise ValueError('invalid')
async for each, err in my_async_stream():
if each == 1:
assert each == 1
assert err is None
else:
assert each is None
assert isinstance(err, ValueError)
Functions Returning list or tuple
@with_err
def my_list_func(is_good=False):
if not is_good:
raise ValueError('not good')
return [1, 2]
data, err = my_list_func()
assert data is None
assert isinstance(err, ValueError)
data, err = my_list_func(True)
assert data is not None
assert err is None
item1, item2 = data
assert item1 == 1
assert item2 == 2
Get err Traceback Stack
import json
from with_err import with_err, get_err_strs
@with_err
def json_loads_e(a: str):
return json.loads(a)
_data, err = json_loads_e('{"a": 1}')
err_stack = get_err_strs(err)
assert err is None
assert err_stack == []
import json
import re
from with_err import with_err, get_err_strs
@with_err
def json_loads_e(a: str):
return json.loads(a)
_data, err = json_loads_e('{"a": }')
err_stack = get_err_strs(err)
err_str = '\n'.join(err_stack)
assert isinstance(err, json.decoder.JSONDecodeError)
assert len(err_stack) > 0
assert re.search(r', line \d+, in json_loads_e', err_str)
assert re.search(r'json/__init__.py", line \d+, in loads', err_str)
assert 'json.decoder.JSONDecodeError: Expecting value:' in err_str
Raise err
import json
import re
from with_err import with_err, get_err_strs, raise_err
@with_err
def json_loads_e(a: str):
return json.loads(a)
def gen_err():
data, err = json_loads_e('{"a": }')
return data, raise_err(err)
data, err = gen_err()
err_stack = get_err_strs(err)
err_str = '\n'.join(err_stack)
assert isinstance(err, json.decoder.JSONDecodeError)
assert len(err_stack) > 0
assert re.search(r', line \d+, in gen_err', err_str)
assert re.search(r', line \d+, in json_loads_e', err_str)
assert re.search(r'json/__init__.py", line \d+, in loads', err_str)
assert 'json.decoder.JSONDecodeError: Expecting value:' in err_str
Raise err with Continuous @with_err
import json
import re
from with_err import with_err, get_err_strs, raise_err
@with_err
def json_loads_e(a: str):
return json.loads(a)
@with_err
def gen_err():
data, err = json_loads_e('{"a": }')
if err is not None:
raise err
return data
data, err = gen_err()
err_stack = get_err_strs(err)
err_str = '\n'.join(err_stack)
assert isinstance(err, json.decoder.JSONDecodeError)
assert len(err_stack) > 0
assert re.search(r', line \d+, in gen_err', err_str)
assert re.search(r', line \d+, in json_loads_e', err_str)
assert re.search(r'json/__init__.py", line \d+, in loads', err_str)
assert 'json.decoder.JSONDecodeError: Expecting value:' in err_str
Acknowledgement
The implementation is based on the following Gemini / ChatGPT suggestions:
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
with_err-1.2.1.tar.gz
(4.3 kB
view details)
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file with_err-1.2.1.tar.gz.
File metadata
- Download URL: with_err-1.2.1.tar.gz
- Upload date:
- Size: 4.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b74f6895789d9c7ea642e6c5a7aa9ec72b7b72345dc0d3f584945c49d29bf83b
|
|
| MD5 |
42ab6f21783343ee7ef4c94b9d8e1be6
|
|
| BLAKE2b-256 |
54f2708a377775dad4d7d45c7cd264931cb4faaf0763ccb77ba61e576035e460
|
File details
Details for the file with_err-1.2.1-py3-none-any.whl.
File metadata
- Download URL: with_err-1.2.1-py3-none-any.whl
- Upload date:
- Size: 5.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b90619ffb7af771c9d620e735e271c1cb8db33b1b04f09765e949ca362b1c0be
|
|
| MD5 |
77212daa4f4f32dd681540653cdd148f
|
|
| BLAKE2b-256 |
ac60de416446ec01eb3ef985ad5561cc4cd1d00b4d806e358ebb3d23d21d8520
|