[Zope-Checkins] CVS: Zope3/lib/python/Zope/ComponentArchitecture - IToIRegistry.py:1.3

Jim Fulton jim@zope.com
Tue, 11 Jun 2002 19:10:45 -0400


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

Modified Files:
	IToIRegistry.py 
Log Message:
Fixed a bug in IToIRegistry that caused incorrent components to be
looked up.  

For example:

  Component 1 is registered for Interface (i.e. default)

  Component 2 is registered for I2.

  No component is registered for I3.

  An object implements I3, I2, in that order.

  When looking up an adapter or view, the default component, Componet
  1, would be found, rather than the more specific component,
  Component 2.



=== Zope3/lib/python/Zope/ComponentArchitecture/IToIRegistry.py 1.2 => 1.3 ===
         Returns None if not found.
         """
-        c = self._find(ob_interface, provide)
+        get = self._reg.get
+
+        if ob_interface is not None:
+        
+            for interface in _flatten(ob_interface):
+                c = get((interface, provide))
+                if c is not None:
+                    return c[1]
+            
+        c = get((None, provide))
         if c is not None:
             return c[1]
-        bases = getattr(ob_interface, '__bases__', ())
-        if bases:
-            # 'require' might be a subinterface of a required interface
-            # for a registered component.
-            for base in bases:
-                c = self.get(base, provide)
-                if c is not None:
-                    return c
-        return None
 
+        return c 
 
     def getDefinitions(self, used_for=None, provide=None):
         if used_for is not None:
@@ -155,10 +156,7 @@
         return result
 
     def getForObject(self, ob, provided):
-        for i in objectImplements(removeAllProxies(ob)):
-            c=self.get(i, provided)
-            if c is not None: return c
-        return self.get(None, provided)
+        return self.get(getattr(ob, '__implements__', None), provided)
 
     def getAllForObject(self, ob, provided):
         """Get all components that match an object's interfaces
@@ -242,3 +240,38 @@
         """
         r = self._find(interface, None)
         return r and r[1]
+
+
+    
+def _flatten_recurse_interface(interface, list):
+    list.append(interface)
+    for i in interface.__bases__:
+        _flatten_recurse_interface(i, list)
+        
+def _flatten_recurse(implements, list):
+    if implements.__class__ == tuple:
+        for i in implements:
+            _flatten_recurse(i, list)
+    else:
+        _flatten_recurse_interface(implements, list)
+
+def _flatten(implements):
+    """Flatten an implements spec to a list of interfaces
+
+    The list includes all base interfaces of the interface(s) in
+    implements. Each interface is listed only once and more
+    specific interfaces are listed before less specific
+    interfaces. This is similar to Python 2.2's MRO.
+    """
+    interfaces = []
+    _flatten_recurse(implements, interfaces)
+    interfaces.reverse()
+    seen = {}
+    flattened = []
+    for interface in interfaces:
+        if interface not in seen:
+            seen[interface] = 1
+            flattened.append(interface)
+    flattened.reverse()
+
+    return flattened