Skip to content

forbid_extra_keys or hooks get loss with Converter.copy() #410

@philpep

Description

@philpep
  • cattrs version: 23.1.2
  • Python version: 3.11
  • Operating System: Debian bookworm

Description

Hi, I noticed some issues with Converter.copy() where in some case forbid_extra_keys or hooks get loss.

What I Did

Here's some code reproducing the issue:

from typing import Any

import attrs
import cattrs


@attrs.frozen
class M:
    some_attr: int


base = cattrs.Converter(forbid_extra_keys=True)
camel = base.copy()


def to_camel(string: str) -> str:
    parts = string.split("_")
    return parts[0] + "".join(word.capitalize() for word in parts[1:])


def camel_structure(cls: Any) -> Any:
    return cattrs.gen.make_dict_structure_fn(
        cls,
        camel,
        **{
            a.name: cattrs.gen.override(rename=to_camel(a.name))
            for a in attrs.fields(cls)
        },
    )


camel.register_structure_hook_factory(attrs.has, camel_structure)

print(camel.structure({"someAttr": 42}, M))
# OK: M(some_attr=42)

print(camel.structure({"someAttr": 42, "extra": "forbid"}, M))
# NOK: M(some_attr=42)
# should fail with cattrs.errors.ForbiddenExtraKeysError
# looks this can be workaround by adding _cattrs_forbid_extra_keys=True to make_dict_structure_fn()

camel2 = camel.copy()
print(camel2.structure({"someAttr": 42}, M))
# NOK cattrs.errors.ForbiddenExtraKeysError: Extra fields in constructor for M: someAttr
# should sucess and return M(some_attr=42)
# BUT seems ok with cattrs current master branch

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions