Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

`make_unstructure_dict_unstructure_fn` does not honor `use_class_methods`

Aperta
#566 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
35/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Ferma
Stack tecnologico
python
Ambito
backend

Direzione di ricerca

Reproduce the two tagging examples and inspect make_dict_unstructure_fn, make_unstructure_dict_unstructure_fn, and use_class_methods to trace hook dispatch and recursion. Done means the tagging hook preserves its _type field while nested values still use the configured metamethods, without infinite recursion.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

From comments in #558. Custom metamethods and make_unstructure_dict_unstructure_fn cannot be used together:

import cattrs
from cattrs.strategies import use_class_methods
import attrs

# Use a set of metamethods
@attrs.define
class Thing:
    a: int

    def _unstructure(self):
        return {"a" : str(self.a)}

    @classmethod
    def _structure(cls, val):
        return cls(a=int(val["a"]))

conv = cattrs.Converter()
use_class_methods(
    conv,
    "_structure",
    "_unstructure",
)

assert conv.unstructure(Thing(1)) == {
    "a" : "1",
}


def tag_attrs_hook_factory(cl):

    base_hook = cattrs.gen.make_dict_unstructure_fn(cl, conv)

    def hook(instance):

        unstruct = base_hook(instance)
        unstruct["_type"] = type(instance).__name__

        return unstruct
    return hook


tagging_conv_a = cattrs.Converter()
tagging_conv_a.register_unstructure_hook_factory(attrs.has, tag_attrs_hook_factory)
use_class_methods(
    tagging_conv_a,
    "_structure",
    "_unstructure",
)

# THIS IS WRONG. Does not have the tag
assert tagging_conv_a.unstructure(Thing(1)) == {
    "a" : "1",
}

tagging_conv_b = cattrs.Converter()
use_class_methods(
    tagging_conv_b,
    "_structure",
    "_unstructure",
)
tagging_conv_b.register_unstructure_hook_factory(attrs.has, tag_attrs_hook_factory)

# THIS IS WRONG. Does not convert the sub value correctly via the metamethod
assert tagging_conv_b.unstructure(Thing(1)) == {
    "_type" : "Thing",
    "a" : 1,
}

What I tried initially was to just inject the converter so it dispatches to the metamethods properly. But this causes infinite recursion, e.g.:

def tag_attrs_hook_factory(cl):

    converter = ... # via closure

    def hook(instance, converter):

        unstruct = converter.unstructure(instance)
        unstruct["_type"] = type(instance).__name__

        return unstruct
    return hook

I think that make_dict_unstructure_fn and friends should honor the metamethods for the passed in converter and break recursion. I'm not sure if this makes sense though... In any case this is a difficult case to handle generally.

Lingua principale
Python
Stelle
1.1k
Fork
159
Merge medio
12h 21m
PR unite (30g)
6

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di python-attrs/cattrs

Tutte le issue di python-attrs/cattrs

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.