Properties#

Property objects can be defined on subclasses of Dispatcher to create instance attributes that emit events when their values change. Binding and unbinding works exactly the same as with events. The callback signature is slightly different however. The first two arguments will be:

  1. The instance object that generated the event

  2. The Property value

Usage#

>>> from pydispatch import Dispatcher, Property

>>> class MyEmitter(Dispatcher):
...     name = Property()
...     value = Property()

>>> class MyListener(object):
...     def on_name(self, instance, value, **kwargs):
...         print('emitter name is {}'.format(value))
...     def on_value(self, instance, value, **kwargs):
...         print('emitter value is {}'.format(value))

>>> emitter = MyEmitter()
>>> listener = MyListener()

>>> # Bind to the "name" and "value" properties of emitter
>>> emitter.bind(name=listener.on_name, value=listener.on_value)

>>> # Set emitter.name property (triggering the on_name callback)
>>> emitter.name = 'foo'
emitter name is foo

>>> # Set emitter.value (triggering the on_value callback)
>>> emitter.value = 42
emitter value is 42

>>> # If the property value assigned equals the current value,
>>> # the event isn't triggered.
>>> emitter.value = 42

>>> emitter.value = 43
emitter value is 43

Container Properties#

dict and list objects are implemented as subclasses of Property:

They will emit events when their contents change. Nesting is also supported, so even the contents of a list or dict anywhere inside of the structure can trigger an event.

>>> from pydispatch import Dispatcher, ListProperty, DictProperty

>>> class MyEmitter(Dispatcher):
...     values = ListProperty()
...     data = DictProperty()

>>> class MyListener(object):
...     def on_values(self, instance, value, **kwargs):
...         print('emitter.values = {}'.format(value))
...     def on_data(self, instance, value, **kwargs):
...         print('emitter.data = {}'.format(value))

>>> emitter = MyEmitter()
>>> listener = MyListener()

>>> # Bind to the "values" (list) and "data" (dict) properties of emitter
>>> emitter.bind(values=listener.on_values, data=listener.on_data)

>>> emitter.values.append('foo')
emitter.values = ['foo']

>>> emitter.values.extend(['bar', 'baz'])
emitter.values = ['foo', 'bar', 'baz']

>>> # The property can be assigned directly
>>> emitter.data = {'foo':'bar'}
emitter.data = {'foo': 'bar'}

>>> # or using item assignment
>>> emitter.data['foo'] = 'baz'
emitter.data = {'foo': 'baz'}

>>> # also through the update() method
>>> emitter.data.update({'spam':'eggs'})
emitter.data = {'foo': 'baz', 'spam': 'eggs'}

>>> emitter.data.clear()
emitter.data = {}

>>> # Create a nested dict
>>> emitter.data['fruit'] = {'apple':'red'}
emitter.data = {'fruit': {'apple': 'red'}}

>>> # changes to the inner dict are propagated and dispatched
>>> emitter.data['fruit']['banana'] = 'yellow'
emitter.data = {'fruit': {'apple': 'red', 'banana': 'yellow'}}