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
2 changes: 2 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Our backwards-compatibility policy can be found [here](https://github.com/python
([#696](https://github.com/python-attrs/cattrs/pull/696))
- Use the optional `_value_` type hint to structure and unstructure enums if present.
([#699](https://github.com/python-attrs/cattrs/issues/699))
- Aliases (when in use) now properly generate rename metadata in generated hooks.
([#706](https://github.com/python-attrs/cattrs/issues/706) [#710](https://github.com/python-attrs/cattrs/pull/710))
- _cattrs_ now tracks performance using [codspeed](https://codspeed.io/python-attrs/cattrs).
([#703](https://github.com/python-attrs/cattrs/pull/703))
- The {mod}`tomlkit <cattrs.preconf.tomlkit>` preconf converter now properly handles native `date` objects when structuring.
Expand Down
10 changes: 9 additions & 1 deletion src/cattrs/gen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from collections.abc import Callable, Iterable, Mapping
from typing import TYPE_CHECKING, Any, Final, Literal, TypeVar

from attrs import NOTHING, Attribute, Converter, Factory
from attrs import NOTHING, Attribute, Converter, Factory, evolve
from typing_extensions import NoDefault

from .._compat import (
Expand Down Expand Up @@ -124,6 +124,8 @@ def make_dict_unstructure_fn_from_attrs(
continue
if override.rename is None:
kn = attr_name if not _cattrs_use_alias else a.alias
if kn != attr_name:
kwargs[attr_name] = evolve(override, rename=kn)
else:
kn = override.rename
d = a.default
Expand Down Expand Up @@ -435,6 +437,8 @@ def make_dict_structure_fn_from_attrs(
ian = a.alias
if override.rename is None:
kn = an if not _cattrs_use_alias else a.alias
if kn != an:
kwargs[an] = evolve(override, rename=kn)
else:
kn = override.rename

Expand Down Expand Up @@ -562,6 +566,8 @@ def make_dict_structure_fn_from_attrs(

if override.rename is None:
kn = an if not _cattrs_use_alias else a.alias
if kn != an:
kwargs[an] = evolve(override, rename=kn)
else:
kn = override.rename
allowed_fields.add(kn)
Expand Down Expand Up @@ -631,6 +637,8 @@ def make_dict_structure_fn_from_attrs(

if override.rename is None:
kn = an if not _cattrs_use_alias else a.alias
if kn != an:
kwargs[an] = evolve(override, rename=kn)
else:
kn = override.rename
allowed_fields.add(kn)
Expand Down
24 changes: 24 additions & 0 deletions tests/test_gen_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,30 @@ class A:
)


def test_alias_implicit_rename(converter: BaseConverter) -> None:
"""Attributes with aliases generate rename metadata."""

@define
class A:
a: int = field(alias="b")
c: int = field(alias="d", default=1)

u_fn = make_dict_unstructure_fn(A, converter, _cattrs_use_alias=True)
s_fn = make_dict_structure_fn(A, converter, _cattrs_use_alias=True)

assert u_fn.overrides["a"].rename == "b"
assert s_fn.overrides["a"].rename == "b"
assert u_fn.overrides["c"].rename == "d"
assert s_fn.overrides["c"].rename == "d"

converter.register_unstructure_hook(A, u_fn)
converter.register_structure_hook(A, s_fn)

assert converter.unstructure(A(1)) == {"b": 1, "d": 1}
assert converter.structure({"b": 1}, A) == A(1)
assert converter.structure({"b": 1, "d": 2}, A) == A(1, 2)


def test_init_false(converter: BaseConverter) -> None:
"""By default init=False keys are ignored."""

Expand Down
Loading