Skip to content

Reusing existing hooks #657

Description

@AdrianSosic

Hi @Tinche,

I already feel that the answer to my question is again going to be related to singledispatch vs predicates or similar 😄 but nevertheless I'm a bit lost at the moment. Would appreciate if you enlighten me once again 🤓:

In #632, we've clarified that machinery like make_dict_unstructure_fn reach into the passed converter and get already existing hooks for all the fields. But then why do I get the following behavior?

import cattrs
from attrs import define

converter = cattrs.Converter()


@define
class Pair:
    x: float
    y: float


@define(init=False)
class ContainerInner:
    pair: Pair

    def __init__(self, x: float, y: float):
        self.pair = Pair(x, y)


@define
class ContainerOuter:
    inner: ContainerInner


@cattrs.register_unstructure_hook
def _unstructure_container(container: ContainerInner) -> dict:
    return {"x": container.pair.x, "y": container.pair.y}


@cattrs.register_unstructure_hook
def _unstructure_container_outer(container: ContainerOuter) -> dict:
    fn = cattrs.gen.make_dict_unstructure_fn(ContainerOuter, converter)
    return fn(container)


container = ContainerOuter(ContainerInner(1.0, 2.0))
print(container)
dct = cattrs.unstructure(container)
print(dct)

This gives:

{'inner': {'pair': {'x': 1.0, 'y': 2.0}}}

meaning that the hook for ContainerInner is not used when assembling the hook for ConverterOuter using make_dict_unstructure_fn.

Can you tell me what's going on / where's the flaw in my reasoning?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions