#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# michael a.g. aïvázis
# orthologue
# (c) 1998-2009 all rights reserved
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Derived from pyre-1.0/packages/pyre/patterns/Observable.py
# See pyre-1.0 for full copyright and license information
__all__ = ["Observable"]
from diffpy.srfit.util.weakrefcallable import weak_ref
[docs]
class Observable(object):
"""Provide notification support for classes that maintain dynamic
associations with multiple clients.
Observers, i.e. clients of the observable, register event handlers
that will be invoked to notify them whenever something interesting
happens to the observable. The nature of what is being observed is
defined by Observable descendants and their managers. For example,
instances of pyre.calc.Node are observable by other nodes whose
value depends on them so that the dependents can be notified about
value changes and forced to recompute their own value.
The event handlers are callables that take the observable instance
as their single argument.
interface:
addObserver: registers its callable argument with the list of
handlers to invoke removeObserver: remove an event handler from
the list of handlers to invoke notify: invoke the registered
handlers in the order in which they were registered
"""
[docs]
def notify(self, other=()):
"""Notify all observers."""
# build a list before notification, just in case the observer's
# callback behavior involves removing itself from our callback set
semaphores = (self,) + other
for callable in tuple(self._observers):
callable(semaphores)
return
# callback management
[docs]
def addObserver(self, callable):
"""Add callable to the set of observers."""
f = weak_ref(callable, fallback=_fbRemoveObserver)
self._observers.add(f)
return
[docs]
def removeObserver(self, callable):
"""Remove callable from the set of observers."""
f = weak_ref(callable)
self._observers.remove(f)
return
[docs]
def hasObserver(self, callable):
"""True if `callable` is present in the set of observers."""
f = weak_ref(callable)
rv = f in self._observers
return rv
# meta methods
def __init__(self, **kwds):
super(Observable, self).__init__(**kwds)
self._observers = set()
return
# end of class Observable
# Local helpers --------------------------------------------------------------
def _fbRemoveObserver(fobs, semaphores):
# Remove WeakBoundMethod `fobs` from the observers of notifying object.
# This is called from Observable.notify when the WeakBoundMethod
# associated object dies.
observable = semaphores[0]
observable.removeObserver(fobs)
return
# end of file