[Zope-Checkins] CVS: Zope3/lib/python/Zope/App/OFS/Services/LocalEventService - LocalEventService.py:1.1.2.5 LocalSubscriptionAware.py:1.1.2.2

Gary Poster garyposter@earthlink.net
Sun, 19 May 2002 13:43:31 -0400


Update of /cvs-repository/Zope3/lib/python/Zope/App/OFS/Services/LocalEventService
In directory cvs.zope.org:/tmp/cvs-serv8180/lib/python/Zope/App/OFS/Services/LocalEventService

Modified Files:
      Tag: Zope-3x-branch
	LocalEventService.py LocalSubscriptionAware.py 
Log Message:
more tests and fixes to the local event service



=== Zope3/lib/python/Zope/App/OFS/Services/LocalEventService/LocalEventService.py 1.1.2.4 => 1.1.2.5 ===
 from Zope.Event.ISubscriber import ISubscriber
 from LocalServiceSubscribable import LocalServiceSubscribable
-from Zope.ComponentArchitecture import getNextService, getAdapter
+from Zope.ComponentArchitecture import getNextService, getAdapter, getService
 from Zope.App.OFS.ServiceManager.IBindingAware import IBindingAware
 from Zope.ContextWrapper import ContextMethod
 from Zope.Proxy.ProxyIntrospection import removeAllProxies
@@ -31,6 +31,7 @@
 from LocalSubscriptionAware import LocalSubscriptionAware
 from Interface.Attribute import Attribute
 from Zope.Event.GlobalEventService import eventService
+from Zope.Event.IEvent import IEvent
 
 class ILocalEventService(IEventService, ISubscriber, IBindingAware, ISubscriptionAware):
     
@@ -121,16 +122,45 @@
         clean_self=removeAllProxies(wrapped_self)
         subscriber=PathSubscriber(wrapped_self)
         clean_self._v_unbinding=1
-        for subscribable_path in clean_self._subscriptions:
-            subscribable=getAdapter(wrapped_self, ITraverser).traverse(subscribable_path)
+        for subscription in clean_self._subscriptions:
+            subscribable=getAdapter(wrapped_self, ITraverser).traverse(subscription[0])
             subscribable.unsubscribe(subscriber)
         clean_self._subscriptions=()
         for subscriber in clean_self._subscribers:
-            wrapped_self.unsubscribe(subscriber)
+            clean_self.__unsubscribeAllFromSelf(wrapped_self, subscriber[0])
         clean_self._v_unbinding=None
 
     unbound=ContextMethod(unbound)
     
+    def __unsubscribeAllFromSelf(clean_self, wrapped_self, subscriber):
+        """this is *not* an interface function, and should not be used
+        outside of this class"""
+    
+        wrapped_subscriber=ContextWrapper(subscriber, wrapped_self)
+        
+        for subscriber_index in range(len(clean_self._subscribers)):
+            sub=clean_self._subscribers[subscriber_index]
+            if sub[0]==subscriber:
+                ev_set=sub[1]
+                break
+        else:
+            raise NotFoundError(subscriber)
+        do_alert=ISubscriptionAware.isImplementedBy(subscriber)
+        for ev_type in ev_set:
+            subscriptions = clean_self._registry.getJustForType(ev_type)
+            subs=subscriptions[:]
+            subscriptions[:] = []
+            for sub in subs:
+                if sub[0] == subscriber: # deleted (not added back)
+                    if do_alert:
+                        wrapped_subscriber.unsubscribedFrom(
+                            wrapped_self, ev_type or IEvent, sub[1])
+                        # IEvent switch is to make optimization transparent
+                else: # kept (added back)
+                    subscriptions.append(sub)
+        del clean_self._subscribers[subscriber_index]
+        clean_self._registry=clean_self._registry #trigger persistence, if pertinent
+    
     def unsubscribedFrom(wrapped_self, subscribable, event_type, filter):
         "see ISubscriptionAware"
         clean_self=removeAllProxies(wrapped_self)
@@ -144,8 +174,11 @@
             clean_subscribable=removeAllProxies(subscribable)
             if IEventService.isImplementedBy(removeAllProxies(clean_subscribable)):
                 context=getService(wrapped_self, "Events")
-                while removeAllProxies(context) is clean_subscribable:
-                    context=getService(context, "Events")
+                # we do this instead of getNextService because the order
+                # of unbinding and notification of unbinding is not
+                # guaranteed
+                while removeAllProxies(context) in (clean_subscribable, clean_self): 
+                    context=getNextService(context, "Events")
                 # XXX as usual, we *must not* be working with a global service;
                 # this probably should raise an error if service is global service...
                 # that leaves replacing top level event services an


=== Zope3/lib/python/Zope/App/OFS/Services/LocalEventService/LocalSubscriptionAware.py 1.1.2.1 => 1.1.2.2 ===
     
     def subscribedTo(self, subscribable, event_type, filter):
-        subscribable_path=getAdapter(
-            subscribable, ITraverser).getPhysicalPath()
+        #subscribable_path=getAdapter(
+         #   subscribable, ITraverser).getPhysicalPath()
+        subscribable_path="/%s" % "/".join(getAdapter(
+            subscribable, ITraverser).getPhysicalPath())
+        # XXX right now the conversion to a string is necessary because
+        # the tuple path returned by the Traverser does not include an
+        # empty initial space to represent the root
         if (subscribable_path, event_type, filter) not in self._subscriptions:
             self._subscriptions+=((subscribable_path,event_type, filter),)
     
     def unsubscribedFrom(self, subscribable, event_type, filter):
-        subscribable_path=getAdapter(
-            subscribable, ITraverser).getPhysicalPath()
+        subscribable_path="/%s" % "/".join(getAdapter(
+            subscribable, ITraverser).getPhysicalPath())
         sub=list(self._subscriptions)
         sub.remove((subscribable_path, event_type, filter))
-        self._subscriptions=sub
+        self._subscriptions=tuple(sub)