1 # Copyright (c) 2008 David Aguilar
2 """This module provides the Observable class"""
6 class Observable(object):
7 """Handles subject/observer notifications."""
10 self
.message_observers
= {}
11 self
.notification_enabled
= True
12 self
.register_messages()
14 def register_messages(self
, messages
=None):
16 Automatically register all class-scope message names.
18 There are two rules at play here:
20 1. Message names must be defined at class scope. e.g.:
25 2. Message name variables must begin with the string 'message_'
27 Providing a 'messages' dict avoids this built-in behavior but
28 does not guarantee that the messages names are registered for
29 clones or unserialized objects.
33 self
.message_observers
.update(messages
)
35 for k
, v
in self
.__class
__.__dict
__.iteritems():
36 if k
.startswith('message_') and type(v
) in types
.StringTypes
:
37 self
.message_observers
[v
] = set()
39 def add_observer(self
, observer
):
40 """Adds an observer to this model"""
41 self
.observers
.add(observer
)
43 def add_message_observer(self
, message
, observer
):
44 """Add an observer for a specific message."""
45 observers
= self
.message_observers
.setdefault(message
, set())
46 observers
.add(observer
)
48 def remove_observer(self
, observer
):
49 """Removes an observer"""
50 if observer
in self
.observers
:
51 self
.observers
.remove(observer
)
52 for message
, observers
in self
.message_observers
.items():
53 if observer
in observers
:
54 observers
.remove(observer
)
56 def notify_observers(self
, *param
):
57 """Notifies observers about attribute changes"""
58 if not self
.notification_enabled
:
60 for observer
in self
.observers
:
61 observer
.notify(*param
)
63 def notify_message_observers(self
, message
, **opts
):
64 """Notifies message observers."""
65 if not self
.notification_enabled
:
67 if message
not in self
.message_observers
:
68 raise ValueError('%s is not a valid message name.' % message
)
69 observers
= self
.message_observers
[message
]
70 for method
in observers
:
71 method(self
, message
, **opts
)