I have been trying to implement a reactive change notification system on top of attrs using on_setattr handlers. However, on_setattr handlers are called before the value is assigned, in order to allow them to perform data conversion. For a reactive change notification, this is subobtimal: you want the changes to be notified after value assignment, so that handlers can inspect the new state on the object. This is especially important when change handlers chain, e.g. when a change handler on an attribute a potentially triggers a change in b, and a change handler on b may want to inspect a, which would otherwise be inconsistent.
Implementing that using the existing mechanisms in attrs proved quite difficult; you'd need a custom __setattr__. However, that immediately prevents any on_setattr behaviour (such as frozen attributes), which requires an attrs-built __setattr__. Thus, one would have to collect all on_setattr specifications on all fields and replace them with custom metadata, which can then be collected into the handling of the custom __setattr__. Obviously, that is suboptimal.
I therefore propose to add another handler on_change, which behaves similar to on_setattr, but is invoked after the value is assigned to the instance. Preferably, in addition to the values provided to on_setattr handlers, we would also supply the previous value (without making any guarantees for concurrent multi-threaded access).
If there is interest in this, I'm happy to whip up a PR.
I have been trying to implement a reactive change notification system on top of
attrsusingon_setattrhandlers. However,on_setattrhandlers are called before the value is assigned, in order to allow them to perform data conversion. For a reactive change notification, this is subobtimal: you want the changes to be notified after value assignment, so that handlers can inspect the new state on the object. This is especially important when change handlers chain, e.g. when a change handler on an attributeapotentially triggers a change inb, and a change handler onbmay want to inspecta, which would otherwise be inconsistent.Implementing that using the existing mechanisms in
attrsproved quite difficult; you'd need a custom__setattr__. However, that immediately prevents anyon_setattrbehaviour (such as frozen attributes), which requires anattrs-built__setattr__. Thus, one would have to collect allon_setattrspecifications on all fields and replace them with custom metadata, which can then be collected into the handling of the custom__setattr__. Obviously, that is suboptimal.I therefore propose to add another handler
on_change, which behaves similar toon_setattr, but is invoked after the value is assigned to the instance. Preferably, in addition to the values provided toon_setattrhandlers, we would also supply the previous value (without making any guarantees for concurrent multi-threaded access).If there is interest in this, I'm happy to whip up a PR.