[Python-Dev] Generic notifier module
Ka-Ping Yee
ping@lfw.org
Wed, 19 Apr 2000 10:25:12 -0700 (PDT)
On Wed, 19 Apr 2000, Ka-Ping Yee wrote:
> object.send(message, **args) - Call all callbacks registered on
> object for message, in reverse order of registration, passing
> along message and **args as arguments to each callback.
One revision to the above: callbacks should get the sender of the
message passed in as well as the message. The tweaked module follows.
-------- snip snip ---------------------------------- notifier.py --------
# If a callback returns BREAK, no more callbacks are called.
BREAK = "break"
# This number goes up every time a callback is added.
serial = 0
# This dictionary maps callback functions to serial numbers.
callbacks = {}
def recipients(sender, message):
"""Return a list of (serial, callback) pairs for all the callbacks
on this message and its base classes."""
key = (sender, message)
if callbacks.has_key(key):
list = map(lambda (k, v): (v, k), callbacks[key].items())
else:
list = []
if hasattr(message, "__bases__"):
for base in message.__bases__:
list.extend(recipients(sender, base))
return list
class Notifier:
"""Mix in this class to provide notifier functionality on your objects.
On a notifier object, use the 'notify' and 'denotify' methods to register
or unregister callbacks on messages, and use the 'send' method to send a
message from the object."""
def send(self, message, **args):
"""Call any callbacks registered on this object for the given message.
If message is a class or instance, callbacks registered on the class
or any base class are called. Otherwise callbacks registered on a
message of the same value (compared by hash) are called. The message
and any extra keyword arguments are passed along to each callback."""
if hasattr(message, "__class__"):
message = message.__class__
recip = recipients(self, message)
recip.sort()
recip.reverse()
for serial, callback in recip:
if callback(self, message, **args) == BREAK: return
def notify(self, message, callback):
"""Register a callback on this object for a given message. The
message should be a class (not an instance) or a hashable object."""
key = (self, message)
if not callbacks.has_key(key):
callbacks[key] = {}
callbacks[key][callback] = serial
def denotify(self, message, callback=None):
"""Unregister a particular callback or all existing callbacks on
this object for a given message. The message should be a class
(not an instance) or a hashable object."""
key = (self, message)
if callbacks.has_key(key):
if callback is None:
del callbacks[key]
elif callbacks[key].has_key(callback):
del callbacks[key][callback]
-------- snip snip ---------------------------------- notifier.py --------
-- ?!ng
"Je n'aime pas les stupides garçons, même quand ils sont intelligents."
-- Roople Unia