[Zope3-checkins] CVS: Zope3/lib/python/Persistence - cPersistence.c:1.23

Jeremy Hylton jeremy@zope.com
Thu, 10 Oct 2002 17:54:42 -0400


Update of /cvs-repository/Zope3/lib/python/Persistence
In directory cvs.zope.org:/tmp/cvs-serv24581

Modified Files:
	cPersistence.c 
Log Message:
Only use a custom metaclass for Python 2.2.

If the code is compiled with other versions of Python, make
PersistentMetaClass an alias for type.


=== Zope3/lib/python/Persistence/cPersistence.c 1.22 => 1.23 ===
--- Zope3/lib/python/Persistence/cPersistence.c:1.22	Thu Oct 10 17:36:18 2002
+++ Zope3/lib/python/Persistence/cPersistence.c	Thu Oct 10 17:54:42 2002
@@ -20,7 +20,12 @@
 "\n"
 "$Id$\n";
 
+/* A custom metaclass is only needed to support Python 2.2. */
+#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION == 2
 static PyTypeObject PyPersist_MetaType;
+#else
+#define PyPersist_MetaType PyType_Type
+#endif
 
 /* Python version of the simple_new function; */
 static PyObject *py_simple_new = NULL;
@@ -666,37 +671,6 @@
 */
 #define DEFERRED_ADDRESS(ADDR) 0
 
-/* Make persistent objects work with Python 2.2. 
-
-   The rules for deciding whether to give an object an __dict__ or an
-   __weakref__ are different in 2.2 than in later versions of Python.
-   In particular, an object will not get an __dict__ if it has a
-   custom setattr.
-*/
-
-static PyObject *
-persist_dict(PyObject *obj, void *context)
-{
-    PyObject **dictptr;
-
-    dictptr = _PyObject_GetDictPtr(obj);
-    assert(dictptr);
-    
-    if (!*dictptr) {
-	PyObject *dict = PyDict_New();
-	if (!dict)
-	    return NULL;
-	*dictptr = dict;
-    }
-    Py_INCREF(*dictptr);
-    return *dictptr;
-}
-
-static PyGetSetDef persist_meta_getsets[] = {
-	{"__dict__",  (getter)persist_dict,  NULL, NULL},
-	{NULL}
-};
-
 static PyTypeObject PyPersist_Type = {
     PyObject_HEAD_INIT(&PyPersist_MetaType)
     0,					/* ob_size */
@@ -740,20 +714,44 @@
     0,					/* tp_new */
 };
 
-/* PyPersist_New is the tp_new of PersistentMetaClass, which exists
-   only for compatibility with Python 2.2. 
-
-   This new function must determine whether to create an __dict__.
-   XXX In the future, it might also handle __weakref__.
+#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION == 2
 
-   Python 2.2 and 2.3 have fairly different rules for whether an
-   instance should get a dict.  The 2.3 rules will often create an
-   __dict__; we don't want to emulate that functionality because it
-   would make persistent classes different from non-persistent
-   new-style classes.
+/* PyPersist_MetaType / PersistentMetaClass exists to work around
+   problems with the way Python 2.2 determines whether a class's
+   instances will get an __dict__, or, more concretely, what the value
+   of tp_dictoffset should be.
+
+   The metaclass uses a custom tp_alloc function PyPersist_Alloc() to
+   set tp_dictoffset to -1.  This assignment prevents type_new() from
+   doing anything with dictoffset.  Later the metaclass tp_new
+   function PyPersist_New() assigns a reasonable value for
+   tp_dictoffset and creates an __dict__ descriptor.
 */
 
 static PyObject *
+persist_dict(PyObject *obj, void *context)
+{
+    PyObject **dictptr;
+
+    dictptr = _PyObject_GetDictPtr(obj);
+    assert(dictptr);
+    
+    if (!*dictptr) {
+	PyObject *dict = PyDict_New();
+	if (!dict)
+	    return NULL;
+	*dictptr = dict;
+    }
+    Py_INCREF(*dictptr);
+    return *dictptr;
+}
+
+static PyGetSetDef persist_meta_getsets[] = {
+	{"__dict__",  (getter)persist_dict,  NULL, NULL},
+	{NULL}
+};
+
+static PyObject *
 PyPersist_Alloc(PyTypeObject *metatype, int nitems)
 {
     PyObject *type = PyType_GenericAlloc(metatype, nitems);
@@ -811,6 +809,8 @@
     "Persistence.PersistentMetaClass",	/* tp_name */
 };
 
+#endif
+
 static PyObject *
 simple_new(PyObject *self, PyObject *type_object)
 {
@@ -875,9 +875,15 @@
 {
     PyObject *m, *d, *v;
 
-    /* It's easier to initialize a few fields by assignment than to
-       fill out the entire type structure in an initializer. 
-    */
+    m = Py_InitModule3("cPersistence", PyPersist_methods, 
+		       PyPersist_doc_string);
+    if (m == NULL)
+	return;
+    d = PyModule_GetDict(m);
+    if (d == NULL)
+	return;
+
+#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION == 2
     PyPersist_MetaType.ob_type = &PyType_Type;
     PyPersist_MetaType.tp_alloc = PyPersist_Alloc;
     PyPersist_MetaType.tp_new = PyPersist_New;
@@ -888,27 +894,26 @@
     PyPersist_MetaType.tp_clear = PyType_Type.tp_clear;
     if (PyType_Ready(&PyPersist_MetaType) < 0)
 	return;
+    Py_INCREF(&PyPersist_MetaType);
+    if (PyDict_SetItemString(d, "PersistentMetaClass", 
+			     (PyObject *)&PyPersist_MetaType) < 0)
+	return;
+#else
+    Py_INCREF(&PyType_Type);
+    if (PyDict_SetItemString(d, "PersistentMetaClass", 
+			     (PyObject *)&PyType_Type) < 0)
+	return;
+#endif
 
+    PyPersist_Type.ob_type = &PyPersist_MetaType;
     PyPersist_Type.tp_new = PyType_GenericNew;
     if (PyType_Ready(&PyPersist_Type) < 0)
 	return;
     if (persist_set_interface(&PyPersist_Type) < 0)
 	return;
 
-    m = Py_InitModule3("cPersistence", PyPersist_methods, 
-		       PyPersist_doc_string);
-    if (m == NULL)
-	return;
-    d = PyModule_GetDict(m);
-    if (d == NULL)
-	return;
-
     Py_INCREF(&PyPersist_Type);
     if (PyDict_SetItemString(d, "Persistent", (PyObject *)&PyPersist_Type) < 0)
-	return;
-    Py_INCREF(&PyPersist_MetaType);
-    if (PyDict_SetItemString(d, "PersistentMetaClass", 
-			     (PyObject *)&PyPersist_MetaType) < 0)
 	return;
 
     v = PyCObject_FromVoidPtr(&c_api, NULL);