Skip to content
Closed
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: 4 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ Our backwards-compatibility policy can be found [here](https://github.com/python
- For {class}`cattrs.errors.StructureHandlerNotFoundError` and {class}`cattrs.errors.ForbiddenExtraKeysError`
correctly set {attr}`BaseException.args` in `super()` and hence make them pickable.
([#666](https://github.com/python-attrs/cattrs/pull/666))
- Do not Unstructure the faulty state {data}`attrs.NOTHING` instead of to `1` (int). The unstructure to `1` was caused
by a change in attrs 22.2 that {data}`attrs.NOTHING` is internally represented as an integer {class}`enum.Enum`,
but as it is logically just a Singleton we apply now the identity-function on unstructuring it.
([#667](https://github.com/python-attrs/cattrs/pull/667))

## 25.1.1 (2025-06-04)

Expand Down
3 changes: 2 additions & 1 deletion src/cattrs/converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from pathlib import Path
from typing import Any, Optional, Tuple, TypeVar, overload

from attr._make import _Nothing
from attrs import Attribute, resolve_types
from attrs import has as attrs_has
from typing_extensions import Self
Expand Down Expand Up @@ -223,7 +224,7 @@ def __init__(
unstructure_fallback_factory, self
)
self._unstructure_func.register_cls_list(
[(bytes, identity), (str, identity), (Path, str)]
[(bytes, identity), (str, identity), (Path, str), (_Nothing, identity)]
)
self._unstructure_func.register_func_list(
[
Expand Down
15 changes: 15 additions & 0 deletions tests/test_enums.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Tests for enums."""

from attrs import NOTHING
from hypothesis import given
from hypothesis.strategies import data, sampled_from
from pytest import raises
Expand Down Expand Up @@ -29,3 +30,17 @@ def test_enum_failure(enum):
converter.structure("", type)

assert exc_info.value.args[0] == f" not in literal {type!r}"


def test_nothing_from_attrs():
"""Test that `NOTHING` from attrs does not unstructure to `1` (int), but remains `NOTHING`."""
converter = BaseConverter()

assert (
converter.unstructure(NOTHING) != 1
), "NOTHING should not unstructure to 1 (int)."
assert not isinstance(converter.unstructure(NOTHING), int)
assert not converter.unstructure(
NOTHING
) # bool(NOTHING) should be False although `bool(1)` is True
assert converter.unstructure(NOTHING) is NOTHING
6 changes: 3 additions & 3 deletions tests/test_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
"err_cls, err_args",
[
(StructureHandlerNotFoundError, ("Structure Message", int)),
(ForbiddenExtraKeysError, ("Forbidden Message", int, {"foo", "bar"})),
(ForbiddenExtraKeysError, ("", str, {"foo", "bar"})),
(ForbiddenExtraKeysError, (None, list, {"foo", "bar"})),
(ForbiddenExtraKeysError, ("Forbidden Message", int, {"foo"})),
(ForbiddenExtraKeysError, ("", str, {"foo"})),
(ForbiddenExtraKeysError, (None, list, {"foo"})),
(
BaseValidationError,
("BaseValidation Message", [ValueError("Test BaseValidation")], int),
Expand Down