Open bdanofsky opened 1 year ago
Are you sure it's necessary to run after and can't be just part of on_setattr
?
I think the answer is no but let me spell out my use case:
1) User sets a new attribute value (call this attrs attribute abc)
2) Publish is called when setattr is called on abc
a. stack is inspected to determine if abc depends on other attrs attributes
b. If abc depends on other attrs attributes then their relationship is stored as part of my publish/subscribe system.
example: abc = 8 * xyz # where xyz is another attrs attribute.
c. Lookup if another attrs attribute depends on abc if so then that attribute is updated.
example: qrs = abc / 128 # when abc updates then qrs updates with new value.
This is done doing exec('qrs = abc/128')
Note in step C there is an implied getattr() on abc which requires the new value
if Publish is called before abc actually has a new value then all the dependencies (in my example qrs) will be assigned based on the old value.
I was able to work around this issue by using a custom setattr .
FYI that workflow in attrs is a bit buggy or was when I implemented the code.
That said if you feel this feature is not something you wish to support I understand.
It seems like an obvious feature though.
I think the issue here is that on_setattr
doesn't provide any mechanism to do something after a new value is set, only to intercept a value before it is set. There are many things one might want to do immediately after setting a value including:
_dirty=True
.Instead of specific pub/sub support, would it make sense to add a post_setattr
hook? So the semantics would be
def set_dirty(obj, attribute, value):
obj._dirty=True
@define
class A:
x : int = field(default=0, post_setattr=set_dirty)
_dirty: bool = False
# Mostly equivalent to
x_attr = ...
psa_attrs = {'x': (x_attr, set_dirty)}
class A:
def __init__(x: int=0, dirty=False):
self.x = x
self._dirty=dirty
def __setattr__(self, name, val):
object.__setattr__(self, name, val)
try:
a, hook = psa_attrs[name]
except KeyError:
pass
else:
hook(self, a, val)
I'd be very happy with a post_setattr feature.
Attrs has nice support for validation and conversion. That same concept could/should be extended to post setattr() phase of attribute updates. This would allow for publish / subscribe systems on attribute updates.
In theory this should be a trivial feature enhancement to allow an additional hook.