With a bit modification it can work, e.g. the last setattr(self, attr,
value) should explicitly invoke SignalBehavior().__set__() instead.

You're absolutely right. For whatever reason I was thinking .__set__ gets called first anyway (I am probably confusing this behavior with .__get__ and .__getattr__).

I believe that line should be:

SignalBehavior.__set__(getattr(type(self), attr), self, value)