Skip to content

Register structure hook only for optional types #529

Closed
@ljnsn

Description

@ljnsn
  • cattrs version: 23.2.3
  • Python version: 3.11
  • Operating System: Linux

Description

I'd like to register a structure hook only for optional types. I've search both existing issues and the docs, but please let me know if I missed this somehow.

What I Did

Suppose I receive some data where values can be "" and I want to convert them to None. I only want to convert the fields that are annotated as optional on my model though, fields that are not annotated as optional should raise a validation error.

from typing import Any, Optional

import attrs
import cattrs

converter = cattrs.Converter()


@attrs.define()
class Foo:
    bar: int | None
    baz: int


def _int_or_none(value: Any, _type: type[Any]) -> int | None:
    return None if value == "" else int(value)

I've tried both these, but it seems like they aren't registered at all:

converter.register_structure_hook(Optional[int], _int_or_none)
converter.register_structure_hook(int | None, _int_or_none)

d = {"bar": "", "baz": "2"}
converter.structure(d, Foo)  # with either of the above, tries to convert "" to int

This works, but it also converts non-optional fields to None:

converter.register_structure_hook(int, _int_or_none)
d = {"bar": "", "baz": ""}
converter.structure(d, Foo)  # Foo(bar=None, baz=None)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions