[Modeling-cvs] NotificationFramework CHANGES,1.10,1.11 Notification.py,1.6,1.7 NotificationCenter.py
Status: Abandoned
Brought to you by:
sbigaret
From: <sbi...@us...> - 2004-02-15 14:11:26
|
Update of /cvsroot/modeling/NotificationFramework In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4053 Modified Files: CHANGES Notification.py NotificationCenter.py __init__.py log.py mems_lib.py Log Message: All docstrings updated for epydoc + reStructuredText Index: CHANGES =================================================================== RCS file: /cvsroot/modeling/NotificationFramework/CHANGES,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** CHANGES 14 Feb 2004 19:44:11 -0000 1.10 --- CHANGES 15 Feb 2004 14:03:56 -0000 1.11 *************** *** 1,3 **** --- 1,5 ---- + - All docstrings updated for epydoc + reStructuredText + - Added attribute __version__ to package NotificationFramework Index: Notification.py =================================================================== RCS file: /cvsroot/modeling/NotificationFramework/Notification.py,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** Notification.py 14 Feb 2004 19:44:11 -0000 1.6 --- Notification.py 15 Feb 2004 14:03:56 -0000 1.7 *************** *** 23,28 **** #----------------------------------------------------------------------------- ! """ ! Notifications are the messages transmitted by the NotificationCenter. $Id$ --- 23,28 ---- #----------------------------------------------------------------------------- ! """A `Notification` object is a message transmitted by the ! `NotificationCenter`. $Id$ *************** *** 34,43 **** """ Notification objects are generally encountered when supplied by the ! NotificationCenter to its listener's callback method. ! A Notification object is designed as an immutable object. ! You should not need to directly instanciate Notification objects: rather, ! use NotificationCenter methods to add or remove observers and to post notifications. """ --- 34,43 ---- """ Notification objects are generally encountered when supplied by the ! `NotificationCenter` to its listener's callback method. ! A `Notification` object is designed as an immutable object. ! You should not need to directly instanciate `Notification` objects: rather, ! use `NotificationCenter` methods to add or remove observers and to post notifications. """ *************** *** 45,49 **** """ This is the Notification initializer -- you should not directly instanciate ! a Notification object: rather, use NoticationCenter methods to add observers or to post notifications """ --- 45,49 ---- """ This is the Notification initializer -- you should not directly instanciate ! a `Notification` object: rather, use `NotificationCenter` methods to add observers or to post notifications """ *************** *** 84,88 **** def __setattr__(self, name, value): ! "Raises TypeError since this is an immutable object" raise TypeError, 'object has read-only attributes' --- 84,88 ---- def __setattr__(self, name, value): ! "Raises ``TypeError`` since this is an immutable object" raise TypeError, 'object has read-only attributes' Index: NotificationCenter.py =================================================================== RCS file: /cvsroot/modeling/NotificationFramework/NotificationCenter.py,v retrieving revision 1.10 retrieving revision 1.11 diff -C2 -d -r1.10 -r1.11 *** NotificationCenter.py 14 Feb 2004 19:44:11 -0000 1.10 --- NotificationCenter.py 15 Feb 2004 14:03:56 -0000 1.11 *************** *** 24,30 **** ! """ ! NotificationCenter is the central object of the framework --full documentation ! is here. This module acts as a NotificationCenter. --- 24,29 ---- ! """NotificationCenter is the central object of the framework --full ! documentation is here. This module acts as a NotificationCenter. *************** *** 35,166 **** notification are automatically notified. ! Listeners and callbacks ! ! First at all, the Notification Center needs to have a mean to notify ! objects that a notification they are listening to was posted. To achieve ! this, objects should supply their reference, as well as a callback method ! at registration time (Note: by default only one callback is accepted per ! object; see discussion below). ! ! The possible listeners are: class instances ('types.InstanceType'), code ! objects or functions (such as functions defined in a module). See method ! 'addObserver' for full details ; we will focus in the following on class ! instances. ! ! For listeners being class instances, callbacks' signature should minimally ! be one of these:: ! ! def callback(self, notification) ! def callback(self, *arg) ! ! Hence, any of the following signatures are okay: ! ! def callback(self, notification, param1='param1') ! def callback(self, notification, *arg) ! def callback(self, notification, **kw) ! etc. ! ! Please note that the callback method must be supplied as a unbound ! method, e.g.: 'ObjectClass.callback'. ! ! When called by the NotificationCenter upon notification post, callback's ! parameter 'notification' is a Notification instance. ! ! Registration: Generic- and Specific- listeners ! ! Object can register as "generic observers" or "specific observers". ! ! Generic observers listens all notifications coming with a given ! name. They register themselves with:: ! ! NotificationCenter.addObserver(object, ObjectClass.method, 'NewMessage') ! Generic observers will be notified each time a notification with that name ! is posted, whatever the accompaying object can be (including None). ! ! Specific observers only listens notifications which have a given name ! *and* a given value. They register themselves with:: ! NotificationCenter.addObserver(object, ObjectClass.method, ! 'NewMessage', 'email') ! NotificationCenter.addObserver(object, ObjectClass.method, ! 'NewMessage', 'news') ! etc. ! Specific observers are only notified when a notification with these name ! and object is posted. ! Registering more than one callback per object ! By default, addObserver() checks that only one callback is registered per ! object; if you try to register a different one, you'll get a ValueError. ! Of course, a single object can listen to multiple notifications. In that ! case, you'll probably register a given method, say, handleNotification(), ! dedicated to this task:: ! def handleNotification(self, notification): ! notification_name=notification.name() ! if notification_name == "NOTIFICATION_ONE": ! # code for notification one ! elif notification_name == "NOTIFICATION_TWO" ! # code for notification two ! else: ! # Unhandled notification ! However, sometimes you do not want this; for example, you want to bind ! several methods of an object defined by a third-party module, and you do ! not want to modify its code. Registering multiple callbacks is possible ! when the environment variable ! 'NOTIFICATION_CENTER_MULTIPLE_CALLBACKS_PER_OBSERVER' is defined and ! its value is not an empty string. ! IMPORTANT: this variable should be set *prior* to any import statement ! importing the NotificationCenter module, or it wont have any ! effect at all. ! Example: - bash -- - export NOTIFICATION_CENTER_MULTIPLE_CALLBACKS_PER_OBSERVER='y' - - python -- ! import os ! os.environ['NOTIFICATION_CENTER_MULTIPLE_CALLBACKS_PER_OBSERVER']='y' ! from NotificationFramework import NotificationCenter ! Why is it not the default/only behaviour? ! Handling multiple callbacks per object implies a performance ! penalty. You can test which are the consequences on your platform with ! the supplied script 'compare_perfs.py' in directory tests/ On my ! machine, postNotification() is about 2.4x slower when the handling of ! multiple callbacks per object is activated. ! Notification names and objects ! Notifications names should be strings, even if this is not enforced by the ! framework. ! Notifications objects and info can be (almost: see below) everything. ! Restricting their type to existing python types will save you ! fighting against some strange behaviour, however, and should be sufficient ! for most situations --hopefully! - Zope: some important notes ! TBD!!! In the meantime you can look at the code for methods ! observerCodeForZopePersistentObject() and ! observerCodeForZopeTemporaryObject(), and to ! tests/test_NotificationCenter. test_7_codeObjectObservers(). ! MT status: This library was designed to be MT-safe. $Id$ """ --- 34,176 ---- notification are automatically notified. ! Listeners and callbacks ! ----------------------- ! First at all, the Notification Center needs to have a mean to notify ! objects that a notification they are listening to was posted. To achieve ! this, objects should supply their reference, as well as a callback method ! at registration time (Note: by default only one callback is accepted per ! object; see discussion below). ! The possible listeners are: class instances (`types.InstanceType`), code ! objects or functions (such as functions defined in a module). See method ! `addObserver` for full details ; we will focus in the following on class ! instances. ! ! For listeners being class instances, callbacks' signature should minimally ! be one of these:: ! ! def callback(self, notification) ! def callback(self, *arg) ! Hence, any of the following signatures are okay:: ! def callback(self, notification, param1='param1') ! def callback(self, notification, *arg) ! def callback(self, notification, **kw) ! etc. ! Please note that the callback method must be supplied as a unbound ! method, e.g.: ``ObjectClass.callback``. ! When called by the NotificationCenter upon notification post, callback's ! parameter ``notification`` is a `Notification` instance. ! Registration: Generic- and Specific- listeners ! ---------------------------------------------- ! Object can register as "generic observers" or "specific observers". ! Generic observers listens all notifications coming with a given ! name. They register themselves with:: ! NotificationCenter.addObserver(object, ObjectClass.method, 'NewMessage') ! Generic observers will be notified each time a notification with that name ! is posted, whatever the accompaying object can be (including None). ! Specific observers only listens notifications which have a given name ! *and* a given value. They register themselves with:: ! ! NotificationCenter.addObserver(object, ObjectClass.method, ! 'NewMessage', 'email') ! NotificationCenter.addObserver(object, ObjectClass.method, ! 'NewMessage', 'news') ! etc. ! ! Specific observers are only notified when a notification with these name ! and object is posted. ! ! Registering more than one callback per object ! --------------------------------------------- ! ! By default, `addObserver()` checks that only one callback is registered per ! object; if you try to register a different one, you'll get a ValueError. ! ! Of course, a single object can listen to multiple notifications. In that ! case, you'll probably register a given method, say, handleNotification(), ! dedicated to this task:: ! ! def handleNotification(self, notification): ! notification_name=notification.name() ! if notification_name == "NOTIFICATION_ONE": ! # code for notification one ! elif notification_name == "NOTIFICATION_TWO" ! # code for notification two ! else: ! # Unhandled notification ! ! However, sometimes you do not want this; for example, you want to bind ! several methods of an object defined by a third-party module, and you do ! not want to modify its code. Registering multiple callbacks is possible ! when the environment variable ! ``NOTIFICATION_CENTER_MULTIPLE_CALLBACKS_PER_OBSERVER`` is defined and ! its value is not an empty string. ! ! .. IMPORTANT:: ! ! This variable should be set *prior* to any import statement importing the ! `NotificationCenter` module, or it wont have any effect at all. ! ! Example ! ~~~~~~~ ! bash ! :: ! export NOTIFICATION_CENTER_MULTIPLE_CALLBACKS_PER_OBSERVER='y' ! ! python ! :: ! ! import os ! os.environ['NOTIFICATION_CENTER_MULTIPLE_CALLBACKS_PER_OBSERVER']='y' ! from NotificationFramework import NotificationCenter ! Why is it not the default/only behaviour? ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Handling multiple callbacks per object implies a performance penalty. You ! can test which are the consequences on your platform with the supplied ! script 'compare_perfs.py' in directory tests/ On my machine, ! postNotification() is about 2.4x slower when the handling of multiple ! callbacks per object is activated. ! Notification names and objects ! ------------------------------ ! Notifications names should be strings, even if this is not enforced by the ! framework. + Notifications objects and info can be (almost: see below) everything. + Restricting their type to existing python types will save you fighting against + some strange behaviour, however, and should be sufficient for most situations + --hopefully! ! Zope: some important notes ! -------------------------- ! ! TBD!!! In the meantime you can look at the code for methods ! `observerCodeForZopePersistentObject()` and ! `observerCodeForZopeTemporaryObject()`, and to ! ``tests/test_NotificationCenter.test_7_codeObjectObservers()``. ! MT status: This library was designed to be MT-safe. $Id$ + """ *************** *** 251,256 **** def addObserver(observer, callback, notificationName, object=None, sameObserverRegistersOnce=1): ! """ ! Adds the supplied observer to the list. Note that if the observer in a class' instance, it will be weakly --- 261,265 ---- def addObserver(observer, callback, notificationName, object=None, sameObserverRegistersOnce=1): ! """Adds the supplied observer to the list. Note that if the observer in a class' instance, it will be weakly *************** *** 260,274 **** first time they are supposed to receive a notification. ! addObserver() raises ValueError when an attempt is made to register an object that was previously registered with a different callback than the one supplied. Please refer to the module's documentation for a complete discussion on this topic. ! Parameters: ! observer, callback -- the observer object to be notified, and the method ! to call on that object when a given notification (see other parameters, ! below) is received. The following combinations of observer/callback are ! possible: - observer is a class instance (either a classic or a new-style --- 269,284 ---- first time they are supposed to receive a notification. ! `addObserver()` raises ``ValueError`` when an attempt is made to register an object that was previously registered with a different callback than the one supplied. Please refer to the module's documentation for a complete discussion on this topic. ! :Parameters: ! - `observer` ! - `callback`: the observer object to be notified, and the ! method to call on that object when a given notification (see other ! parameters, below) is received. The following combinations of ! observer/callback are possible: - observer is a class instance (either a classic or a new-style *************** *** 299,322 **** - observer is None: the callback must be of type 'types.FunctionType' ! notificationName, object -- identifies the notification the observer ! listens to. The 'notificationName' is mandatory and is usually a ! string. The object is optional. If provided, the observer will only be ! notified when a notification is posted with the same name and ! accompanying object. If omitted or 'None',the observer will be notified ! each time a notification with the correspoinding 'notificationName' is ! posted (whatever the accompanying object can be in the posted ! notification). ! sameObserverRegistersOnce -- if omitted or if it evaluates to a true ! value, the same observer will only be added once for the notification ! identified by '(notificationName, object)' (if the observer is None, ! replace ``observer'' with ``callback'' in the previous sentence) ; note ! that a notification with an accompanying object being None and another one ! whose accompanying object is not None are always considered different, ! hence in this case this option has obviously no effect. If this parameter ! evaluates to a false value, then the same observer can be multiply ! registered --in this case, such an observer's callback should be ready to ! answer more than once to a single notification post, and should be removed ! as many times as it was registered. """ --- 309,333 ---- - observer is None: the callback must be of type 'types.FunctionType' ! - `notificationName` ! - `object`: identifies the notification the observer listens to. The ! `notificationName` is mandatory and is usually a string. The object is ! optional. If provided, the observer will only be notified when a ! notification is posted with the same name and accompanying object. If ! omitted or ``None``,the observer will be notified each time a ! notification with the correspoinding `notificationName` is posted ! (whatever the accompanying object can be in the posted notification). ! ! - `sameObserverRegistersOnce`: if omitted or if it evaluates to a true ! value, the same observer will only be added once for the notification ! identified by ``(notificationName, object)`` (if the observer is None, ! replace ``observer`` with ``callback`` in the previous sentence) ; note ! that a notification with an accompanying object being None and another ! one whose accompanying object is not None are always considered ! different, hence in this case this option has obviously no effect. If ! this parameter evaluates to a false value, then the same observer can be ! multiply registered --in this case, such an observer's callback should ! be ready to answer more than once to a single notification post, and ! should be removed as many times as it was registered. """ *************** *** 363,381 **** Unregisters the observer for the given notification. Regarding the fact that an observer can be multiply registered for a single Notification (see: ! addObserver()), this method removes **one and only one** of the registered ! occurences except when both 'notificationName' and 'object' are omitted or None: see below. Silently returns if 'observer' is not registered. ! Parameters: ! observer -- the observer object to unregister ! notificationName, object -- these parameters identify the Notification for ! which the observer should be unregistered. If both are omitted or are ! equal to None, then the observer is completely removed from all the lists ! of observers. This includes all occurrences of 'observer' if it has been ! multiply registered. """ --- 374,393 ---- Unregisters the observer for the given notification. Regarding the fact that an observer can be multiply registered for a single Notification (see: ! `addObserver()`), this method removes **one and only one** of the registered ! occurences except when both `notificationName` and `object` are omitted or None: see below. Silently returns if 'observer' is not registered. ! :Parameters: ! - `observer`: the observer object to unregister ! - `notificationName` ! - `object`: these parameters identify the ! `Notification` for which the observer should be unregistered. If both ! are omitted or are equal to None, then the observer is completely ! removed from all the lists of observers. This includes all occurrences ! of 'observer' if it has been multiply registered. """ Index: __init__.py =================================================================== RCS file: /cvsroot/modeling/NotificationFramework/__init__.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** __init__.py 14 Feb 2004 19:41:22 -0000 1.5 --- __init__.py 15 Feb 2004 14:03:56 -0000 1.6 *************** *** 27,34 **** they have no idea of who and where the other objects live. ! The complete documentation can found in L{module ! NotificationCenter<NotificationCenter>}. It is distributed under the GNU General Public License. """ __version__="0.6.1" --- 27,97 ---- they have no idea of who and where the other objects live. ! The complete documentation can found in module `NotificationCenter`. It is distributed under the GNU General Public License. + + `Download the last release at sourceforge`_ + + .. _`Download the last release at sourceforge`: https://sourceforge.net/project/showfiles.php?group_id=58935&package_id=54990 + + Example of use: + + .. code-block:: Python + + >>> from NotificationFramework import NotificationCenter as NC + + >>> SUBJECT_CHANGED='Subject changed' # string identifying the notification + + >>> class Subject: + ... value=0 + ... def __init__(self, name): + ... self.name=name + ... def change_and_notify(self, value): + ... self.value=value + ... NC.postNotification(SUBJECT_CHANGED, self, info=value) + ... def __str__(self): + ... return self.name + + >>> class Observer: + ... def __init__(self, name): + ... self.name=name + ... + ... def handle_notification(self, notification): + ... print self.name, 'received notification:', str(notification) + ... print ' with info:', notification.userInfo() + ... + >>> s1=Subject('s1') + >>> s2=Subject('s2') + >>> observ1, observ2 = Observer('observ1'), Observer('observ2') + >>> generic = Observer('generic') + + >>> # observ1 listens to SUBJECT_CHANGED posted by s1 + ... NC.addObserver(observ1, Observer.handle_notification, SUBJECT_CHANGED, s1) + >>> # observ2 listens to SUBJECT_CHANGED posted by s2 + ... NC.addObserver(observ2, Observer.handle_notification, SUBJECT_CHANGED, s2) + >>> # generic listens to all SUBJECT_CHANGED notifications + ... NC.addObserver(generic, Observer.handle_notification, SUBJECT_CHANGED) + + + >>> s1.change_and_notify(value='hop') + observ1 received notification: <Notification name:'Subject changed' object:'s1'> + with info: hop + generic received notification: <Notification name:'Subject changed' object:'s1'> + with info: hop + + + >>> s2.change_and_notify(value=3) + observ2 received notification: <Notification name:'Subject changed' object:'s2'> + with info: 3 + generic received notification: <Notification name:'Subject changed' object:'s2'> + with info: 3 + + .. raw:: html + + Hosted by:<a href="http://sourceforge.net"> + <img src="http://sourceforge.net/sflogo.php?group_id=58935&type=1" + width="88" height="31" border="0" alt="SourceForge.net Logo"> + </a> + """ __version__="0.6.1" Index: log.py =================================================================== RCS file: /cvsroot/modeling/NotificationFramework/log.py,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** log.py 14 Feb 2004 19:44:11 -0000 1.5 --- log.py 15 Feb 2004 14:03:56 -0000 1.6 *************** *** 26,32 **** Logging methods. ! All methods log(), warn() and trace() are disabled by default. To enable ! them set the environment variable 'NOTIFICATION_FRAMEWORK_TRACE' (for ! debugging purpose mainly) CVS Information --- 26,32 ---- Logging methods. ! All methods `log()`, `warn()` and `trace()` are disabled by default. To ! enable them set the environment variable ``NOTIFICATION_FRAMEWORK_TRACE`` ! (for debugging purpose mainly) CVS Information Index: mems_lib.py =================================================================== RCS file: /cvsroot/modeling/NotificationFramework/mems_lib.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** mems_lib.py 14 Feb 2004 19:44:11 -0000 1.4 --- mems_lib.py 15 Feb 2004 14:03:56 -0000 1.5 *************** *** 3,16 **** The code in this module is borrowed from the ZODB Programmer's Guide. ! It redefines the python2.1's builtin functions issubclass() and isinstance() ! so that they work properly with extension classes. Versions 2.2 and up of python do not have the problem so the module's ! functions issubclass() and isinstance() are the default ones, unchanged. - Note: this is not indicated in the ZODB Programming Guide anymore, probably - because it's of no use for python2.2 and up. Last time I checked I was able to - find the page I'm referring to at: - http://cvs.zope.org/StandaloneZODB/Doc/guide/zodb/node18.html?rev=1.2 - but this URL might be unavailable at the time you're reading this. So in case it is not available, here is a copy of the comments A.M. Kuchling --- 3,20 ---- The code in this module is borrowed from the ZODB Programmer's Guide. ! It redefines the python2.1's builtin functions ``issubclass()`` and ! ``isinstance()`` so that they work properly with extension classes. Versions 2.2 and up of python do not have the problem so the module's ! functions ``issubclass()`` and ``isinstance()`` are the default ones, ! unchanged. ! ! **Note**: ! ! This is not indicated in the ZODB Programming Guide anymore, ! probably because it's of no use for python2.2 and up. Last time I checked I ! was able to find the page I'm referring to at: ! http://cvs.zope.org/StandaloneZODB/Doc/guide/zodb/node18.html?rev=1.2 but ! this URL might be unavailable at the time you're reading this. So in case it is not available, here is a copy of the comments A.M. Kuchling |