Skip to content

Commit df9af01

Browse files
committed
Merge branch '23.2'
2 parents 8878ad3 + bed932c commit df9af01

4 files changed

Lines changed: 24 additions & 3 deletions

File tree

.github/workflows/main.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ on:
55
push:
66
branches: ["main"]
77
pull_request:
8-
branches: ["main"]
98
workflow_dispatch:
109

1110
jobs:

HISTORY.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
- Imports are now sorted using Ruff.
1212
- Tests are run with the pytest-xdist plugin by default.
1313

14+
## 23.2.2 (2023-11-21)
15+
16+
- Fix a regression when unstructuring `Any | None`.
17+
([#453](https://github.com/python-attrs/cattrs/issues/453))
18+
1419
## 23.2.1 (2023-11-18)
1520

1621
- Fix unnecessary `typing_extensions` import on Python 3.11.

src/cattrs/converters.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -973,7 +973,12 @@ def gen_unstructure_optional(self, cl: Type[T]) -> Callable[[T], Any]:
973973
"""Generate an unstructuring hook for optional types."""
974974
union_params = cl.__args__
975975
other = union_params[0] if union_params[1] is NoneType else union_params[1]
976-
handler = self._unstructure_func.dispatch(other)
976+
977+
# TODO: Remove this special case when we make unstructuring Any consistent.
978+
if other is Any:
979+
handler = self.unstructure
980+
else:
981+
handler = self._unstructure_func.dispatch(other)
977982

978983
def unstructure_optional(val, _handler=handler):
979984
return None if val is None else _handler(val)

tests/test_optionals.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
from typing import NewType, Optional
1+
from typing import Any, NewType, Optional
22

33
import pytest
44
from attrs import define
55

6+
from cattrs import Converter
7+
68
from ._compat import is_py310_plus
79

810

@@ -39,3 +41,13 @@ class ModelWithFoo:
3941
"total_foo": "bar",
4042
"maybe_foo": "is it a bar?",
4143
}
44+
45+
46+
def test_optional_any(converter: Converter):
47+
"""Unstructuring Any|None is equivalent to unstructuring as v.__class__."""
48+
49+
@define
50+
class A:
51+
pass
52+
53+
assert converter.unstructure(A(), Optional[Any]) == {}

0 commit comments

Comments
 (0)