[pypy-svn] r74822 - in pypy/trunk/pypy/module/cpyext: . test
afa at codespeak.net
afa at codespeak.net
Thu May 27 18:43:52 CEST 2010
Author: afa
Date: Thu May 27 18:43:50 2010
New Revision: 74822
Modified:
pypy/trunk/pypy/module/cpyext/test/foo.c
pypy/trunk/pypy/module/cpyext/test/test_cpyext.py
pypy/trunk/pypy/module/cpyext/test/test_typeobject.py
pypy/trunk/pypy/module/cpyext/typeobject.py
Log:
Implement metatypes for cpyext.
The change seems simple, but was hard to get right...
Modified: pypy/trunk/pypy/module/cpyext/test/foo.c
==============================================================================
--- pypy/trunk/pypy/module/cpyext/test/foo.c (original)
+++ pypy/trunk/pypy/module/cpyext/test/foo.c Thu May 27 18:43:50 2010
@@ -166,6 +166,8 @@
foo_getseters, /*tp_getset*/
};
+/* A type that inherits from 'unicode */
+
typedef struct {
PyUnicodeObject HEAD;
int val;
@@ -312,6 +314,68 @@
};
+/* A Metatype */
+
+PyTypeObject MetaType = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "foo.Meta",
+ sizeof(PyTypeObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
+ 0, /*tp_doc*/
+
+ 0, /*tp_traverse*/
+ 0, /*tp_clear*/
+
+ 0, /*tp_richcompare*/
+ 0, /*tp_weaklistoffset*/
+
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+
+ /* Attribute descriptor and subclassing stuff */
+
+ 0, /*tp_methods*/
+ 0, /*tp_members*/
+ 0, /*tp_getset*/
+ 0, /*tp_base*/
+ 0, /*tp_dict*/
+
+ 0, /*tp_descr_get*/
+ 0, /*tp_descr_set*/
+ 0, /*tp_dictoffset*/
+
+ 0, /*tp_init*/
+ 0, /*tp_alloc*/
+ 0, /*tp_new*/
+ 0, /*tp_free*/
+ 0, /*tp_is_gc*/
+ 0, /*tp_bases*/
+ 0, /*tp_mro*/
+ 0, /*tp_cache*/
+ 0, /*tp_subclasses*/
+ 0 /*tp_weaklist*/
+};
+
+
/* foo functions */
static PyObject *
@@ -344,6 +408,7 @@
FuuType.tp_base = &PyUnicode_Type;
Fuu2Type.tp_base = &FuuType;
+ MetaType.tp_base = &PyType_Type;
if (PyType_Ready(&footype) < 0)
return;
@@ -351,15 +416,20 @@
return;
if (PyType_Ready(&Fuu2Type) < 0)
return;
+ if (PyType_Ready(&MetaType) < 0)
+ return;
m = Py_InitModule("foo", foo_functions);
if (m == NULL)
return;
d = PyModule_GetDict(m);
- if (d) {
- if (PyDict_SetItemString(d, "fooType", (PyObject *)&footype) < 0)
- return;
- PyDict_SetItemString(d, "FuuType", (PyObject *) &FuuType);
- PyDict_SetItemString(d, "Fuu2Type", (PyObject *) &Fuu2Type);
- }
- /* No need to check the error here, the caller will do that */
+ if (d == NULL)
+ return;
+ if (PyDict_SetItemString(d, "fooType", (PyObject *)&footype) < 0)
+ return;
+ if (PyDict_SetItemString(d, "FuuType", (PyObject *) &FuuType) < 0)
+ return;
+ if(PyDict_SetItemString(d, "Fuu2Type", (PyObject *) &Fuu2Type) < 0)
+ return;
+ if (PyDict_SetItemString(d, "MetaType", (PyObject *) &MetaType) < 0)
+ return;
}
Modified: pypy/trunk/pypy/module/cpyext/test/test_cpyext.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/test/test_cpyext.py (original)
+++ pypy/trunk/pypy/module/cpyext/test/test_cpyext.py Thu May 27 18:43:50 2010
@@ -90,6 +90,14 @@
gc.collect()
lost_objects_w = identity_dict()
lost_objects_w.update((key, None) for key in self.frozen_refcounts.keys())
+
+ # Clear all lifelines, objects won't resurrect
+ for w_obj, obj in typeobject.lifeline_dict._dict.items():
+ if w_obj not in state.py_objects_w2r:
+ typeobject.lifeline_dict.set(w_obj, None)
+ del obj
+ gc.collect()
+
for w_obj, obj in state.py_objects_w2r.iteritems():
base_refcnt = self.frozen_refcounts.get(w_obj)
delta = obj.c_ob_refcnt
Modified: pypy/trunk/pypy/module/cpyext/test/test_typeobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/test/test_typeobject.py (original)
+++ pypy/trunk/pypy/module/cpyext/test/test_typeobject.py Thu May 27 18:43:50 2010
@@ -135,6 +135,13 @@
assert newobj.get_val() == 42
assert newobj.foobar == 32
+ def test_metatype(self):
+ module = self.import_module(name='foo')
+ assert module.MetaType.__mro__ == (module.MetaType, type, object)
+ x = module.MetaType('name', (), {})
+ assert isinstance(x, type)
+ x()
+
def test_sre(self):
module = self.import_module(name='_sre')
import sre_compile
Modified: pypy/trunk/pypy/module/cpyext/typeobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/typeobject.py (original)
+++ pypy/trunk/pypy/module/cpyext/typeobject.py Thu May 27 18:43:50 2010
@@ -120,10 +120,6 @@
slot_func.api_func.get_wrapper(space))
# XXX special case wrapper-functions and use a "specific" slot func
- # the special case of __new__ in CPython works a bit differently, hopefully
- # this matches the semantics
- if method_name == "__new__" and not pto.c_tp_new:
- continue
if len(slot_name) == 1:
setattr(pto, slot_name[0], slot_func_helper)
else:
@@ -439,6 +435,7 @@
typedescr = get_typedescr(w_obj.typedef)
py_obj = typedescr.allocate(space, w_type, itemcount=itemcount)
lifeline_dict.set(w_obj, PyOLifeline(space, py_obj))
+ typedescr.attach(space, py_obj, w_obj)
return py_obj
@cpython_api([PyObject, rffi.INTP], lltype.Signed, external=False,
@@ -486,8 +483,9 @@
rffi.free_charp(obj_pto.c_tp_name)
obj_pto_voidp = rffi.cast(rffi.VOIDP_real, obj_pto)
generic_cpy_call(space, type_pto.c_tp_free, obj_pto_voidp)
- pto = rffi.cast(PyObject, type_pto)
- Py_DecRef(space, pto)
+ if type_pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE:
+ pto = rffi.cast(PyObject, type_pto)
+ Py_DecRef(space, pto)
def type_attach(space, py_obj, w_type):
More information about the Pypy-commit
mailing list