[Zope3-checkins] CVS: Zope3/src/zope/interface - _zope_interface_coptimizations.c:1.3 declarations.py:1.19

Jim Fulton jim at zope.com
Wed Jan 21 16:58:48 EST 2004


Update of /cvs-repository/Zope3/src/zope/interface
In directory cvs.zope.org:/tmp/cvs-serv21701/src/zope/interface

Modified Files:
	_zope_interface_coptimizations.c declarations.py 
Log Message:
Changed the way providedBy worked to fix a bug in handling old-style
extension classes.

Note that the test is actually in Packages3/Interfaces, the facade
that emulated Z2 interfaces using Z3 interfaces. It was easier
to write the test there, because I could actually write it using
extension class. :) My attempts at simulating EC failed and are too
hard to understand, at least today.


=== Zope3/src/zope/interface/_zope_interface_coptimizations.c 1.2 => 1.3 ===
--- Zope3/src/zope/interface/_zope_interface_coptimizations.c:1.2	Fri Nov 21 12:11:43 2003
+++ Zope3/src/zope/interface/_zope_interface_coptimizations.c	Wed Jan 21 16:58:47 2004
@@ -169,23 +169,68 @@
 static PyObject *
 providedBy(PyObject *ignored, PyObject *ob)
 {
-  PyObject *result;
+  PyObject *result, *cls, *cp;
   
   result = PyObject_GetAttr(ob, str__providedBy__);
-  if (result != NULL)
+  if (result == NULL)
     {
-      /* We want to make sure we have a spec. We can't do a type check
-         because we may have a proxy, so we'll just try to get the
-         only attribute.
+      PyErr_Clear();
+      return getObjectSpecification(NULL, ob);
+    } 
+
+  
+  /* We want to make sure we have a spec. We can't do a type check
+     because we may have a proxy, so we'll just try to get the
+     only attribute.
+  */
+  if (PyObject_HasAttr(result, strextends))
+    return result;
+    
+  /*
+    The object's class doesn't understand descriptors.
+    Sigh. We need to get an object descriptor, but we have to be
+    careful.  We want to use the instance's __provides__,l if
+    there is one, but only if it didn't come from the class.
+  */
+  Py_DECREF(result);
+
+  cls = PyObject_GetAttr(ob, str__class__);
+  if (cls == NULL)
+    return NULL;
+
+  result = PyObject_GetAttr(ob, str__provides__);
+  if (result == NULL)
+    {      
+      /* No __provides__, so just fall back to implementedBy */
+      PyErr_Clear();
+      result = implementedBy(NULL, cls);
+      Py_DECREF(cls);
+      return result;
+    } 
+
+  cp = PyObject_GetAttr(cls, str__provides__);
+  if (cp == NULL)
+    {
+      /* The the class has no provides, assume we're done: */
+      PyErr_Clear();
+      Py_DECREF(cls);
+      return result;
+    }
+
+  if (cp == result)
+    {
+      /*
+        Oops, we got the provides from the class. This means
+        the object doesn't have it's own. We should use implementedBy
       */
-      if (PyObject_HasAttr(result, strextends))
-        return result;
       Py_DECREF(result);
+      result = implementedBy(NULL, cls);
     }
 
-  PyErr_Clear();
+  Py_DECREF(cls);
+  Py_DECREF(cp);
 
-  return getObjectSpecification(NULL, ob);
+  return result;
 }
 
 static PyObject *


=== Zope3/src/zope/interface/declarations.py 1.18 => 1.19 ===
--- Zope3/src/zope/interface/declarations.py:1.18	Fri Nov 21 12:11:43 2003
+++ Zope3/src/zope/interface/declarations.py	Wed Jan 21 16:58:47 2004
@@ -1138,9 +1138,15 @@
     # Here we have either a special object, an old-style declaration
     # or a descriptor
 
+    # Try to get __providedBy__
     try:
         r = ob.__providedBy__
+    except AttributeError:
+        # Not set yet. Fall back to lower-level thing that computes it
+        return getObjectSpecification(ob)
+    
 
+    try:
         # We might have gotten a descriptor from an instance of a
         # class (like an ExtensionClass) that doesn't support
         # descriptors.  We'll make sure we got one by trying to get
@@ -1148,8 +1154,33 @@
         r.extends
 
     except AttributeError:
-        # No descriptor, so fall back to a plain object spec
-        r = getObjectSpecification(ob)
+
+        # The object's class doesn't understand descriptors.
+        # Sigh. We need to get an object descriptor, but we have to be
+        # careful.  We want to use the instance's __provides__,l if
+        # there is one, but only if it didn't come from the class.
+
+        try:
+            r = ob.__provides__
+        except AttributeError:
+            # No __provides__, so just fall back to implementedBy
+            return implementedBy(ob.__class__)
+
+        # We need to make sure we got the __provides__ from the
+        # instance. We'll do this by making sure we don't get the same
+        # thing from the class:
+
+        try:
+            cp = ob.__class__.__provides__
+        except AttributeError:
+            # The ob doesn't have a class or the class has no
+            # provides, assume we're done:
+            return r
+
+        if r is cp:
+            # Oops, we got the provides from the class. This means
+            # the object doesn't have it's own. We should use implementedBy
+            return implementedBy(ob.__class__)
 
     return r
 




More information about the Zope3-Checkins mailing list