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

When structuring, how to forbid type casting to base classes? #469

Open
philip-bl opened this issue Dec 12, 2023 · 2 comments
Open

When structuring, how to forbid type casting to base classes? #469

philip-bl opened this issue Dec 12, 2023 · 2 comments
Milestone

Comments

@philip-bl
Copy link

I want to use cattrs to structure dicts and other stuff to attrs. However, I am unhappy with the default behaviour that if attrs expects an int, float, str, bool or something like that, it casts the object to that type using int(), float(), str(), or bool() respectively. I want cattrs to structure containers such as sequences, dicts, etc. but I don't want it to typecast base types - I want it to error out instead if the types don't match. How can I do this?

@Tinche
Copy link
Member

Tinche commented Dec 12, 2023

Hello!

You can override the default hooks for those types to be anything you like. Cattrs is based on function composition to this is how problems are usually solved.

A simple solution would be like this:

from cattrs import Converter

c = Converter()


def structure_int(val, _) -> int:
    if not isinstance(val, int):
        raise ValueError("Not an int")
    return val


c.register_structure_hook(int, structure_int)

c.structure("1", int)  # Error

You can get fancier by making use of the fact structure hooks receive their target type as their second argument, like this:

c = Converter()


def validate_type(val, type):
    if not isinstance(val, type):
        raise ValueError(f"Not a {type}")
    return val


c.register_structure_hook(int, validate_type)
c.register_structure_hook(float, validate_type)
c.register_structure_hook(str, validate_type)
c.register_structure_hook(bool, validate_type)

c.structure("1", bool)

These rules propagate to collections, attrs classes etc.

@Tinche
Copy link
Member

Tinche commented Dec 12, 2023

I'm planning a strategy to make this easier, probably in the next version.

@Tinche Tinche added this to the 24.1 milestone Dec 12, 2023
@Tinche Tinche modified the milestones: 24.1, 24.2 Jun 20, 2024
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