Skip to content

Extending current hook #632

Description

@AdrianSosic

Hi @Tinche,

Probably I just can't see the wood for the trees, but I'm somehow stuck getting this simple scenario to work. Can you give a quick hint what is:

  • generally the "right" way to extend an existing hook? That is, what is the best way to define some hook logic that internally uses the old logic without running into recursion errors? I mean, I know I can use things like make_dict_unstructure_fn but quick question on this one: does it use already registered hooks? I guess the answer is "yes", because we explicitly pass a converter object, right? So it would use the hooks of that converter, whatever they are?
  • Assuming the above is true, I still don't know how to get it running for non-attrs classes, and specifically, protocols, for which I can't even do an isinstance check that would enable me to use hook factories. Below the example:
from typing import Protocol

import cattrs
from attrs import define

converter = cattrs.Converter()


class SomeGetter(Protocol):
    """A index-based mapping from strings to surrogates."""

    def __getitem__(self, key: str) -> int: ...


@define
class Container:
    getter: SomeGetter


# None of the following works, expectedly, because of endless recursion loops / non-attrs

@converter.register_unstructure_hook
def unstructure_getter(obj: SomeGetter) -> dict:
    return {"type": type(obj), **converter.unstructure(obj)}


@converter.register_unstructure_hook
def unstructure_getter(obj: SomeGetter) -> dict:
    fn = converter.get_unstructure_hook(SomeGetter)
    return {"type": type(obj), **fn(obj)}


@converter.register_unstructure_hook
def unstructure_getter(obj: SomeGetter) -> dict:
    from cattrs.gen import make_dict_unstructure_fn

    fn = make_dict_unstructure_fn(SomeGetter, converter)
    return {"type": type(obj), **fn(obj)}


container = Container({"a": 1})
dct = converter.unstructure(container)
print(dct)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    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