[Zope3-checkins] CVS: Zope3/src/zope/app/services - hub.py:1.21

Jim Fulton jim at zope.com
Sun Sep 21 13:32:53 EDT 2003


Update of /cvs-repository/Zope3/src/zope/app/services
In directory cvs.zope.org:/tmp/cvs-serv14736/src/zope/app/services

Modified Files:
	hub.py 
Log Message:
Refactored object events. Object events no longer have locations.
Object movement events have object parents and names.

No-longer use context wrappers.

Added and removed events now extend moved events.


=== Zope3/src/zope/app/services/hub.py 1.20 => 1.21 ===
--- Zope3/src/zope/app/services/hub.py:1.20	Thu Aug  7 11:32:41 2003
+++ Zope3/src/zope/app/services/hub.py	Sun Sep 21 13:32:52 2003
@@ -22,6 +22,7 @@
 
 import random
 
+from zope.app import zapi
 from zodb.btrees.IOBTree import IOBTree
 from zodb.btrees.OIBTree import OIBTree
 
@@ -29,13 +30,14 @@
 
 from zope.component import getAdapter, getService
 from zope.exceptions import NotFoundError
-from zope.context import ContextMethod
 from zope.proxy import removeAllProxies
 from zope.app.services.servicenames import EventSubscription
 
 from zope.app.interfaces.traversing import ITraverser
-from zope.app.interfaces.event import IObjectRemovedEvent, IObjectEvent
-from zope.app.interfaces.event import IObjectMovedEvent, IObjectCreatedEvent
+from zope.app.interfaces.event import IObjectEvent
+from zope.app.interfaces.container import IObjectRemovedEvent
+from zope.app.interfaces.container import IObjectMovedEvent
+from zope.app.interfaces.event import IObjectCreatedEvent
 from zope.app.interfaces.event import IObjectModifiedEvent
 from zope.app.interfaces.services.hub import IObjectHub, ObjectHubError
 from zope.app.services.event import ServiceSubscriberEventChannel
@@ -48,16 +50,17 @@
 from zope.app.interfaces.services.service import ISimpleService
 from zope.interface import implements
 from zope.app.interfaces.event import ISubscriber
-from zope.app.interfaces.event import IObjectAddedEvent
+from zope.app.interfaces.container import IObjectAddedEvent
 from zope.app.interfaces.content.folder import IFolder
 from zope.app.interfaces.traversing import ITraversable
 from zope.app.services.servicenames import HubIds
-from zope.app.event.objectevent import ObjectAddedEvent
+from zope.app.container.contained import ObjectAddedEvent
 
 from zope.app.traversing import traverse, traverseName, getPath, getRoot
 from zope.app.interfaces.services.hub import ObjectHubError
 from zope.app.interfaces.services.hub import ISubscriptionControl
 from persistence import Persistent
+from zope.app.container.contained import Contained
 
 class HubEvent:
     """Convenient mix-in for HubEvents"""
@@ -176,11 +179,14 @@
     else:
         return abs
 
-def canonicalSlash(path):
+def canonicalSlash(parent, name=None):
     # Return a canonical path, with a slash appended
-    return canonicalPath(path) + u'/'
+    path = canonicalPath(parent) + u'/'
+    if name:
+        path += name + u'/'
+    return path
 
-class ObjectHub(ServiceSubscriberEventChannel):
+class ObjectHub(ServiceSubscriberEventChannel, Contained):
 
     # this implementation makes the decision to not interact with any
     # object hubs above it: it is a world unto itself, as far as it is
@@ -197,19 +203,43 @@
         # unicode pathslash --> int
         self.__path_to_hubid = OIBTree()
 
-    def notify(wrapped_self, event):
+    def notify(self, event):
         '''See interface ISubscriber'''
-        clean_self = removeAllProxies(wrapped_self)
-        clean_self._notify(wrapped_self, event)
+        self._notify(self, event)
+
+        # XXX all of these "if"s are BS.  We should subscribe to the
+        # different kinds of events independently.
+
+        
         if IObjectEvent.isImplementedBy(event):
             # generate NotificationHubEvents only if object is known
             # ie registered
+              
             if IObjectMovedEvent.isImplementedBy(event):
-                pathslash = canonicalSlash(event.fromLocation)
-                hubid = clean_self.__path_to_hubid.get(pathslash)
-                if hubid is not None:
-                    new_pathslash = canonicalSlash(event.location)
-                    path_to_hubid = clean_self.__path_to_hubid
+                if not (event.oldParent and event.oldName):
+                    # add event, not interested
+                    return
+
+                # We have a move or remove. See if we know anything about it:
+                pathslash = canonicalSlash(event.oldParent, event.oldName)
+                hubid = self.__path_to_hubid.get(pathslash)
+                if hubid is None:
+                    # Nope
+                    return
+
+                if not (event.newParent and event.newName):
+                    # Removed event
+                    del self.__hubid_to_path[hubid]
+                    del self.__path_to_hubid[pathslash]
+                    # send out IObjectRemovedHubEvent to plugins
+                    event = ObjectRemovedHubEvent(
+                        event.object, hubid, pathslash[:-1], event.object)
+                    self._notify(self, event)
+                else:
+                    # Move
+                    new_pathslash = canonicalSlash(
+                        event.newParent, event.newName)
+                    path_to_hubid = self.__path_to_hubid
                     if path_to_hubid.has_key(new_pathslash):
                         raise ObjectHubError(
                             'Cannot move to location %s, '
@@ -218,34 +248,22 @@
                     hubid = path_to_hubid[pathslash]
                     del path_to_hubid[pathslash]
                     path_to_hubid[new_pathslash] = hubid
-                    clean_self.__hubid_to_path[hubid] = new_pathslash
+                    self.__hubid_to_path[hubid] = new_pathslash
                     # send out IObjectMovedHubEvent to plugins
                     event = ObjectMovedHubEvent(
-                        wrapped_self, hubid, pathslash[:-1],
+                        self, hubid, pathslash[:-1],
                         new_pathslash[:-1], event.object)
-                    clean_self._notify(wrapped_self, event)
-            elif IObjectCreatedEvent.isImplementedBy(event):
-                # a newly created object that has not been added to a
-                # container yet has no location. So, we're not interested in
-                # it.
-                pass
-            else:
-                pathslash = canonicalSlash(event.location)
-                hubid = clean_self.__path_to_hubid.get(pathslash)
-                if hubid is not None:
-                    if IObjectModifiedEvent.isImplementedBy(event):
-                        # send out IObjectModifiedHubEvent to plugins
-                        event = ObjectModifiedHubEvent(
-                            wrapped_self, hubid, pathslash[:-1], event.object)
-                        clean_self._notify(wrapped_self, event)
-                    elif IObjectRemovedEvent.isImplementedBy(event):
-                        del clean_self.__hubid_to_path[hubid]
-                        del clean_self.__path_to_hubid[pathslash]
-                        # send out IObjectRemovedHubEvent to plugins
-                        event = ObjectRemovedHubEvent(
-                            event.object, hubid, pathslash[:-1], event.object)
-                        clean_self._notify(wrapped_self, event)
-    notify = ContextMethod(notify)
+                    self._notify(self, event)
+
+            elif IObjectModifiedEvent.isImplementedBy(event):
+                # send out IObjectModifiedHubEvent to plugins
+                pathslash = canonicalSlash(zapi.getPath(event.object))
+                hubid = self.__path_to_hubid.get(pathslash)
+                if hubid is None:
+                    return
+                event = ObjectModifiedHubEvent(
+                    self, hubid, pathslash[:-1], event.object)
+                self._notify(self, event)
 
     def getHubId(self, path_or_object):
         '''See interface ILocalObjectHub'''
@@ -268,17 +286,16 @@
         except KeyError:
             raise NotFoundError(hubid)
 
-    def getObject(wrapped_self, hubid):
+    def getObject(self, hubid):
         '''See interface IObjectHub'''
-        path = wrapped_self.getPath(hubid)
-        adapter = getAdapter(wrapped_self, ITraverser)
-        wrapped_self._verifyPath(path, adapter)
+        path = self.getPath(hubid)
+        adapter = getAdapter(self, ITraverser)
+        self._verifyPath(path, adapter)
         return adapter.traverse(path)
-    getObject = ContextMethod(getObject)
 
-    def register(wrapped_self, path_or_object):
+    def register(self, path_or_object):
         '''See interface ILocalObjectHub'''
-        clean_self = removeAllProxies(wrapped_self)
+
         # XXX Need a new unit test for this; previously we tested
         #     whether it's wrapped, which is wrong because the root
         #     isn't wrapped (and it certainly makes sense to want to
@@ -292,33 +309,31 @@
 
         pathslash = canonicalSlash(path)
 
-        path_to_hubid = clean_self.__path_to_hubid
+        path_to_hubid = self.__path_to_hubid
         if path_to_hubid.has_key(pathslash):
             raise ObjectHubError('path %s already in object hub' % path)
-        hubid = clean_self._generateHubId(pathslash)
+        hubid = self._generateHubId(pathslash)
         path_to_hubid[pathslash] = hubid
 
         # send out IObjectRegisteredHubEvent to plugins
         event = ObjectRegisteredHubEvent(
-            wrapped_self, hubid, pathslash[:-1], obj)
-        clean_self._notify(wrapped_self, event)
+            self, hubid, pathslash[:-1], obj)
+        self._notify(self, event)
         return hubid
-    register = ContextMethod(register)
 
-    def unregister(wrapped_self, path_or_object_or_hubid):
+    def unregister(self, path_or_object_or_hubid):
         '''See interface ILocalObjectHub'''
-        clean_self = removeAllProxies(wrapped_self)
         if isinstance(path_or_object_or_hubid, (unicode, str)):
             path = canonicalPath(path_or_object_or_hubid)
         elif isinstance(path_or_object_or_hubid, int):
-            path = clean_self.getPath(path_or_object_or_hubid)
+            path = self.getPath(path_or_object_or_hubid)
         else:
             path = getPath(path_or_object_or_hubid)
 
         pathslash = canonicalSlash(path)
 
-        path_to_hubid = clean_self.__path_to_hubid
-        hubid_to_path = clean_self.__hubid_to_path
+        path_to_hubid = self.__path_to_hubid
+        hubid_to_path = self.__hubid_to_path
         try:
             hubid = path_to_hubid[pathslash]
         except KeyError:
@@ -329,9 +344,8 @@
 
             # send out IObjectUnregisteredHubEvent to plugins
             event = ObjectUnregisteredHubEvent(
-                wrapped_self, hubid, pathslash[:-1])
-            clean_self._notify(wrapped_self, event)
-    unregister = ContextMethod(unregister)
+                self, hubid, pathslash[:-1])
+            self._notify(self, event)
 
     def numRegistrations(self):
         """See interface IObjectHub"""
@@ -359,12 +373,11 @@
                 min=pathslash, max=pathslash[:-1]+u'0', excludemax=True):
                 yield pathslash[:-1], hubId
 
-    def iterObjectRegistrations(wrapped_self):
+    def iterObjectRegistrations(self):
         """See interface IHubEventChannel"""
-        traverser = getAdapter(wrapped_self, ITraverser)
-        for path, hubId in wrapped_self.iterRegistrations():
-            yield (path, hubId, wrapped_self._safeTraverse(path, traverser))
-    iterObjectRegistrations = ContextMethod(iterObjectRegistrations)
+        traverser = getAdapter(self, ITraverser)
+        for path, hubId in self.iterRegistrations():
+            yield (path, hubId, self._safeTraverse(path, traverser))
 
     ############################################################
 
@@ -379,15 +392,14 @@
         return index
 
 
-    def _verifyPath(wrapped_self, path, traverser=None):
+    def _verifyPath(self, path, traverser=None):
         if traverser is None:
-            traverser = getAdapter(wrapped_self, ITraverser)
+            traverser = getAdapter(self, ITraverser)
         try:
             traverser.traverse(path)
         except NotFoundError, e:
-            wrapped_self.unregister(path)
+            self.unregister(path)
             raise e
-    _verifyPath = ContextMethod(_verifyPath)
 
 
     def _safeTraverse(self, path, traverser):
@@ -396,17 +408,16 @@
         except NotFoundError:
             return None
 
-    def unregisterMissingObjects(wrapped_self):
+    def unregisterMissingObjects(self):
         # XXX temporary method for clearing missing objects - remove when
         # proper unregistration mechanisms are added.
         missing = []
-        for object in wrapped_self.iterObjectRegistrations():
+        for object in self.iterObjectRegistrations():
             if object[2] is None:
                 missing.append(object[0])
         for path in missing:
-            wrapped_self.unregister(path)
+            self.unregister(path)
         return len(missing)
-    unregisterMissingObjects = ContextMethod(unregisterMissingObjects)
 
 
 """A simple-minded registration object.
@@ -427,11 +438,11 @@
 """
 
 
-class Registration(Persistent):
+class Registration(Persistent, Contained):
 
     implements(ISubscriptionControl, ISubscriber)
 
-    def notify(wrapped_self, event):
+    def notify(self, event):
         """An event occured. Perhaps register this object with the hub."""
 
         # XXX quick hack to make sure we *only* register on add events
@@ -440,41 +451,37 @@
         # have it correct now.
 
         if event.__class__ is ObjectAddedEvent:
-            hub = getService(wrapped_self, HubIds)
-            wrapped_self._registerObject(event.location, hub)
-    notify = ContextMethod(notify)
+            hub = getService(self, HubIds)
+            self._registerObject(event.object, hub)
 
     currentlySubscribed = False # Default subscription state
 
-    def subscribe(wrapped_self):
-        if wrapped_self.currentlySubscribed:
+    def subscribe(self):
+        if self.currentlySubscribed:
             raise RuntimeError, "already subscribed; please unsubscribe first"
         # we subscribe to the HubIds service so that we're
         # guaranteed to get exactly the events *that* service receives.
-        events = getService(wrapped_self, EventSubscription)
-        events.subscribe(wrapped_self, IObjectAddedEvent)
-        wrapped_self.currentlySubscribed = True
-    subscribe = ContextMethod(subscribe)
+        events = getService(self, EventSubscription)
+        events.subscribe(self, IObjectAddedEvent)
+        self.currentlySubscribed = True
 
-    def unsubscribe(wrapped_self):
-        if not wrapped_self.currentlySubscribed:
+    def unsubscribe(self):
+        if not self.currentlySubscribed:
             raise RuntimeError, "not subscribed; please subscribe first"
-        events = getService(wrapped_self, EventSubscription)
-        events.unsubscribe(wrapped_self, IObjectAddedEvent)
-        wrapped_self.currentlySubscribed = False
-    unsubscribe = ContextMethod(unsubscribe)
+        events = getService(self, EventSubscription)
+        events.unsubscribe(self, IObjectAddedEvent)
+        self.currentlySubscribed = False
 
     def isSubscribed(self):
         return self.currentlySubscribed
 
-    def registerExisting(wrapped_self):
-        object = findContentObject(wrapped_self)
-        hub = getService(wrapped_self, HubIds)
-        wrapped_self._registerTree(object, hub)
-    registerExisting = ContextMethod(registerExisting)
+    def registerExisting(self):
+        object = findContentObject(self)
+        hub = getService(self, HubIds)
+        self._registerTree(object, hub)
 
-    def _registerTree(wrapped_self, object, hub):
-        wrapped_self._registerObject(object, hub)
+    def _registerTree(self, object, hub):
+        self._registerObject(object, hub)
         # XXX Policy decision: only traverse into folders
         if not IFolder.isImplementedBy(object):
             return
@@ -483,17 +490,15 @@
         traversable = getAdapter(object, ITraversable)
         for name in names:
             sub_object = traverseName(object, name, traversable=traversable)
-            wrapped_self._registerTree(sub_object, hub)
-    _registerTree = ContextMethod(_registerTree)
+            self._registerTree(sub_object, hub)
 
-    def _registerObject(wrapped_self, location, hub):
+    def _registerObject(self, location, hub):
         # XXX Policy decision: register absolutely everything
         try:
             hub.register(location)
         except ObjectHubError:
             # Already registered
             pass
-    _registerObject = ContextMethod(_registerObject)
 
 def findContentObject(context):
     # We want to find the (content) Folder in whose service manager we




More information about the Zope3-Checkins mailing list