[Zope3-checkins] CVS: Zope3/lib/python/Zope/ObjectHub - configure.zcml:1.1 HubEvent.py:1.3 IHubEvent.py:1.4 IObjectHub.py:1.4 ObjectHub.py:1.10

Gary Poster gary@modernsongs.com
Mon, 21 Oct 2002 02:14:49 -0400


Update of /cvs-repository/Zope3/lib/python/Zope/ObjectHub
In directory cvs.zope.org:/tmp/cvs-serv13005/Zope/ObjectHub

Modified Files:
	HubEvent.py IHubEvent.py IObjectHub.py ObjectHub.py 
Added Files:
	configure.zcml 
Log Message:
sorry for the huge honking checkin.

Adds a simple local objecthub implementation and made ObjectHub a service

Modifies the main objecthub as we have been discussing:
 * objecthub attribute is hubid, not hid (sorry Jim, I'll change it back if you want but there were a lot of "yay"s and no "nay"s :-)
 * no more IObjectAddedHubEvent
 * IObjectRemovedEvent now (hopefully) actually has the effect on the ObjectHub that is described in the interface, and that we agreed upon, namely (assuming removed object was cataloged in objecthub) removing catalog of object in objecthub and sending out an IObjectRemovedHubEvent, subclass of IObjectUnregisteredHubEvent, to the ObjectHub subscribers

I tried to spruce up the LocalEventService a bit but the code still looks as opaque as ever, I'm afraid.  Among other small improvements, though, at least you actually can see the silly "user interface" now without a traceback.  Now for a *real* user interface sometime. :-)

Fixed a few typos while I was at it as well...and I'm sure made my share of new ones :-)




=== Added File Zope3/lib/python/Zope/ObjectHub/configure.zcml ===
<zopeConfigure
   xmlns='http://namespaces.zope.org/zope'
   xmlns:browser='http://namespaces.zope.org/browser'
>

<serviceType id='ObjectHub' 
             interface='Zope.ObjectHub.IObjectHub.' />

</zopeConfigure>


=== Zope3/lib/python/Zope/ObjectHub/HubEvent.py 1.2 => 1.3 ===
--- Zope3/lib/python/Zope/ObjectHub/HubEvent.py:1.2	Thu Oct  3 16:53:22 2002
+++ Zope3/lib/python/Zope/ObjectHub/HubEvent.py	Mon Oct 21 02:14:48 2002
@@ -20,30 +20,30 @@
 __metaclass__ = type
 
 from IHubEvent import IObjectRegisteredHubEvent
-from IHubEvent import IObjectAddedHubEvent
 from IHubEvent import IObjectUnregisteredHubEvent
 from IHubEvent import IObjectModifiedHubEvent
 from IHubEvent import IObjectMovedHubEvent
 from IHubEvent import IObjectRemovedHubEvent
+from Zope.App.Traversing import traverse
 
 class HubEvent:
     """Convenient mix-in for HubEvents"""
 
     location = None
-    hid = None
+    hubid = None
     
-    def __init__(self, objecthub, hid, location):
+    def __init__(self, objecthub, hubid, location):
         # we keep all three, to avoid unnecessary lookups
         # and to give the objecthub an opportunity to do
         # caching of objects
         self.__objecthub = objecthub
-        self.hid = hid
+        self.hubid = hubid
         self.location = location
         
     def __getObject(self):
         if hasattr(self, '_v_object'):
             return self._v_object
-        obj = self._v_object = self.__objecthub.getObject(self.hid)
+        obj = self._v_object = self.__objecthub.getObject(self.hubid)
         return obj
 
     object = property(__getObject)
@@ -59,13 +59,14 @@
     """We are no longer interested in this object."""
 
     __implements__ = IObjectUnregisteredHubEvent
-
-
-class ObjectAddedHubEvent(HubEvent):
-    """An ruid has been freshly created and mapped against an object.
-       Also, implies the object has been newly added."""
     
-    __implements__ = IObjectAddedHubEvent
+    # XXX __getObject is *not* implemented in a safe way for this
+    # event, because the hubid-to-object mapping in the object hub may
+    # have already been deleted.  However, I am more concerned about the
+    # local version and will merely mark this as an issue.  In the
+    # global object hub I have merely made the deletion happen *after*
+    # the event notify.  (We cannot use traverse for these events
+    # because that is a Zope-specific capability, in App.)
     
     
 class ObjectModifiedHubEvent(HubEvent):
@@ -81,14 +82,13 @@
     __implements__ = IObjectMovedHubEvent
 
 
-class ObjectRemovedHubEvent(HubEvent):
+class ObjectRemovedHubEvent:
     """An object with an ruid has been removed."""
 
     __implements__ = IObjectRemovedHubEvent
+    # ...which is a subclass of IObjectUnregisteredHubEvent
 
-    object = None
-
-    def __init__(self, obj, hid, location):
+    def __init__(self, obj, hubid, location):
         self.object = obj
-        self.hid = hid
+        self.hubid = hubid
         self.location = location


=== Zope3/lib/python/Zope/ObjectHub/IHubEvent.py 1.3 => 1.4 ===
--- Zope3/lib/python/Zope/ObjectHub/IHubEvent.py:1.3	Thu Oct  3 16:53:22 2002
+++ Zope3/lib/python/Zope/ObjectHub/IHubEvent.py	Mon Oct 21 02:14:48 2002
@@ -21,43 +21,40 @@
 
 class IHubEvent(IEvent):
     """Internal Object Hub Event : something has happened to an object for
-       which there is an ruid.
-       An ruid is a way of refering to an object independent of location.
+       which there is a hub id.
+       A hub id is a way of refering to an object independent of location.
     """
 
     object = Attribute("The subject of the event.")
 
-    hid = Attribute("the object's hub-unique id")
+    hubid = Attribute("the object's hub-unique id")
 
     location = Attribute("An optional object location.")
    
 
 class IRegistrationHubEvent(IHubEvent):
-    """Some work could be done on registration or deregistration of an object.
+    """The hub registration status of an object has changed
     """
 
+
 class IObjectRegisteredHubEvent(IRegistrationHubEvent):
-    """An ruid has been freshly created and mapped against an object."""
+    """A hub id has been freshly created and mapped against an object."""
 
 
 class IObjectUnregisteredHubEvent(IRegistrationHubEvent):
     """We are no longer interested in this object."""
-
-
-class IObjectAddedHubEvent(IObjectRegisteredHubEvent):
-    """An ruid has been freshly created and mapped against an object.
-       Also, implies the object has been newly added."""
     
     
 class IObjectModifiedHubEvent(IHubEvent):
-    """An object with an ruid has been modified."""
+    """An object with a hub id has been modified."""
     
     
 class IObjectMovedHubEvent(IHubEvent):
-    """An object with an ruid has had its context changed. Typically, this
+    """An object with a hub id has had its context changed. Typically, this
        means that it has been moved."""
 
     fromLocation = Attribute("The old location for the object.")
 
-class IObjectRemovedHubEvent(IHubEvent):
-    """An object with an ruid has been removed."""
+
+class IObjectRemovedHubEvent(IObjectUnregisteredHubEvent):
+    """An object with a hub id has been removed and unregistered."""


=== Zope3/lib/python/Zope/ObjectHub/IObjectHub.py 1.3 => 1.4 ===
--- Zope3/lib/python/Zope/ObjectHub/IObjectHub.py:1.3	Tue Jun 25 06:45:46 2002
+++ Zope3/lib/python/Zope/ObjectHub/IObjectHub.py	Mon Oct 21 02:14:48 2002
@@ -23,51 +23,51 @@
     """ObjectHub.
     
     Receives Object Modify Events from the Event Service, and
-    changes these into RUID Object Modify Events, then passes
-    these on to its PlugIns (possibly via some other EventChannels).
+    changes these into Hub Id Object Modify Events, then passes
+    these on to its subscribers.
        
-    To map Object Modify Events onto RUID Object Modify Events, take
-    the location from the Object Modify Event, look up the RUID for this
-    location, and create an equivalent RUID Object Modify Event using this
-    RUID.
+    To map Object Modify Events onto Hub Id Object Modify Events, take
+    the location from the Object Modify Event, look up the Hub Id for this
+    location, and create an equivalent Hub Id Object Modify Event using this
+    Hub Id.
        
     Note that we are concerned with locations and not with Objects.
     An object may have more than one location. That doesn't concern
     us here.
+    
+    We're only interested in what happens during the time during which
+    an object is registered with the hub -- between ObjectRegistered
+    and ObjectUnregistered events.  As one consequence of that, we do
+    care about object removals, but not (directly) about object
+    additions.
        
-    Table of decisions about maintaining the location<->ruid lookup:
+    Table of decisions about maintaining the location<->Hub Id lookup:
        
       Register
       
          if location already in lookup:
              raise ObjectHubError, as this is implies bad state somewhere
-         generate new ruid
-         place ruid<->location into lookup, to say that we have an
+         generate new hub id
+         place hub id<->location into lookup, to say that we have an
              interesting object
              
-         send out ruid object register event to plug-ins, via event channels
+         send out hub id object register event to subscribers
          
       Unregister
          
          if location not in lookup:
              raise ObjectHubError, as this is implies bad state somewhere
-         remove location<->ruid from lookup
+         remove location<->hub id from lookup
             
-         send out ruid unregister event to plug-ins, via event channels
-       
-      Add (specialises Register)
-         
-         as Register, except at the end send out ruid object add event
-         instead
+         send out hub id unregister event to subscribers
          
       Modify
          
          if location not in lookup:
              ignore this event, as we're not interested in this object
          else:
-             look up ruid for the location
-             send out ruid object modify event to plug-ins,
-                 via event channels
+             look up hub id for the location
+             send out hub id object modify event to subscribers
                 
       Move 
 
@@ -76,36 +76,26 @@
          elif new_location is in lookup:
              raise ObjectHubError
          else:
-             look up ruid for old_location
+             look up hub id for old_location
              change lookup:
-                 remove ruid<->old_location
-                 add ruid<->new_location
-             send out ruid object context-change event to plug-ins,
-                 via event channels
-         
-      Remove (specialises Unregister)
+                 remove hub id<->old_location
+                 add hub id<->new_location
+             send out hub id object context-change event to subscribers
+
+      Remove (specializes Unregister)
 
          if old_location not in lookup:
              ignore this event, as we're not interested in this object
          else:
-             look up ruid for old_location
+             look up hub id for old_location
              change lookup:
-                 remove ruid<->old_location
-             send out ruid object remove event to plug-ins,
-                 via event channels
-    
-     # XXX: Possibly add Link to EventChannel.
-     #      This implies multiple locations for a ruid. 
-     #      We'll refactor later if needed.
-        
-     # Possibly also add registerObject and unregisterObject methods
-     # unless these are better handled by events, or unless we don't
-     # need them.
+                 remove hub id<->old_location
+             send out hub id object remove event to subscribers
      """
 
         
-    def lookupRuid(location):
-        """Returns the ruid int that is mapped to the given location.
+    def lookupHubId(location):
+        """Returns the hub id int that is mapped to the given location.
         
         Location is either a string, or a sequence of strings.
         It must be absolute, so if it is a string it must start with a '/',
@@ -114,36 +104,36 @@
         ('','whatever','whatever2')
         '/whatever/whatever2'
         
-        If there is no ruid, raise Zope.Exceptions.NotFoundError.
+        If there is no hub id, raise Zope.Exceptions.NotFoundError.
         
         """
         
-    def lookupLocation(ruid):
+    def lookupLocation(hubid):
         """Returns a location as a string.
         
         If there is no location, raise Zope.Exceptions.NotFoundError.
         """
         
-    def getObject(ruid):
-        """Returns an object for the given ruid.
+    def getObject(hubid):
+        """Returns an object for the given hub id.
         
-        If there is no such ruid, raise Zope.Exceptions.NotFoundError.
+        If there is no such hub id, raise Zope.Exceptions.NotFoundError.
         If there is no such object, passes through whatever error
         the traversal service raises.
         """
 
     def register(location):
-        """Returns a new ruid for the given location if it is not 
+        """Returns a new hub id for the given location if it is not 
         already registered. 
 
-        It also emits a RuidObjectRegisteredEvent.  Raises an 
+        It also emits a HubIdObjectRegisteredEvent.  Raises an 
         ObjectHubError if the location was previously registered. 
         """
 
-    def unregister(ruid_or_location):
-        """Unregister an object identified either by location or by ruid.
+    def unregister(hubid_or_location):
+        """Unregister an object identified either by location or by hubid.
 
-        It also emits a RuidObjectUnregisteredEvent. 
-        If the Ruid or location wasn't registered a 
+        It also emits a HubIdObjectUnregisteredEvent. 
+        If the hub id or location wasn't registered a 
         Zope.Exceptions.NotFoundError is raised.
         """ 


=== Zope3/lib/python/Zope/ObjectHub/ObjectHub.py 1.9 => 1.10 ===
--- Zope3/lib/python/Zope/ObjectHub/ObjectHub.py:1.9	Thu Oct  3 16:53:22 2002
+++ Zope3/lib/python/Zope/ObjectHub/ObjectHub.py	Mon Oct 21 02:14:48 2002
@@ -25,7 +25,6 @@
 from Zope.Event.EventChannel import EventChannel
 from HubEvent import ObjectRegisteredHubEvent
 from HubEvent import ObjectUnregisteredHubEvent
-from HubEvent import ObjectAddedHubEvent
 from HubEvent import ObjectModifiedHubEvent
 from HubEvent import ObjectMovedHubEvent
 from HubEvent import ObjectRemovedHubEvent
@@ -33,8 +32,6 @@
 
 from Zope.Exceptions import NotFoundError
 from Persistence import Persistent
-from Interface.Implements import objectImplements
-from types import StringTypes
 from Persistence.BTrees.IOBTree import IOBTree
 from Persistence.BTrees.OIBTree import OIBTree
 
@@ -55,14 +52,14 @@
 class ObjectHubError(Exception):
     pass
 
-class ObjectHub(Persistent):
+class ObjectHub(EventChannel, Persistent):
 
     __implements__ =  IObjectHub
 
     def __init__(self):
-        self.__ruid_to_location = IOBTree()
-        self.__location_to_ruid = OIBTree()
-        self.__eventchannel = EventChannel()
+        EventChannel.__init__(self)
+        self.__hubid_to_location = IOBTree()
+        self.__location_to_hubid = OIBTree()
         
     _clear = __init__
 
@@ -71,71 +68,53 @@
     # Implementation methods for interface
     # Zope.ObjectHub.IObjectHub
 
-    def subscribe(self, subscriber, event_type=IEvent, filter=None):
-        '''See interface ISubscribable'''
-        self.__eventchannel.subscribe(subscriber, event_type, filter)
-
-    def unsubscribe(self, subscriber, event_type=None, filter=None):
-        '''See interface ISubscribable'''
-        self.__eventchannel.unsubscribe(subscriber, event_type, filter)
-    
-    def listSubscriptions(self, subscriber, event_type=None):
-        "See interface ISubscribable"
-        return self.__eventchannel.listSubscriptions(subscriber, event_type)
-
     def notify(self, event):
         '''See interface ISubscriber'''
-        if IHubEvent.isImplementedBy(event):
-            self.__eventchannel.notify(event)
-            return
+        self._notify(event)
 
         if IObjectEvent.isImplementedBy(event):
-            self.__eventchannel.notify(event)
-
             # generate NotificationHubEvents only if object is known
             # ie registered  
             if IObjectMovedEvent.isImplementedBy(event):
                 canonical_location = locationAsUnicode(event.fromLocation)
-                ruid = self._lookupRuid(canonical_location)
-                if ruid is not None:
+                hubid = self._lookupHubId(canonical_location)
+                if hubid is not None:
                     self._objectMoved(event.fromLocation,
                                       event.location)
                 return
-                
+            
             canonical_location = locationAsUnicode(event.location)
-            ruid = self._lookupRuid(canonical_location)
-            if ruid is not None:
-                if IObjectAddedEvent.isImplementedBy(event): 
-                    self._objectAdded(canonical_location, ruid)
+            hubid = self._lookupHubId(canonical_location)
+            if hubid is not None:
                     
-                elif IObjectModifiedEvent.isImplementedBy(event):
-                    self._objectModified(canonical_location, ruid)
-                                      
+                if IObjectModifiedEvent.isImplementedBy(event):
+                    self._objectModified(canonical_location, hubid)
+                
                 elif IObjectRemovedEvent.isImplementedBy(event):
                     self._objectRemoved(canonical_location,
-                                        ruid,
+                                        hubid,
                                         event.object)
         # otherwise, ignore the event
 
-    def lookupRuid(self, location):
+    def lookupHubId(self, location):
         '''See interface IObjectHub'''
-        ruid = self._lookupRuid(location)
-        if ruid is None:
+        hubid = self._lookupHubId(location)
+        if hubid is None:
             raise NotFoundError, locationAsUnicode(location)
         else:
-            return ruid
+            return hubid
     
-    def lookupLocation(self, ruid):
+    def lookupLocation(self, hubid):
         '''See interface IObjectHub'''
         try:
-            return self.__ruid_to_location[ruid]
+            return self.__hubid_to_location[hubid]
         except KeyError:
-            raise NotFoundError, ruid
+            raise NotFoundError, hubid
         
-    def getObject(self, ruid):
+    def getObject(self, hubid):
         '''See interface IObjectHub'''
-        location = self.lookupLocation(ruid)
-        adapter = getAdapter(object, ITraverser)
+        location = self.lookupLocation(hubid)
+        adapter = getAdapter(self, ITraverser)
         return adapter.traverse(location)
 
     def register(self, location):
@@ -143,117 +122,122 @@
         canonical_location=locationAsUnicode(location)
         if location[0] != u'/':
             raise ValueError, "Location must be absolute"
-        ruid = self._registerObject(canonical_location)
-        return ruid
+        hubid = self._registerObject(canonical_location)
+        return hubid
 
-    def unregister(self, ruid_or_location):
+    def unregister(self, hubid_or_location):
         '''See interface IObjectHub'''
-        if type(ruid_or_location) is int:
-            canonical_location=self.lookupLocation(ruid_or_location)
+        if type(hubid_or_location) is int:
+            canonical_location=self.lookupLocation(hubid_or_location)
         else:
-            canonical_location=locationAsUnicode(ruid_or_location)
-        ruid = self._unregisterObject(canonical_location)
-        if ruid is None:
+            canonical_location=locationAsUnicode(hubid_or_location)
+        hubid = self._unregisterObject(canonical_location)
+        if hubid is None:
             raise NotFoundError, 'location %s is not in object hub' % \
                 canonical_location
   
     #
     ############################################################
+    
+    _notify = EventChannel.notify # this is a plug so we can reuse
+    # almost the entirety of this code for the local version of the
+    # ObjectHub (Zope.App.OFS.Services.ObjectHub.ObjectHub)
 
-    def _generateRuid(self, location):
+    def _generateHubId(self, location):
         index=getattr(self, '_v_nextid', 0)
         if index%4000 == 0: index = randid()
-        ruid_to_location=self.__ruid_to_location
-        while not ruid_to_location.insert(index, location):
+        hubid_to_location=self.__hubid_to_location
+        while not hubid_to_location.insert(index, location):
             index=randid()
         self._v_nextid=index+1
         return index
 
-    def _lookupRuid(self, location):
+    def _lookupHubId(self, location):
         canonical_location = locationAsUnicode(location) 
-        return self.__location_to_ruid.get(canonical_location, None)
+        return self.__location_to_hubid.get(canonical_location, None)
 
     def _registerObject(self, canonical_location):
-        location_to_ruid = self.__location_to_ruid
-        if location_to_ruid.has_key(canonical_location):
+        location_to_hubid = self.__location_to_hubid
+        if location_to_hubid.has_key(canonical_location):
             raise ObjectHubError, 'location %s already in object hub' % \
                 canonical_location
-        ruid = self._generateRuid(canonical_location)
-        location_to_ruid[canonical_location] = ruid
+        hubid = self._generateHubId(canonical_location)
+        location_to_hubid[canonical_location] = hubid
 
         # send out IObjectRegisteredHubEvent to plugins
         event = ObjectRegisteredHubEvent(
             self, 
-            ruid,
+            hubid,
             canonical_location)
-        self.__eventchannel.notify(event)
-        return ruid
+        self._notify(event)
+        return hubid
 
-    def _objectAdded(self, canonical_location, ruid):
-        # send out IObjectAddedHubEvent to plugins
-        event = ObjectAddedHubEvent(
-            self, 
-            ruid,
-            canonical_location)
-        self.__eventchannel.notify(event)
+    # see comment in notify
+    #def _objectAdded(self, canonical_location, hubid):
+    #    # send out IObjectAddedHubEvent to plugins
+    #    event = ObjectAddedHubEvent(
+    #        self, 
+    #        hubid,
+    #        canonical_location)
+    #    self._notify(event)
     
-    def _objectModified(self, canonical_location, ruid):
+    def _objectModified(self, canonical_location, hubid):
         # send out IObjectModifiedHubEvent to plugins
         event = ObjectModifiedHubEvent(
             self, 
-            ruid,
+            hubid,
             canonical_location)
-        self.__eventchannel.notify(event)
+        self._notify(event)
     
     def _objectMoved(self, old_location, new_location):
-        location_to_ruid = self.__location_to_ruid
+        location_to_hubid = self.__location_to_hubid
         canonical_location = locationAsUnicode(old_location)
         canonical_new_location = locationAsUnicode(new_location)
-        if location_to_ruid.has_key(canonical_new_location):
+        if location_to_hubid.has_key(canonical_new_location):
             raise ObjectHubError(
                 'Cannot move to location %s, '
                 'as there is already something there'
                 % canonical_new_location)
-        # already tested before calling _objectMoved
-##        if not location_to_ruid.has_key(canonical_location):
-##            # we're not interested in this event
-##            return
-
-        ruid = location_to_ruid[canonical_location]
-        del location_to_ruid[canonical_location]
-        location_to_ruid[canonical_new_location] = ruid
-        self.__ruid_to_location[ruid] = canonical_new_location
+        hubid = location_to_hubid[canonical_location]
+        del location_to_hubid[canonical_location]
+        location_to_hubid[canonical_new_location] = hubid
+        self.__hubid_to_location[hubid] = canonical_new_location
         # send out IObjectMovedHubEvent to plugins
         event = ObjectMovedHubEvent(
             self, 
-            ruid,
+            hubid,
             canonical_new_location)
-        self.__eventchannel.notify(event)
+        self._notify(event)
 
     def _unregisterObject(self, canonical_location):
-        location_to_ruid = self.__location_to_ruid
-        ruid_to_location = self.__ruid_to_location
+        location_to_hubid = self.__location_to_hubid
+        hubid_to_location = self.__hubid_to_location
         try:
-            ruid = location_to_ruid[canonical_location]
+            hubid = location_to_hubid[canonical_location]
         except KeyError:
             # we don't know about this location, so we
             # just return None 
             return 
         else:
-            del ruid_to_location[ruid]
-            del location_to_ruid[canonical_location]
+            del hubid_to_location[hubid]
+            del location_to_hubid[canonical_location]
             # send out IObjectUnregisteredHubEvent to plugins
             event = ObjectUnregisteredHubEvent(
                 self, 
-                ruid,
+                hubid,
                 canonical_location)
-            self.__eventchannel.notify(event)
-            return ruid
+            self._notify(event)
+            return hubid
 
-    def _objectRemoved(self, canonical_location, ruid, obj):
+    def _objectRemoved(self, canonical_location, hubid, obj):
         # send out IObjectRemovedHubEvent to plugins
         event = ObjectRemovedHubEvent(
             obj,
-            ruid,
+            hubid,
             canonical_location)
-        self.__eventchannel.notify(event)
+        self._notify(event)
+        
+        # we would delete the registration first, but it's not safe
+        # for the global version--see HubEvent.ObjectUnregisteredHubEvent
+        del self.__hubid_to_location[hubid]
+        del self.__location_to_hubid[canonical_location]