Skip to content

Commit

Permalink
Simplify code as cattrs depends on modern attrs
Browse files Browse the repository at this point in the history
This modern version of `attrs` provides the `alias` attribute on
fields that contains the name we should use here.

Also add a test to verify that structuring and unstructuring aliased
attributes (which can be triggered by prefixing an attribute with an
underscore) works as expected.
  • Loading branch information
jap committed Sep 1, 2023
1 parent acd3d10 commit dc48705
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 6 deletions.
2 changes: 2 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
([#408](https://github.com/python-attrs/cattrs/pull/408))
- Fix structuring `Final` lists.
([#412](https://github.com/python-attrs/cattrs/issues/412))
- Remove some unused lines in the unstructuring code.
([#416](https://github.com/python-attrs/cattrs/pull/416))


## 23.1.2 (2023-06-02)
Expand Down
8 changes: 2 additions & 6 deletions src/cattrs/converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -511,16 +511,12 @@ def structure_attrs_fromdict(self, obj: Mapping[str, Any], cl: Type[T]) -> T:

conv_obj = {} # Start with a fresh dict, to ignore extra keys.
for a in fields(cl):
name = a.name

try:
val = obj[name]
val = obj[a.name]
except KeyError:
continue

if name[0] == "_":
name = name[1:]

# try .alias and .name because this code also supports dataclasses!
conv_obj[getattr(a, "alias", a.name)] = self._structure_attribute(a, val)

return cl(**conv_obj)
Expand Down
17 changes: 17 additions & 0 deletions tests/test_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,23 @@ class C:
assert inst == converter.structure(unstructured, C)


def test_dict_roundtrip_with_alias():
"""
A class with an aliased attribute can be unstructured and structured.
"""

converter = Converter()

@define
class C:
_a: int

inst = C(a=0)
unstructured = converter.unstructure(inst)
assert unstructured == {"_a": 0}
assert converter.structure(unstructured, C) == inst


@given(simple_typed_classes(defaults=True))
def test_type_overrides(cl_and_vals):
"""
Expand Down

0 comments on commit dc48705

Please sign in to comment.