[Zope3-checkins] CVS: Zope3/lib/python/Zope/App/OFS/Services/ObjectHub - IObjectHub.py:1.3 ObjectHub.py:1.3

Steve Alexander steve@cat-box.net
Tue, 26 Nov 2002 14:02:49 -0500


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

Modified Files:
	IObjectHub.py ObjectHub.py 
Log Message:
Added a method to IObjectHub for querying the registrations.
Changed the implementatation and the contract so that locations are
canonical as tuples of unicodes rather than as unicodes.



=== Zope3/lib/python/Zope/App/OFS/Services/ObjectHub/IObjectHub.py 1.2 => 1.3 ===
--- Zope3/lib/python/Zope/App/OFS/Services/ObjectHub/IObjectHub.py:1.2	Mon Nov 11 03:35:28 2002
+++ Zope3/lib/python/Zope/App/OFS/Services/ObjectHub/IObjectHub.py	Tue Nov 26 14:02:49 2002
@@ -100,18 +100,20 @@
         """Returns the hub id int that is mapped to the given location
         or wrapped object.
         
-        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 '/',
-        and if it is a sequence, it must start with an empty string.
+        Location is either a unicode, or a tuple of unicodes, or an
+        ascii string, or a tuple of ascii strings.
+        (See Zope/App/Traversing/__init__.py)
+        It must be absolute, so if it is a string it must start with a u'/',
+        and if it is a tuple, it must start with an empty string.
         
-        ('','whatever','whatever2')
-        '/whatever/whatever2'
+        (u'',u'whatever',u'whatever2')
+        u'/whatever/whatever2'
         
         If there is no hub id, raise Zope.Exceptions.NotFoundError.
         """
         
     def getLocation(hubid):
-        """Returns a location as a string.
+        """Returns a location as a tuple of unicodes.
         
         If there is no location, raise Zope.Exceptions.NotFoundError.
         """
@@ -138,4 +140,16 @@
         It also emits a HubIdObjectUnregisteredEvent. 
         If the hub id or location wasn't registered a 
         Zope.Exceptions.NotFoundError is raised.
-        """ 
+        """
+
+    def numRegistrations():
+        """Returns the number of location<-->hubid registrations held.
+        """
+
+    def registrations(location='/'):
+        """Returns a sequence of the registrations at and within the
+        given location.
+
+        A registration a tuple (location, hib_id).
+        """
+


=== Zope3/lib/python/Zope/App/OFS/Services/ObjectHub/ObjectHub.py 1.2 => 1.3 ===
--- Zope3/lib/python/Zope/App/OFS/Services/ObjectHub/ObjectHub.py:1.2	Mon Nov 11 03:35:28 2002
+++ Zope3/lib/python/Zope/App/OFS/Services/ObjectHub/ObjectHub.py	Tue Nov 26 14:02:49 2002
@@ -38,8 +38,8 @@
 from Zope.ContextWrapper import ContextMethod
 from Zope.Proxy.ContextWrapper import isWrapper
 from Zope.App.Traversing.ITraverser import ITraverser
-from Zope.App.Traversing import getPhysicalPathString
-from Zope.App.Traversing import locationAsUnicode
+from Zope.App.Traversing import getPhysicalPath
+from Zope.App.Traversing import locationAsTuple, locationAsUnicode
 from Zope.Proxy.ProxyIntrospection import removeAllProxies
 from Zope.Proxy.ContextWrapper import ContextWrapper
 from Zope.ComponentArchitecture import getAdapter
@@ -67,7 +67,9 @@
 
     def __init__(self):
         ProtoServiceEventChannel.__init__(self)
+        # int --> tuple of unicodes
         self.__hubid_to_location = IOBTree()
+        # tuple of unicodes --> int
         self.__location_to_hubid = OIBTree()
     
     # XXX this is copied because of some context method problems
@@ -92,17 +94,17 @@
             # generate NotificationHubEvents only if object is known
             # ie registered
             if IObjectMovedEvent.isImplementedBy(event):
-                canonical_location = locationAsUnicode(event.fromLocation)
-                hubid = clean_self._lookupHubId(canonical_location)
+                canonical_location = locationAsTuple(event.fromLocation)
+                hubid = clean_self.__location_to_hubid.get(canonical_location)
                 if hubid is not None:
-                    canonical_new_location = locationAsUnicode(
+                    canonical_new_location = locationAsTuple(
                         event.location)
                     location_to_hubid = clean_self.__location_to_hubid
                     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)
+                            % locationAsUnicode(canonical_new_location))
                     hubid = location_to_hubid[canonical_location]
                     del location_to_hubid[canonical_location]
                     location_to_hubid[canonical_new_location] = hubid
@@ -117,8 +119,8 @@
                         event.object)
                     clean_self._notify(wrapped_self, event)
             else: 
-                canonical_location = locationAsUnicode(event.location)
-                hubid = clean_self._lookupHubId(canonical_location)
+                canonical_location = locationAsTuple(event.location)
+                hubid = clean_self.__location_to_hubid.get(canonical_location)
                 if hubid is not None:
                     if IObjectModifiedEvent.isImplementedBy(event):
                         # send out IObjectModifiedHubEvent to plugins
@@ -138,14 +140,15 @@
                             canonical_location,
                             event.object)
                         clean_self._notify(wrapped_self, event)
-    
     notify = ContextMethod(notify)
 
     def getHubId(self, location):
         '''See interface ILocalObjectHub'''
         if isWrapper(location):
-            location = getPhysicalPathString(location)
-        hubid = self._lookupHubId(location)
+            location = getPhysicalPath(location)
+        else:
+            location = locationAsTuple(location)
+        hubid = self.__location_to_hubid.get(location)
         if hubid is None:
             raise NotFoundError(locationAsUnicode(location))
         else:
@@ -170,17 +173,25 @@
         clean_self = removeAllProxies(wrapped_self)
         if isWrapper(location):
             obj = location
-            location = getPhysicalPathString(location)
+            location = getPhysicalPath(location)
         else:
             obj = None
-        canonical_location = locationAsUnicode(location)
-        if not location.startswith(u'/'):
+        canonical_location = locationAsTuple(location)
+        if not canonical_location[0] == u'':
             raise ValueError("Location must be absolute")
+
+        # This is here to make sure the 'registrations' method won't
+        # trip up on using unichar ffff as a sentinel.
+        for segment in canonical_location:
+            if segment.startswith(u'\uffff'):
+                raise ValueError(
+                    "Location contains a segment starting with \\uffff")
+
         location_to_hubid = clean_self.__location_to_hubid
         if location_to_hubid.has_key(canonical_location):
             raise ObjectHubError(
                 'location %s already in object hub' % 
-                canonical_location)
+                locationAsUnicode(canonical_location))
         hubid = clean_self._generateHubId(canonical_location)
         location_to_hubid[canonical_location] = hubid
 
@@ -198,18 +209,18 @@
         '''See interface ILocalObjectHub'''
         clean_self = removeAllProxies(wrapped_self)
         if isWrapper(location):
-            location = getPhysicalPathString(location)
+            location = getPhysicalPath(location)
         elif isinstance(location, int):
             canonical_location = clean_self.getLocation(location)
         else:
-            canonical_location = locationAsUnicode(location)
+            canonical_location = locationAsTuple(location)
         location_to_hubid = clean_self.__location_to_hubid
         hubid_to_location = clean_self.__hubid_to_location
         try:
             hubid = location_to_hubid[canonical_location]
         except KeyError:
             raise NotFoundError('location %s is not in object hub' % 
-                canonical_location)
+                locationAsUnicode(canonical_location))
         else:
             del hubid_to_location[hubid]
             del location_to_hubid[canonical_location]
@@ -221,7 +232,31 @@
                 canonical_location)
             clean_self._notify(wrapped_self, event)
     unregister = ContextMethod(unregister)
-    
+   
+    def numRegistrations(self):
+        """See interface IObjectHub"""
+        # The hubid<-->location mappings should be the same size.
+        # The IOBTree of hubid-->location might be faster to find the
+        # size of, as the keys are ints. But, I haven't tested that.
+        # assert len(self.__hubid_to_location)==len(self.__location_to_hubid)
+        return len(self.__hubid_to_location)
+
+    def registrations(self, location=(u'',)):
+        """See interface IObjectHub"""
+        # Location can be an ascii string a unicode or a tuple of strings
+        # or unicodes. So, get a canonical location first of all.
+        location = locationAsTuple(location)
+        if location == (u'',):
+            # Optimisation when we're asked for all the registered objects.
+            # Returns an IOBTreeItems object.
+            return self.__location_to_hubid.items()
+        
+        # BTrees only support searches including the min and max.
+        # So, I need to add to the end of the location a string that will
+        # be larger than any other. I could also use a type that
+        # sorts after unicodes.
+        return self.__location_to_hubid.items(location, location+(u'\uffff',))
+
     ############################################################
 
     def _generateHubId(self, location):
@@ -234,6 +269,3 @@
         self._v_nextid = index + 1
         return index
 
-    def _lookupHubId(self, location):
-        canonical_location = locationAsUnicode(location) 
-        return self.__location_to_hubid.get(canonical_location, None)