[Zodb-checkins] CVS: Releases/Zope/lib/Components/ExtensionClass/src - ExtensionClass.c:1.47

Matthew T. Kromer matt@zope.com
Thu, 4 Oct 2001 10:09:39 -0400


Update of /cvs-repository/Releases/Zope/lib/Components/ExtensionClass/src
In directory cvs.zope.org:/tmp/cvs-serv30768

Modified Files:
	ExtensionClass.c 
Log Message:
Jim's changes to Extension Class -- Several PyObject_GetItem requests now check
if the object is a dictionary, and do a PyDict_GetItem instead if possible.
This avoids the error machinery overhead if the key is not found in the
dictionary.  PyDict_GetItem returns a borrowed reference, so the refcount
is also bumped in these cases.


=== Releases/Zope/lib/Components/ExtensionClass/src/ExtensionClass.c 1.46 => 1.47 ===
     {
       r= INSTANCE_DICT(inst);
-      if ((r = PyObject_GetItem(r,oname)) && NeedsToBeBound(r))
-	{
-	  ASSIGN(r, CallMethodO(r, py__of__, Build("(O)", inst), NULL));
-	  UNLESS(r) return NULL;
-	}
-    }
-  UNLESS(r)
-    {
-      if (*name=='_' && name[1]=='_' 
-          && 
-          (   (name[2]=='b' && strcmp(name+2,"bases__")==0) 
-           || (name[2]=='d' && strcmp(name+2,"dict__")==0)
-              )
+      if (PyDict_Check(r))
+        {
+          r = PyDict_GetItem(r,oname);
+          Py_XINCREF(r);
+        }
+      else
+        {
+          UNLESS (r = PyObject_GetItem(r,oname))
+            PyErr_Clear();
+        }
+
+      if (r)
+        {
+          if (NeedsToBeBound(r))
+            {
+              ASSIGN(r, CallMethodO(r, py__of__, Build("(O)", inst), NULL));
+            }
+          return r;
+        }
+    }
+
+  if (*name=='_' && name[1]=='_' 
+      && 
+      (   (name[2]=='b' && strcmp(name+2,"bases__")==0) 
+          || (name[2]=='d' && strcmp(name+2,"dict__")==0)
           )
-	{
-	  PyErr_SetObject(PyExc_AttributeError, oname);
-	  return NULL;
-	}
-
-      PyErr_Clear();
-
-      UNLESS(r=CCL_getattr(self,oname,0)) return NULL;
-
-      /* We got something from our class, maybe its an unbound method. */
-      if (UnboundCMethod_Check(r))
-	ASSIGN(r,(PyObject*)bindCMethod((CMethod*)r,inst));
-      else if (UnboundPMethod_Check(r))
-	ASSIGN(r,bindPMethod((PMethod*)r,inst));
+      )
+    {
+      PyErr_SetObject(PyExc_AttributeError, oname);
+      return NULL;
     }
+  
+  UNLESS(r=CCL_getattr(self,oname,0)) return NULL;
+  
+  /* We got something from our class, maybe its an unbound method. */
+  if (UnboundCMethod_Check(r))
+    ASSIGN(r,(PyObject*)bindCMethod((CMethod*)r,inst));
+  else if (UnboundPMethod_Check(r))
+    ASSIGN(r,bindPMethod((PMethod*)r,inst));
       
   return r;
 }
@@ -1704,44 +1714,67 @@
 subclass_simple_setattr(PyObject *self, char *name, PyObject *v);
 
 static PyObject *
+CCL_getattr2(PyObject *self, PyObject *oname, int look_super)
+{
+  PyObject *r=0, *b, *d;
+
+  if (ExtensionClass_Check(self))
+    {
+      b=((PyExtensionClass*)self)->bases;
+      d=((PyExtensionClass*)self)->class_dictionary;
+    }
+  else if (PyClass_Check(self))
+    {
+      b=((PyClassObject*)self)->cl_bases;
+      d=((PyClassObject*)self)->cl_dict;
+    }
+  else
+    {
+      UNLESS (r=PyObject_GetAttr(self, oname)) PyErr_Clear();
+      return r;
+    }
+
+  if (! look_super && d)
+    {
+      if (PyDict_Check(d))
+        {
+          if((r=PyDict_GetItem(d, oname)))
+            {          
+              Py_INCREF(r);
+              return r;
+            }
+        }
+      else
+        {
+          if((r=PyObject_GetItem(d, oname))) return r;
+          PyErr_Clear();
+        }
+    }
+
+  if (b)
+    {
+      int n, i;
+      
+      n = PyTuple_Check(b) ? PyTuple_GET_SIZE(b) : 0; /* I don't care ;) */
+      for (i=0; i < n; i++)
+        {
+          r=CCL_getattr2(PyTuple_GET_ITEM(b, i), oname, 0);
+          if (r) return r;
+        }
+    }
+
+  return NULL;
+}
+
+static PyObject *
 CCL_getattr(PyExtensionClass *self, PyObject *oname, int look_super)
 {
   PyObject *r=0;
 
-  if (! look_super) r=PyObject_GetItem(self->class_dictionary,oname);
-  UNLESS(r)
+  UNLESS (r=CCL_getattr2(OBJECT(self), oname, look_super)) 
     {
-      if (self->bases)
-	{
-	  int n, i;
-	  PyObject *c;
-	  
-	  n=PyTuple_Size(self->bases);
-	  for (i=0; i < n; i++)
-	    {
-	      PyErr_Clear();
-	      c=PyTuple_GET_ITEM(self->bases, i);
-	      if (ExtensionClass_Check(c))
-		r=CCL_getattr(AsExtensionClass(c),oname,0);
-	      else
-		r=PyObject_GetAttr(c,oname);
-	      if (r) break;
-	    }
-	}
-      UNLESS(r)
-	{
-	  PyObject *t, *v, *tb;
-
-	  PyErr_Fetch(&t,&v,&tb);
-	  if (t==PyExc_KeyError && PyObject_Compare(v,oname) == 0)
-	    {
-	      Py_DECREF(t);
-	      t=PyExc_AttributeError;
-	      Py_INCREF(t);
-	    }
-	  PyErr_Restore(t,v,tb);	  
-	  return NULL;
-	}
+      PyErr_SetObject(PyExc_AttributeError, oname);
+      return NULL;
     }
 
   if (PyFunction_Check(r) || NeedsToBeBound(r))
@@ -1753,6 +1786,21 @@
 }
 
 static PyObject *
+CCL_getattrne(PyExtensionClass *self, PyObject *oname)
+{
+  PyObject *r=0;
+
+  if ((r=CCL_getattr2(OBJECT(self), oname, 0)))
+    {
+      if (PyFunction_Check(r) || NeedsToBeBound(r))
+        ASSIGN(r,newPMethod(self,r));
+      else if (PyMethod_Check(r) && ! PyMethod_Self(r))
+        ASSIGN(r,newPMethod(self, PyMethod_Function(r)));
+    }
+  return r;
+}
+
+static PyObject *
 CCL_reduce(PyExtensionClass *self, PyObject *args)
 {
   return PyString_FromString(self->tp_name);
@@ -2109,14 +2157,24 @@
   if (HasInstDict(inst))
     {
       r= INSTANCE_DICT(inst);
-      r = PyObject_GetItem(r,oname);
-      UNLESS(r)
-	{
-	  PyErr_Clear();
-	  r=CCL_getattr(self,oname,0);
-	}
+      if (PyDict_Check(r))
+        {
+          if ((r = PyDict_GetItem(r,oname)))
+            Py_INCREF(r);
+          else
+            r=CCL_getattr(self,oname,0);
+        }
+      else
+        {
+          UNLESS (r = PyObject_GetItem(r,oname))
+            {
+              PyErr_Clear();
+              r=CCL_getattr(self,oname,0);
+            }
+        }
     }
-  else r=CCL_getattr(self,oname,0);
+  else 
+    r=CCL_getattr(self,oname,0);
   
   return r;
 }