Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
set -xe
python -VV
python -m site
python -m pip install --upgrade pip wheel poetry==1.2.2
python -m pip install --upgrade pip wheel poetry==1.3.2
python -m pip install --upgrade coverage[toml] virtualenv tox tox-gh-actions
- name: "Run tox targets for ${{ matrix.python-version }}"
run: "python -m tox"
Expand Down Expand Up @@ -57,7 +57,7 @@ jobs:
python-version: "3.9"

- name: "Install poetry, check-wheel-content, and twine"
run: "python -m pip install poetry==1.2.2 twine check-wheel-contents"
run: "python -m pip install poetry==1.3.2 twine check-wheel-contents"
- name: "Build package"
run: "poetry build"
- name: "List result"
Expand Down
1 change: 1 addition & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## 23.1.0 (UNRELEASED)

- Introduce the `tagged_union` strategy. ([#318](https://github.com/python-attrs/cattrs/pull/318) [#317](https://github.com/python-attrs/cattrs/issues/317))
- Introduce the `cattrs.transform_error` helper function for formatting validation exceptions. ([258](https://github.com/python-attrs/cattrs/issues/258) [342](https://github.com/python-attrs/cattrs/pull/342))
- Introduce `override.struct_hook` and `override.unstruct_hook`. Learn more [here](https://catt.rs/en/latest/customizing.html#struct-hook-and-unstruct-hook).
[#326](https://github.com/python-attrs/cattrs/pull/326)
- Fix generating structuring functions for types with angle brackets (`<>`) and pipe symbols (`|`) in the name.
Expand Down
2 changes: 1 addition & 1 deletion docs/cattrs.preconf.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ cattrs.preconf.bson module
:show-inheritance:

cattrs.preconf.cbor2 module
--------------------------
---------------------------

.. automodule:: cattrs.preconf.cbor2
:members:
Expand Down
8 changes: 8 additions & 0 deletions docs/cattrs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ cattrs.gen module
:undoc-members:
:show-inheritance:

cattrs.v module
---------------

.. automodule:: cattrs.v
:members:
:undoc-members:
:show-inheritance:

Module contents
---------------

Expand Down
11 changes: 0 additions & 11 deletions docs/cattrs.strategies.rst
Original file line number Diff line number Diff line change
@@ -1,17 +1,6 @@
cattrs.strategies package
=========================

Submodules
----------

cattrs.strategies.subclasses module
-----------------------------------

.. automodule:: cattrs.strategies.subclasses
:members:
:undoc-members:
:show-inheritance:

Module contents
---------------

Expand Down
4 changes: 4 additions & 0 deletions docs/preconf.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ When parsing msgpack data from bytes, the library needs to be passed `strict_map

## _cbor2_

```{versionadded} 23.1.0

```

Found at {mod}`cattrs.preconf.cbor2`.

_cbor2_ implements a fully featured CBOR encoder with several extensions for handling shared references, big integers, rational numbers and so on.
Expand Down
54 changes: 51 additions & 3 deletions docs/validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
_cattrs_ has a detailed validation mode since version 22.1.0, and this mode is enabled by default.
When running under detailed validation, the un/structuring hooks are slightly slower but produce more precise and exhaustive error messages.

## Detailed validation
## Detailed Validation

```{versionadded} 22.1.0

```
In detailed validation mode, any un/structuring errors will be grouped and raised together as a {class}`cattrs.BaseValidationError`, which is a [PEP 654 ExceptionGroup](https://www.python.org/dev/peps/pep-0654/).
ExceptionGroups are special exceptions which contain lists of other exceptions, which may themselves be other ExceptionGroups.
In essence, ExceptionGroups are trees of exceptions.
Expand All @@ -23,7 +26,7 @@ class Class:
a_list: list[int]
a_dict: dict[str, int]

>>> structure({"a_list": ["a"], "a_dict": {"str": "a"}})
>>> structure({"a_list": ["a"], "a_dict": {"str": "a"}}, Class)
+ Exception Group Traceback (most recent call last):
| File "<stdin>", line 1, in <module>
| File "/Users/tintvrtkovic/pg/cattrs/src/cattr/converters.py", line 276, in structure
Expand Down Expand Up @@ -63,7 +66,52 @@ class Class:
+------------------------------------
```

## Non-detailed validation
### Transforming Exceptions into Error Messages

```{versionadded} 23.1.0

```

ExceptionGroup stack traces are great while you're developing, but sometimes a more compact representation of validation errors is better.
_cattrs_ provides a helper function, {func}`cattrs.transform_error`, which transforms validation errors into lists of error messages.

The example from the previous paragraph produces the following error messages:

```python
>>> from cattrs import transform_error

>>> try:
... structure({"a_list": ["a"], "a_dict": {"str": "a"}}, Class)
... except Exception as exc:
... print(transform_error(exc))

[
'invalid value for type, expected int @ $.a_list[0]',
"invalid value for type, expected int @ $.a_dict['str']"
]
```

A small number of built-in exceptions are converted into error messages automatically.
This can be further customized by providing {func}`cattrs.transform_error` with a function that it can use to turn individual, non-ExceptionGroup exceptions into error messages.
A useful pattern is wrapping the default, {func}`cattrs.v.format_exception` function.

```
>>> from cattrs.v iomport format_exception

>>> def my_exception_formatter(exc: BaseException, type) -> str:
... if isinstance(exc, MyInterestingException):
... return "My error message"
... return format_exception(exc, type)

>>> try:
... structure(..., Class)
... except Exception as exc:
... print(transform_error(exc, format_exception=my_exception_formatter))
```

If even more customization is required, {func}`cattrs.transform_error` can be copied over into your codebase and adjusted as needed.

## Non-detailed Validation

Non-detailed validation can be enabled by initializing any of the converters with `detailed_validation=False`.
In this mode, any errors during un/structuring will bubble up directly as soon as they happen.
99 changes: 79 additions & 20 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,15 @@ pytest-benchmark = "^3.2.3"
hypothesis = "^6.54.5"
pendulum = "^2.1.2"
isort = { version = "5.10.1", python = "<4" }
black = "^22.8.0"
black = "^23.1.0"
immutables = "^0.18"
furo = "^2022.9.29"
furo = "^2023.3.27"
coverage = "^6.2"
urllib3 = { version = "^1.26.12", python = "<4" }
sphinx-copybutton = "^0.5.0"
myst-parser = "^0.18.1"
cbor2 = "^5.4.6"
pyperf = "^2.6.0"

[tool.poetry.urls]
"Changelog" = "https://catt.rs/en/latest/history.html"
Expand Down Expand Up @@ -85,5 +87,4 @@ requires = ["poetry-core>=1.1.0"]
build-backend = "poetry.core.masonry.api"

[tool.mypy]
plugins = "unionize.py"
strict = true
12 changes: 9 additions & 3 deletions src/cattrs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
from .converters import BaseConverter, Converter, GenConverter, UnstructureStrategy
from .errors import (
AttributeValidationNote,
BaseValidationError,
ClassValidationError,
ForbiddenExtraKeysError,
IterableValidationError,
IterableValidationNote,
StructureHandlerNotFoundError,
)
from .gen import override
from .v import transform_error

__all__ = (
"AttributeValidationNote",
"BaseConverter",
"BaseValidationError",
"ClassValidationError",
Expand All @@ -22,16 +26,18 @@
"GenConverter",
"global_converter",
"IterableValidationError",
"IterableValidationNote",
"override",
"preconf",
"register_structure_hook",
"register_structure_hook_func",
"register_unstructure_hook",
"register_structure_hook",
"register_unstructure_hook_func",
"structure",
"register_unstructure_hook",
"structure_attrs_fromdict",
"structure_attrs_fromtuple",
"structure",
"StructureHandlerNotFoundError",
"transform_error",
"unstructure",
"UnstructureStrategy",
)
Expand Down
Loading