jangada.serialization.SerializableProperty.add_observer#

SerializableProperty.add_observer(func: Callable[[object, T, T], None]) Self#

Add an observer function using decorator syntax.

Observers are called after the property value changes. They receive the instance, old value, and new value as arguments.

Parameters:
funcObserver

Function to observe changes. Should accept three arguments (instance, old_value, new_value) and return None.

Returns:
Self

A new SerializableProperty instance with the observer added.

Notes

This method creates a new descriptor instance with the observer added to the set of observers.

Observers are called: - After the value has been parsed and stored - Before the post-initializer runs (if applicable) - In arbitrary order if multiple observers exist

On first access, observers receive old_value=None and new_value=default.

If an observer raises an exception, it propagates to the caller and subsequent observers are not called.

Examples

Track changes:

>>> class Tracked:
...     value = SerializableProperty(default=0)
...
...     @value.add_observer
...     def value(self, old, new):
...         print(f"Value changed: {old} -> {new}")
...
>>> obj = Tracked()
>>> obj.value = 10
Value changed: 0 -> 10
>>> obj.value = 20
Value changed: 10 -> 20

Update dependent properties:

>>> class Rectangle:
...     width = SerializableProperty(default=1.0)
...     height = SerializableProperty(default=1.0)
...     area = SerializableProperty(default=1.0)
...
...     @width.add_observer
...     def width(self, old, new):
...         self.area = self.width * self.height
...
...     @height.add_observer
...     def height(self, old, new):
...         self.area = self.width * self.height
...
>>> rect = Rectangle()
>>> rect.width = 5
>>> rect.height = 3
>>> rect.area
15.0

Multiple observers:

>>> class MultiObserved:
...     value = SerializableProperty()
...
...     @value.add_observer
...     def value(self, old, new):
...         print(f"Observer 1: {old} -> {new}")
...
>>> # Can chain add_observer calls
>>> MultiObserved.value = MultiObserved.value.add_observer(
...     lambda self, old, new: print(f"Observer 2: {old} -> {new}")
... )