Open
Description
This may be by design, but I was hopeful it would work. When an attribute is set during init, on_setattr
does not seem to apply, but it does after instantiation. What's the best way to hook in so I can add a validator to all Attributes? Looking to essentially create a class that enforces all values are set to valid types, without adding the same validator to each attribute when I can have some classes with dozens of attributes.
import attr
def raise_value_error(instance, attribute, value):
raise ValueError
@attr.define(on_setattr=raise_value_error)
class Test:
a: int
test = Test("a string") # fine
test.a = "another string" # fails
Activity
hynek commentedon Aug 21, 2020
Yes that’s on purpose. Your use-case is a bit specific but there has been calls for whole-class validators lately.
wsanchez commentedon Aug 26, 2020
For what it's worth, I think I'd find that a bit surprising also if I were coming in new.
A single validator (for either the class, or for individual attributes) that gets call at the end of initialization and after every attribute change would seem an obvious design to me; not doing the same in both cases seems inconsistent, though perhaps a reasonable exception.
hynek commentedon Aug 30, 2020
I agree that the thought process around it is a tad convoluted by its history and we probably should do a better job at explaining why things work as they do in the docs.
However I feel like the naming makes it IMHO quite unequivocal once you grok the way it works.
Also please note that OP didn’t use validators really. They just wanted something to happen on every
__setattr__
which is technically impossible to implement well (cf freezing etc).