Well Formed Errors¶
Basic Usage¶
In a real-world service, we often want our exception information to be communicated in a well-formed way to the calling service, so that they can do something useful with it, such as present it on the browser. For this reason, Typedpy includes an “errors” module that implements such functionality. Here is an example of usage, taken from the tests (test_errors.py):
from typedpy import ErrorInfo, standard_readable_error_for_typedpy_exception
def test_real_world_usage():
try:
# Supposed this is inconsistent with the definition of structure Foo
Foo(a=1, b=10, c=1.1, arr=['abc', 1])
except Exception as ex:
assert standard_readable_error_for_typedpy_exception(ex) == \
ErrorInfo(field='arr_1', problem='Expected a string', value='1')
Failing Fast vs Gathering All the Errors¶
By default, the __init__() function of a structure fails fast. However, Typepy provides an option to collect all the errors and then throw. An example use-case: a webapp, submits a form to a back-end with a typedpy API. The web-app may want to present all the validation errors in the data, instead of just the first one it encountered.
An example of usage, take from the automated tests:
@fixture(name="all_errors")
def fixture_all_errors():
Structure.set_fail_fast(False)
yield
Structure.set_fail_fast(True)
def test_multiple_errors_not_fail_fast(all_errors):
with raises(Exception) as ex:
Foo(a=1, b=1000, c=-5, arr=[1])
errs = standard_readable_error_for_typedpy_exception(ex.value)
assert ErrorInfo(field='b', problem='Expected a maximum of 100', value='1000') in errs
assert ErrorInfo(field='arr_0', problem='Expected a string', value='1') in errs
assert ErrorInfo(field='c', problem='Expected a positive number', value='-5') in errs
An ErrorInfo can also be hierarchical, in case the error is nested, for example:
class Person(Structure):
name: str
ssid: String(minLength=3)
class Group(Structure):
people: list[Person]
with raises(Exception) as ex:
deserialize_structure(Group, { "people": [{"name": "john", "ssid": "13"}]})
errs = standard_readable_error_for_typedpy_exception(ex.value)
expected_errors = [
ErrorInfo(
field="people_0",
problem=[
ErrorInfo(
field="ssid", problem="Expected a minimum length of 3", value="'13'"
)
],
),
]
assert errs == expected_errors
If you don’t want to use the custom ErrorInfo class, and just get a “simplied” list of errors, Typedpy offers the function get_simplified_error(). Here is an example usage:
err_str = '["c: [\\"b:[\\\\\\"a: got foo; expected bar\\\\\\"]\\"]"]'
simple_form = get_simplified_error(err_str)
assert simple_form == ["c: b: a: got foo; expected bar"]