Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type validation on unstructure #433

Open
danielnelson opened this issue Oct 18, 2023 · 1 comment
Open

Type validation on unstructure #433

danielnelson opened this issue Oct 18, 2023 · 1 comment

Comments

@danielnelson
Copy link

  • cattrs version: 23.1.2
  • Python version: 3.11.5
  • Operating System: gentoo

Description

I want users of my library to fill out an attrs class, then later I will unstructure it and send it out to a remote API. When the user creates the attrs instance, they can optionally use mypy to make sure they set the attributes to the correct types, but of course this is optional. Before I send out the data on the network I would like to be sure it matches the correct schema.

I know I could use attrs validators to enforce types in the attrs class, but I've found that its hard to do correctly for more advanced types. Before I send out the data on the network I would like to be sure it matches the correct schema.

However, it appears that cattrs doesn't check types in unstructure the same way structure does. Is there a way to make cattrs unstructure strictly, or perhaps the recommendation is to add separate validation after unstructuring?

What I Did

import attrs
import cattrs


@attrs.define
class Foo:
    x: int = 42


f = Foo("wrong type")
print(cattrs.unstructure(f))

Actual output:

{'x': 'wrong type'}

Expected output: Exception

@Tinche
Copy link
Member

Tinche commented Oct 19, 2023

Howdy,

I don't have any immediate plans for this, but you can try something like the following:

import attrs

import cattrs

c = cattrs.Converter()


def validate_int(i):
    if not isinstance(i, int):
        raise TypeError()
    return i


c.register_unstructure_hook(int, validate_int)


@attrs.define
class Foo:
    x: int = 42


f = Foo("wrong type")
print(c.unstructure(f))

And put in some additional hooks for strings and other primitives. A comprehensive solution would probably involve writing a strategy, which I'd be glad to mentor someone to do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants