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

Getting the next structure hook

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

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
25/100
Tipo di issue
Funzionalità
Chiarezza
Da chiarire
Stato di attività
Attiva
Stack tecnologico
python
Ambito
data

Direzione di ricerca

The issue asks how to chain a pre-normalization step in front of structure hooks, and it mentions get_structure_hook, make_dict_structure_fn, register_structure_hook_factory and use_class_methods. Read how those hooks are resolved and why a generic like list[Foo] raises StructureHandlerNotFoundError, and check the linked attrs issue for the attrib.type string behaviour. Done would be a maintainer-agreed design for field converters running before structuring, with tests for the ensure_list case.

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

Descrizione

I am trying to wrap and combine attrs.Converter and the structure hook to have a pre-normalization step before the structure logic kicks in. There are 2 issues I hit

Pre-normalizing the class

Here the issue is that I cannot get the original (or next preferred) structure, roughly can simulate it with

use_class_methods(raw_converter, "from_raw", "to_raw")

@define
class Foo:
    a: str
    b: int = 1

    @classmethod
    def from_raw(cls, data, converter):
        if isinstance(data, str):
            data = {"a": data}
        if not isinstance(data, dict):
            raise TypeEroor("Unsupported")
        original_structure = structure.get_structure_hook(cls)
        return original_structure(data, cls)

The recursion here is rather obvious, but there is no way to get n layers further down in the preference to get the next structure hook. Even if it was to be hard-coded or only go one layer further would probably work for most cases.

Pre-normalizing the fields

This is most likely a PEBKAC, but I get StructureHandlerNotFoundError when trying to get the structure hook of a generic. Basically the end goal is to have

@define
class Foo:
    a: str

def ensure_list(data):
    if not isinstance(data, list):
        data = [data]
    return data

@define
class Bar:
    foo: list[Foo] = field(converter=ensure_list)

@raw_converter.register_structure_hook_factory(has)
def structure_attrs_with_converter(cls, converter):
    cls_structure = cattrs.gen.make_dict_structure_fn(
        cls,
        converter,
        **{
            attrib.name: override(struct_hook=attr_structure)
            for attrib in attrs.fields(cls)
            if (
                attr_structure := structure_field_with_converter(
                    attrib=attrib,
                    converter=converter,
                )
            )
        },
    )
    return cls_structure

def structure_field_with_converter(attrib, converter):
    if not attrib.converter:
        return None
    original_structure = converter.get_structure_hook(attrib.type)

    def structure(raw_value, _type):
        value = attrib.converter(raw_value, None, attrib)
        return original_structure(value, _type)

    return structure

core of the issue here is that attrib.type given here is a str, not even a ForwardRef that I could later evaluate 🤔
Edit: Aha, it's an attrs bug https://github.com/python-attrs/attrs/issues/1596

Also I have tried to get attrs.Converter and cattrs to work nicely together, but so far this is the only way I found feasible. The issue is that the attrs.Converter must run before the main structure of the class, otherwise it will try to structure each element in the foo key before making sure it is a list in this example. If there are other ways to design this, that would be welcome, since this can get a bit messy.


This might be related to https://github.com/python-attrs/cattrs/issues/659?

Lingua principale
Python
Stelle
1.1k
Fork
171
Merge medio
14h 46m
PR unite (30g)
5

Preparare l'ambiente

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.