[Zope3-checkins] SVN: Zope3/branches/jim-adapter/src/zope/interface/adapter. Committed to subscription-result order.

Jim Fulton jim at zope.com
Wed Apr 26 19:44:19 EDT 2006


Log message for revision 67629:
  Committed to subscription-result order.
  
  Added unsubscription tests.  Fixed a bug in unsubscription without a
  value.
  

Changed:
  U   Zope3/branches/jim-adapter/src/zope/interface/adapter.py
  U   Zope3/branches/jim-adapter/src/zope/interface/adapter.txt

-=-
Modified: Zope3/branches/jim-adapter/src/zope/interface/adapter.py
===================================================================
--- Zope3/branches/jim-adapter/src/zope/interface/adapter.py	2006-04-26 22:28:30 UTC (rev 67628)
+++ Zope3/branches/jim-adapter/src/zope/interface/adapter.py	2006-04-26 23:44:19 UTC (rev 67629)
@@ -150,7 +150,26 @@
             del self.__dict__['_v_extendors']
 
         self.changed(self)
+
+    def registered(self, required, provided, name=u''):
+        required = tuple(map(_convert_None_to_Interface, required))
+        name = _normalize_name(name)
+        order = len(required)
+        byorder = self._adapters
+        if len(byorder) <= order:
+            return None
+
+        components = byorder[order]
+        key = required + (provided,)
         
+        for k in key:
+            d = components.get(k)
+            if d is None:
+                return None
+            components = d
+
+        return components.get(name)
+        
     def unregister(self, required, provided, name, value=None):
         required = tuple(map(_convert_None_to_Interface, required))
         order = len(required)
@@ -218,7 +237,7 @@
         order = len(required)
         byorder = self._subscribers
         if order >= len(byorder):
-            return False
+            return
         components = byorder[order]
         key = required + (provided,)
         
@@ -228,13 +247,22 @@
                 return
             components = d
 
-        components[u''] = tuple([
-            v for v in components.get(u'', ())
-            if (v != value) or (value is None)
-            ])
+        old = components.get(u'')
+        if not old:
+            return
 
+        if value is None:
+            new = ()
+        else:
+            new = tuple([v for v in old if v != value])
+
+        if new == old:
+            return
+        
+        components[u''] = new
+
         if provided is not None:
-            n = self._provided[provided] - 1
+            n = self._provided[provided] + len(new) - len(old)
             if n == 0:
                 del self._provided[provided]
                 if '_v_extendors' in self.__dict__:
@@ -242,11 +270,8 @@
 
         self.changed(self)
 
-        return
-
-    # XXX hack to fake out twisted's use of a private api.  We'll need
-    # to add a public api to mean twisted's needs and get them to use
-    # it.
+    # XXX hack to fake out twisted's use of a private api.  We need to get them
+    # to use the new registed method.
     def get(self, _):
         class XXXTwistedFakeOut:
             selfImplied = {}

Modified: Zope3/branches/jim-adapter/src/zope/interface/adapter.txt
===================================================================
--- Zope3/branches/jim-adapter/src/zope/interface/adapter.txt	2006-04-26 22:28:30 UTC (rev 67628)
+++ Zope3/branches/jim-adapter/src/zope/interface/adapter.txt	2006-04-26 23:44:19 UTC (rev 67629)
@@ -115,6 +115,32 @@
   >>> registry.lookup([IR2], IP1, '')
   21
 
+Finding out what, if anything, is registered
+--------------------------------------------
+
+We can ask if there is an adapter registered for a collection of
+interfaces. This is different than lookup, because it looks for an
+exact match.
+
+  >>> print registry.registered([IR1], IP1)
+  11
+
+  >>> print registry.registered([IR1], IP2)
+  12
+
+  >>> print registry.registered([IR1], IP2, 'bob')
+  Bob's 12
+  
+
+  >>> print registry.registered([IR2], IP1)
+  21
+
+  >>> print registry.registered([IR2], IP2)
+  None
+
+In the last example, None was returned because nothing was registered
+exactly for the given interfaces.
+
 lookup1
 -------
 
@@ -382,11 +408,6 @@
 Subscriptions
 =============
 
-XXX need tests that demonstrate that more general subscribers are
-    called before more specific subscribers
-
-XXX Need unscription tests
-
 Normally, we want to look up an object that most-closely matches a
 specification.  Sometimes, we want to get all of the objects that
 match some specification.  We use subscriptions for this.  We
@@ -399,43 +420,36 @@
 
 Note that, unlike regular adapters, subscriptions are unnamed.
 
-The order of returned subscriptions is not specified.
-
 You can have multiple subscribers for the same specification::
 
   >>> registry.subscribe([IR1], IP2, 'sub12 2')
-  >>> subs = registry.subscriptions([IR1], IP2)
-  >>> subs.sort()
-  >>> subs
+  >>> registry.subscriptions([IR1], IP2)
   ['sub12 1', 'sub12 2']
 
+If subscribers are registered for the same required interfaces, they
+are returned in the order of definition.
+
 You can register subscribers for all specifications using None::
 
   >>> registry.subscribe([None], IP1, 'sub_1')
-  >>> subs = registry.subscriptions([IR2], IP1)
-  >>> subs.sort()
-  >>> subs
-  ['sub12 1', 'sub12 2', 'sub_1']
+  >>> registry.subscriptions([IR2], IP1)
+  ['sub_1', 'sub12 1', 'sub12 2']
 
+Note that the new subscriber is returned first.  Subscribers defined
+for more general required interfaces are returned before subscribers
+for more general interfaces.
+
 Subscriptions may be combined over multiple compatible specifications::
 
-  >>> subs = registry.subscriptions([IR2], IP1)
-  >>> subs.sort()
-  >>> subs
-  ['sub12 1', 'sub12 2', 'sub_1']
+  >>> registry.subscriptions([IR2], IP1)
+  ['sub_1', 'sub12 1', 'sub12 2']
   >>> registry.subscribe([IR1], IP1, 'sub11')
-  >>> subs = registry.subscriptions([IR2], IP1)
-  >>> subs.sort()
-  >>> subs
-  ['sub11', 'sub12 1', 'sub12 2', 'sub_1']
+  >>> registry.subscriptions([IR2], IP1)
+  ['sub_1', 'sub12 1', 'sub12 2', 'sub11']
   >>> registry.subscribe([IR2], IP2, 'sub22')
-  >>> subs = registry.subscriptions([IR2], IP1)
-  >>> subs.sort()
-  >>> subs
-  ['sub11', 'sub12 1', 'sub12 2', 'sub22', 'sub_1']
-  >>> subs = registry.subscriptions([IR2], IP2)
-  >>> subs.sort()
-  >>> subs
+  >>> registry.subscriptions([IR2], IP1)
+  ['sub_1', 'sub12 1', 'sub12 2', 'sub11', 'sub22']
+  >>> registry.subscriptions([IR2], IP2)
   ['sub12 1', 'sub12 2', 'sub22']
 
 Subscriptions can be on multiple specifications::
@@ -450,10 +464,8 @@
   >>> registry.subscribe([None, IQ], IP2, 'sub_q2')
   >>> registry.subscriptions([IS, IQ], IP2)
   ['sub_q2']
-  >>> subs = registry.subscriptions([IR1, IQ], IP2)
-  >>> subs.sort()
-  >>> subs
-  ['sub1q2', 'sub_q2']
+  >>> registry.subscriptions([IR1, IQ], IP2)
+  ['sub_q2', 'sub1q2']
 
 You can have subscriptions that are indepenent of any specifications::
   
@@ -464,14 +476,29 @@
   >>> registry.subscriptions([], IP1)
   ['sub2']
   >>> registry.subscribe([], IP1, 'sub1')
-  >>> subs = registry.subscriptions([], IP1)
-  >>> subs.sort()
-  >>> subs
-  ['sub1', 'sub2']
+  >>> registry.subscriptions([], IP1)
+  ['sub2', 'sub1']
   >>> registry.subscriptions([], IP2)
   ['sub2']
 
+Unregistering subscribers
+-------------------------
 
+We can unregister subscribers.  When unregistering a subscriber, we
+can unregister a specific subscriber:
+
+  >>> registry.unsubscribe([IR1], IP1, 'sub11')
+  >>> registry.subscriptions([IR1], IP1)
+  ['sub_1', 'sub12 1', 'sub12 2']
+
+If we don't specify a value, then all subscribers matching the given
+interfaces will be unsubscribed:
+
+  >>> registry.unsubscribe([IR1], IP2)
+  >>> registry.subscriptions([IR1], IP1)
+  ['sub_1']
+
+
 Subscription adapters
 ---------------------
 



More information about the Zope3-Checkins mailing list