0

I want to use attrs to run validators on values inside my class. Here is an example:

from attrs import define, field

@define(kw_only=True)
class Foo:
    x: float = field()
    min_x: float = field()
    max_x: float = field()

    @x.validator
    def validate_x(self, _, value) -> None:
        if value < self.min_x:
            raise ValueError(f"x must be greater than {self.min_x}")
        if value > self.max_x:
            raise ValueError(f"x must be less than {self.max_x}")

    @min_x.validator
    def validate_min_x(self, _, value) -> None:
        if value > self.max_x:
            raise ValueError("Min x must be less than max x")

    @max_x.validator
    def validate_max_x(self, _, value) -> None:
        if value < self.min_x:
            raise ValueError("Max x must be greater than min x")

All three values x, min_x and max_x are important to me and need to be stored. As I want to be able to get all three values and change them when needed. The problem I have is how these three validator functions can work together.

For basic usage, like creating a new instance, it works fine.

foo = Foo(x=5, min_x=0, max_x=10)

But say I wanted to change the values. I might want to do it like this:

foo.min_x = 11
foo.max_x = 15
foo.x = 12

But foo.min_x will throw an error because it will compare to max_x = 10. Yes, if I swap the order and set foo.max_x first it will solve it. But next time I might want to make foo.max_x smaller than foo.min_x so I need a robust way to handle all cases.

Is there a good way to handle this kind of situation?

0

Browse other questions tagged or ask your own question.