[Zope-Checkins] CVS: ZODB3/ZODB - coptimizations.c:1.20.2.1

Jeremy Hylton jeremy@zope.com
Fri, 13 Dec 2002 16:57:05 -0500


Update of /cvs-repository/ZODB3/ZODB
In directory cvs.zope.org:/tmp/cvs-serv25075

Modified Files:
      Tag: ZODB3-3_1-branch
	coptimizations.c 
Log Message:
Sideport changes from Zope 2.6 branch.

Get ZClasses working.  (Tested this time.)
Add some more comments and add XDECREFs to avoid leaks.
Remove redundant check of ExtensionClass in get_class().
Apparent fix for ZClass persistent_id problem.

(Also add comment from ZODB trunk.)


=== ZODB3/ZODB/coptimizations.c 1.20 => 1.20.2.1 ===
--- ZODB3/ZODB/coptimizations.c:1.20	Mon Sep 30 12:02:32 2002
+++ ZODB3/ZODB/coptimizations.c	Fri Dec 13 16:57:05 2002
@@ -69,8 +69,8 @@
 /* Returns the klass of a persistent object.
    Returns NULL for other objects.
 */
-static PyObject *
-get_class(PyObject *object)
+int
+get_class(PyObject *object, PyObject **out_class)
 {
     PyObject *class = NULL;
 
@@ -79,19 +79,23 @@
 	    class = PyObject_GetAttr(object, py___class__);
 	    if (!class) {
 		PyErr_Clear();
-		return NULL;
+		return 0;
 	    }
-	    if (!PyExtensionClass_Check(class) ||
-		!(((PyExtensionClass*)class)->class_flags 
+	    /* The __class__ must be an extension class. */
+	    if (!(((PyExtensionClass*)class)->class_flags 
 		  & PERSISTENT_TYPE_FLAG)) {
 		Py_DECREF(class);
-		return NULL;
+		return 0;
 	    }
 	}
 	else
-	    return NULL;
+	    /* Most objects will exit via this path.  They are neither
+	       extension classes nor instances of them.
+	    */
+	    return 0;
     }
-    return class;
+    *out_class = class;
+    return 1;
 }
 
 /* Return a two-tuple of the class's module and name.
@@ -106,7 +110,7 @@
 	goto err;
     if (!PyObject_IsTrue(module)) {
 	Py_DECREF(module);
-	/* XXX Handle degenerate 1.x ZClass case. */
+	/* If the class has no __module__, it must be a degnerate ZClass. */
 	return oid;
     }
 
@@ -152,24 +156,39 @@
     return NULL;
 }
 
+/* persistent_id_call()
+
+   Returns a reference to a persistent object, appending it to the the
+   persistent_id's list of objects.  If a non-persistent object is
+   found, return None.
+
+   The returned reference can be either class info, oid pair or a
+   plain old oid.  If it is a pair, the class info is the module and
+   the name of the class.  The class info can be used to create a
+   ghost without loading the class.
+
+   For unusual objects, e.g. ZClasses, return just the oid.  An object
+   is unusual if it isn't an ExtensionClass, because that means it
+   doesn't inherit from Persistence, or if it has __getinitargs__().
+*/
+
 static PyObject *
 persistent_id_call(persistent_id *self, PyObject *args, PyObject *kwargs)
 {
-    PyObject *object, *oid, *klass=NULL;
+    PyObject *object, *oid=NULL, *klass=NULL;
     PyObject *t1, *t2;
     int setjar = 0;
 
     if (!PyArg_ParseTuple(args, "O", &object))
 	return NULL;
 
-    klass = get_class(object);
-    if (!klass)
+    /* If it is not an extension class, get the object's class. */
+    if (!get_class(object, &klass))
 	goto return_none;
 
     oid = PyObject_GetAttr(object, py__p_oid);
     if (!oid) {
 	PyErr_Clear();
-	Py_DECREF(klass);
 	goto return_none;
     }
 
@@ -205,7 +224,7 @@
     t2 = get_class_tuple(klass, oid);
     if (!t2)
 	goto err;
-    if (t2 == oid) /* pass through ZClass special case */
+    if (t2 == oid) /* Couldn't find class info, just used oid. */
 	goto return_oid;
     t1 = PyTuple_New(2);
     if (!t1) {
@@ -229,6 +248,8 @@
     return oid;
 
  return_none:
+    Py_XDECREF(oid);
+    Py_XDECREF(klass);
     Py_INCREF(Py_None);
     return Py_None;
 }