[pypy-svn] r75122 - in pypy/trunk/pypy/module/cpyext: . test
afa at codespeak.net
afa at codespeak.net
Fri Jun 4 23:26:15 CEST 2010
Author: afa
Date: Fri Jun 4 23:26:14 2010
New Revision: 75122
Modified:
pypy/trunk/pypy/module/cpyext/slotdefs.py
pypy/trunk/pypy/module/cpyext/test/foo.c
pypy/trunk/pypy/module/cpyext/test/test_typeobject.py
Log:
implement wrap_descr_get, wrap_descr_set, wrap_descr_delete
Modified: pypy/trunk/pypy/module/cpyext/slotdefs.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/slotdefs.py (original)
+++ pypy/trunk/pypy/module/cpyext/slotdefs.py Fri Jun 4 23:26:14 2010
@@ -5,7 +5,8 @@
from pypy.module.cpyext.typeobjectdefs import (
unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc,
getattrfunc, setattrofunc, lenfunc, ssizeargfunc, ssizessizeargfunc,
- ssizeobjargproc, iternextfunc, initproc, richcmpfunc, hashfunc)
+ ssizeobjargproc, iternextfunc, initproc, richcmpfunc, hashfunc,
+ descrgetfunc, descrsetfunc)
from pypy.module.cpyext.pyobject import from_ref
from pypy.module.cpyext.pyerrors import PyErr_Occurred
from pypy.module.cpyext.state import State
@@ -82,6 +83,44 @@
if rffi.cast(lltype.Signed, res) == -1:
space.fromcache(State).check_and_raise_exception(always=True)
+def wrap_descr_get(space, w_self, w_args, func):
+ func_target = rffi.cast(descrgetfunc, func)
+ args_w = space.fixedview(w_args)
+ if len(args_w) == 1:
+ w_obj, = args_w
+ w_type = None
+ elif len(args_w) == 2:
+ w_obj, w_type = args_w
+ else:
+ raise operationerrfmt(
+ space.w_TypeError,
+ "expected 1 or 2 arguments, got %d", len(args_w))
+ if w_obj is space.w_None:
+ w_obj = None
+ if w_type is space.w_None:
+ w_type = None
+ if w_obj is None and w_type is None:
+ raise OperationError(
+ space.w_TypeError,
+ space.wrap("__get__(None, None) is invalid"))
+ return generic_cpy_call(space, func_target, w_self, w_obj, w_type)
+
+def wrap_descr_set(space, w_self, w_args, func):
+ func_target = rffi.cast(descrsetfunc, func)
+ check_num_args(space, w_args, 2)
+ w_obj, w_value = space.fixedview(w_args)
+ res = generic_cpy_call(space, func_target, w_self, w_obj, w_value)
+ if rffi.cast(lltype.Signed, res) == -1:
+ space.fromcache(State).check_and_raise_exception(always=True)
+
+def wrap_descr_delete(space, w_self, w_args, func):
+ func_target = rffi.cast(descrsetfunc, func)
+ check_num_args(space, w_args, 1)
+ w_obj, = space.fixedview(w_args)
+ res = generic_cpy_call(space, func_target, w_self, w_obj, None)
+ if rffi.cast(lltype.Signed, res) == -1:
+ space.fromcache(State).check_and_raise_exception(always=True)
+
def wrap_call(space, w_self, w_args, func, w_kwds):
func_target = rffi.cast(ternaryfunc, func)
return generic_cpy_call(space, func_target, w_self, w_args, w_kwds)
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 Fri Jun 4 23:26:14 2010
@@ -483,6 +483,90 @@
0 /*tp_weaklist*/
};
+PyObject * prop_descr_get(PyObject *self, PyObject *obj, PyObject *type)
+{
+ if (obj == NULL)
+ obj = Py_None;
+ if (type == NULL)
+ type = Py_None;
+
+ return PyTuple_Pack(3, self, obj, type);
+}
+
+int prop_descr_set(PyObject *self, PyObject *obj, PyObject *value)
+{
+ int res;
+ if (value != NULL) {
+ PyObject *result = PyTuple_Pack(2, self, value);
+ res = PyObject_SetAttrString(obj, "y", result);
+ Py_DECREF(result);
+ }
+ else {
+ res = PyObject_SetAttrString(obj, "z", self);
+ }
+ return res;
+}
+
+
+PyTypeObject SimplePropertyType = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "foo.Property",
+ sizeof(PyObject),
+ 0,
+ 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*/
+
+ prop_descr_get, /*tp_descr_get*/
+ prop_descr_set, /*tp_descr_set*/
+ 0, /*tp_dictoffset*/
+
+ 0, /*tp_init*/
+ 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/
+ 0, /*tp_new*/
+ 0, /*tp_free Low-level free-memory routine */
+ 0, /*tp_is_gc For PyObject_IS_GC */
+ 0, /*tp_bases*/
+ 0, /*tp_mro method resolution order */
+ 0, /*tp_cache*/
+ 0, /*tp_subclasses*/
+ 0 /*tp_weaklist*/
+};
+
/* Initialize this module. */
@@ -506,6 +590,8 @@
return;
if (PyType_Ready(&InitErrType) < 0)
return;
+ if (PyType_Ready(&SimplePropertyType) < 0)
+ return;
m = Py_InitModule("foo", foo_functions);
if (m == NULL)
return;
@@ -522,4 +608,6 @@
return;
if (PyDict_SetItemString(d, "InitErrType", (PyObject *) &InitErrType) < 0)
return;
+ if (PyDict_SetItemString(d, "Property", (PyObject *) &SimplePropertyType) < 0)
+ return;
}
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 Fri Jun 4 23:26:14 2010
@@ -192,6 +192,20 @@
assert d[cmpr] == 72
assert d[3] == 72
+ def test_descriptor(self):
+ module = self.import_module("foo")
+ prop = module.Property()
+ class C(object):
+ x = prop
+ obj = C()
+ assert obj.x == (prop, obj, C)
+ assert C.x == (prop, None, C)
+
+ obj.x = 2
+ assert obj.y == (prop, 2)
+ del obj.x
+ assert obj.z == prop
+
class TestTypes(BaseApiTest):
def test_type_attributes(self, space, api):
More information about the Pypy-commit
mailing list