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:
https://share.gemini.google/BDvazjX2RWsE https://chatgpt.com/share/6a8b20b2-4ad4-83ea-9926-4f204ebc4e65 https://chatgpt.com/share/6a8b209f-a6f4-83ea-a7da-5d4bf54e4ecd https://chatgpt.com/share/6a8b53e2-570c-83ea-94e4-b312d8048059
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
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.0.tar.gz.
File metadata
- Download URL: with_err-1.2.0.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 |
6783b4cd5de9b34d2e18969e3b076262abb0e355ed512e6eb73f0d90332ec964
|
|
| MD5 |
8b7818d838d60ce0c5a9082f1228ea5e
|
|
| BLAKE2b-256 |
2eeba4cd5c78adc47f4d6a2ee6d70ed1e34a465233b6acca3e805075fa7ed0d7
|
File details
Details for the file with_err-1.2.0-py3-none-any.whl.
File metadata
- Download URL: with_err-1.2.0-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 |
fb140cbe0327c774ae66ff7596ac6e24ba760d0a361c498807ba1f3f204b8df2
|
|
| MD5 |
fefbc0aba23398945a6ebc7a71565629
|
|
| BLAKE2b-256 |
e83e052f8f5e14dc2e6f3c2a5096a105b979f30f431dd57526dffb2255927e03
|