[Zope3-checkins] SVN: Zope3/branches/jim-adapter-alt1/src/zope/interface/adapter.py Moved subscribers to new strategy.

Jim Fulton jim at zope.com
Sun Jan 29 17:58:30 EST 2006


Log message for revision 41487:
  Moved subscribers to new strategy.
  

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

-=-
Modified: Zope3/branches/jim-adapter-alt1/src/zope/interface/adapter.py
===================================================================
--- Zope3/branches/jim-adapter-alt1/src/zope/interface/adapter.py	2006-01-29 20:37:55 UTC (rev 41486)
+++ Zope3/branches/jim-adapter-alt1/src/zope/interface/adapter.py	2006-01-29 22:58:29 UTC (rev 41487)
@@ -33,16 +33,16 @@
     
 
 _delegated = ('lookup', 'queryMultiAdapter', 'lookup1', 'queryAdapter',
-              'adapter_hook', 'lookupAll', 'names')
+              'adapter_hook', 'lookupAll', 'names',
+              'subscriptions', 'subscribers')
 
 _marker = object
 class AdapterRegistry(object):
 
     def __init__(self, bases=()):
         self._adapters = []
+        self._subscribers = []
         self._provided = {}
-        self._unnamed_subscriptions = []
-        self._named_subscriptions = {}
         self._init_non_persistent()
         self.__bases__ = bases
 
@@ -185,89 +185,63 @@
 
 
     def subscribe(self, required, provided, value):
-
-# XXX when we are ready to support named subscribers, we'll add a name
-# argument and uncomment the following.
-##         if name:
-##             name = _normalize_name(name)
-##             byorder = self._named_subscriptions.get(name)
-##             if byorder is None:
-##                 self._named_subscriptions[name] = byorder = []
-##         else:
-##             byorder = self._unnamed_subscriptions
-
-        byorder = self._unnamed_subscriptions
-
+        required = tuple(map(_convert_None_to_Interface, required))
+        name = u''
         order = len(required)
+        byorder = self._subscribers
         while len(byorder) <= order:
-            byorder.append(Subscriptions())
-
+            byorder.append({})
         components = byorder[order]
-        components.register(required, provided, value)
+        key = required + (provided,)
+        
+        for k in key:
+            d = components.get(k)
+            if d is None:
+                d = {}
+                components[k] = d
+            components = d
 
-    def unsubscribe(self, required, provided, value):
+        components[name] = components.get(name, ()) + (value, )
 
-# XXX when we are ready to support named subscribers, we'll add a name
-# argument and uncomment the following.
-##         if name:
-##             name = _normalize_name(name)
-##             byorder = self._named_subscriptions.get(name)
-##             if byorder is None:
-##                 self._named_subscriptions[name] = byorder = []
-##         else:
-##             byorder = self._unnamed_subscriptions
+        if provided is not None:
+            n = self._provided.get(provided, 0) + 1
+            self._provided[provided] = n
+            if n == 1 and '_v_extendors' in self.__dict__:
+                del self.__dict__['_v_extendors']
 
-        byorder = self._unnamed_subscriptions
+        self.changed()
 
+    def unsubscribe(self, required, provided, value):
+        required = tuple(map(_convert_None_to_Interface, required))
         order = len(required)
-        if len(byorder) <= order:
-            return
-
+        byorder = self._subscribers
+        if order >= len(byorder):
+            return False
         components = byorder[order]
-        components.unregister(required, provided, value)
+        key = required + (provided,)
+        
+        for k in key:
+            d = components.get(k)
+            if d is None:
+                return
+            components = d
 
-    def subscriptions(self, required, provided, name=u''):
-        result = []
-        # XXX should we traverse ro in reverse?
-        for self in self.ro:
-            if name:
-                byorder = self._named_subscriptions.get(name)
-                if byorder is None:
-                    continue
-            else:
-                byorder = self._unnamed_subscriptions
+        components[u''] = tuple([
+            v for v in components.get(u'', ())
+            if v != value
+            ])
 
-            order = len(required)
-            if order >= len(byorder):
-                continue
-            
-            subscriptions(byorder[order].components, required, provided,
-                          result)
+        if provided is not None:
+            n = self._provided[provided] - 1
+            if n == 0:
+                del self._provided[provided]
+                if '_v_extendors' in self.__dict__:
+                    del self.__dict__['_v_extendors']
 
-        return result
+        self.changed()
 
-    def subscribers(self, objects, provided, name=u''):
-        if provided is None:
-            result = ()
-        else:
-            result = []
-            
-        for self in self.ro:
-            if name:
-                byorder = self._named_subscriptions.get(name)
-                if byorder is None:
-                    continue
-            else:
-                byorder = self._unnamed_subscriptions
+        return
 
-            order = len(objects)
-            if order >= len(byorder):
-                continue
-
-            subscribers(byorder[order].components, objects, provided, result)
-
-        return result
-
     # 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.
@@ -286,11 +260,13 @@
         self._registry = registry
         self._cache = {}
         self._mcache = {}
+        self._scache = {}
         self._required = {}
 
     def changed(self):
         self._cache.clear()
         self._mcache.clear()
+        self._scache.clear()
         for r in self._required.keys():
             r = r()
             if r is not None:
@@ -389,7 +365,6 @@
         required = tuple(required)
         result = cache.get(required, _not_in_mapping)
         if result is _not_in_mapping:
-
             order = len(required)
             result = {}
             for registry in reversed(self._registry.ro):
@@ -410,11 +385,47 @@
     def names(self, required, provided):
         return [c[0] for c in self.lookupAll(required, provided)]
 
+    def subscriptions(self, required, provided):
+        cache = self._scache.get(provided)
+        if cache is None:
+            cache = {}
+            self._scache[provided] = cache
 
+        required = tuple(required)
+        result = cache.get(required, _not_in_mapping)
+        if result is _not_in_mapping:
+            order = len(required)
+            result = []
+            for registry in reversed(self._registry.ro):
+                byorder = registry._subscribers
+                if order >= len(byorder):
+                    continue
 
+                if provided is None:
+                    extendors = (provided, )
+                else:
+                    extendors = registry._v_extendors.get(provided)
+                    if extendors is None:
+                        continue
 
+                _subscriptions(byorder[order], required, extendors, u'',
+                               result, 0, order)
 
+        return result
 
+    def subscribers(self, objects, provided):
+        subscriptions = self.subscriptions(map(providedBy, objects), provided)
+        if provided is None:
+            result = ()
+            for subscription in subscriptions:
+                subscription(*objects)
+        else:
+            result = []
+            for subscription in subscriptions:
+                subscriber = subscription(*objects)
+                if subscriber is not None:
+                    result.append(subscriber)
+        return result
     
 def _convert_None_to_Interface(x):
     if x is None:
@@ -428,123 +439,6 @@
 
     raise TypeError("name must be a regular or unicode string")
 
-        
-class Next:
-
-    def __init__(self, spec, basis):
-        sro = spec.__sro__
-        self.__sro__ = sro[sro.index(basis)+1:]
-
-
-class Adapters(object):
-
-    def __init__(self):
-        self.components = {}
-        self.provided = {} # {iface -> (iro, [(required, value)])}
-
-    def register(self, required, provided, value):
-        if (provided is None) or (provided is Interface):
-            self._register(required, provided, provided, value)
-        else:
-            registered = self.provided.get(provided)
-            if registered is None:
-                self.provided[provided] = registered = provided.__iro__, []
-                # XXX where is changed?  Where is unsubscribe on unregister?
-                provided.subscribe(self)
-            registered[1].append((required, value))
-
-            for p in provided.__iro__:
-                self._register(required, provided, p, value)
-
-    def _register(self, required, provided, p, value):
-        d = self.components
-        k = p
-        for r in required:
-            if r is None:
-                r = Interface
-            v = d.get(k)
-            if v is None:
-                d[k] = v = {}
-            d = v
-            k = r
-
-        components = d.get(k, ())
-        d[k] = self._add(components, provided, value)
-
-    def _add(self, components, provided, value):
-        if provided is None:
-            return components + ((value, provided), )
-        
-        return (
-            tuple([c for c in components if provided.extends(c[1])])
-            +
-            ((value, provided), )
-            +
-            tuple([c for c in components if not provided.extends(c[1])])
-            )
-        
-    def unregister(self, required, provided, value):
-        if (provided is None) or (provided is Interface):
-            self._unregister(required, provided, provided, value)
-        else:
-            registered = self.provided.get(provided)
-            if registered is None:
-                return
-            if value is None:
-                rv = [r for r in registered[1] if r[0] != required]
-            else:
-                rv = [r for r in registered[1] if r != (required, value)]
-
-            if rv:
-                self.provided[provided] = registered[0], rv
-            else:
-                del self.provided[provided]
-
-            for p in provided.__iro__:
-                self._unregister(required, provided, p, value)
-
-    def _unregister(self, required, provided, p, value):
-        items = []
-        d = self.components
-        k = p
-        for r in required:
-            if r is None:
-                r = Interface
-            v = d.get(k)
-            if v is None:
-                return
-            items.append((d, k))
-            d = v
-            k = r
-
-        components = d.get(k, None)
-        if components is None:
-            return
-
-        if value is None:
-            # unregister all
-            components = [c for c in components
-                          if c[1] != provided]
-        else:
-            # unregister just this one
-            components = [c for c in components
-                          if c != (value, provided)]
-
-        if components:
-            d[k] = tuple(components)
-        else:
-            del d[k]
-
-            items.reverse()
-            for d, k in items:
-                if not d[k]:
-                    del d[k]
-
-class Subscriptions(Adapters):
-
-    def _add(self, components, provided, value):
-        return components + ((value, provided), )
-
 def _lookup(components, specs, provided, name, i, l):
     if i < l:
         for spec in specs[i].__sro__:
@@ -568,47 +462,23 @@
         for spec in reversed(specs[i].__sro__):
             comps = components.get(spec)
             if comps:
-                r = _lookupAll(comps, specs, provided, result, i+1, l)
-                if r is not None:
-                    return r
+                _lookupAll(comps, specs, provided, result, i+1, l)
     else:
         for iface in reversed(provided):
             comps = components.get(iface)
             if comps:
                 result.update(comps)
 
-
-
-
-
-def _subscribers(components, specs, i, l, objects, result):
+def _subscriptions(components, specs, provided, name, result, i, l):
     if i < l:
-        sro = list(specs[i].__sro__)
-        sro.reverse()
-        for spec in sro:
+        for spec in reversed(specs[i].__sro__):
             comps = components.get(spec)
-            if comps is not None:
-                _subscribers(comps, specs, i+1, l, objects, result)
+            if comps:
+                _subscriptions(comps, specs, provided, name, result, i+1, l)
     else:
-        if objects is None:
-            result.extend([c[0] for c in components])
-        else:
-            for c in components:
-                c = c[0](*objects)
-                if c is not None and result is not None:
-                    result.append(c)
-
-def subscriptions(components, required, provided, result):
-    components = components.get(provided)
-    if components:
-        _subscribers(components, required, 0, len(required), None, result)
-
-def subscribers(components, objects, provided, result):
-    components = components.get(provided)
-    if components:
-        required = map(providedBy, objects)
-
-        if provided is None:
-            result == None
-
-        _subscribers(components, required, 0, len(required), objects, result)
+        for iface in reversed(provided):
+            comps = components.get(iface)
+            if comps:
+                comps = comps.get(name)
+                if comps:
+                    result.extend(comps)



More information about the Zope3-Checkins mailing list