[Zope3-checkins] CVS: ZODB4/src/persistence - persistence.c:1.12
Phillip J. Eby
pje@telecommunity.com
Fri, 11 Apr 2003 18:00:24 -0400
Update of /cvs-repository/ZODB4/src/persistence
In directory cvs.zope.org:/tmp/cvs-serv7086/src/persistence
Modified Files:
persistence.c
Log Message:
Fixed the last two bugs from Zope3-Dev Collector #86: you couldn't mix
Persistent and a base class that used a Python metaclass under Python 2.2,
and Persistent subclasses wouldn't have instance dictionaries if a parent
class defined '__slots__', even though for normal Python classes,
subclassing a class with '__slots__' produces a class with instance
dictionaries unless the subclass also defines '__slots__'. Added test
cases for both scenarios. Note that these bugs only existed under Python
2.2, where the custom C metaclass 'PersistentMetaClass' is used.
=== ZODB4/src/persistence/persistence.c 1.11 => 1.12 ===
--- ZODB4/src/persistence/persistence.c:1.11 Thu Apr 10 13:55:25 2003
+++ ZODB4/src/persistence/persistence.c Fri Apr 11 17:59:54 2003
@@ -840,9 +840,11 @@
/* It is possible for a class that inherits from Persistent to
define __slots__, in which case it shouldn't have a dict.
- XXX This isn't ready yet.
+ We have to look in the dictionary supplied to the keyword arguments,
+ however, or we can be fooled by a base type having __slots__.
+ (See 'persistence.tests.test_persistence.Test.testSlots')
*/
- if (PyObject_HasAttrString((PyObject *)new, "__slots__")) {
+ if (PyMapping_HasKeyString(PyTuple_GetItem(args,2), "__slots__")) {
return (PyObject *)new;
}
@@ -971,6 +973,16 @@
PyPersist_MetaType.tp_clear = PyType_Type.tp_clear;
if (PyType_Ready(&PyPersist_MetaType) < 0)
return;
+
+ /* Cheap hack to force us to be used instead of 'type' as '__base__';
+ this ensures that we are always used for C-level layout, and can
+ therefore interoperate with other (pure Python) metaclasses.
+ (See 'persistence.tests.test_persistence.Test.testMultipleMeta')
+ This costs us a (PyObject *) per subclass of Persistent, but it
+ seems to be the only way to fix this in Python 2.2.x. :(
+ */
+ PyPersist_MetaType.tp_basicsize += sizeof(PyObject *);
+
Py_INCREF(&PyPersist_MetaType);
if (PyDict_SetItemString(d, "PersistentMetaClass",
(PyObject *)&PyPersist_MetaType) < 0)