[pypy-svn] r74866 - in pypy/trunk/pypy/module/cpyext: . test
afa at codespeak.net
afa at codespeak.net
Fri May 28 18:12:46 CEST 2010
Author: afa
Date: Fri May 28 18:12:45 2010
New Revision: 74866
Modified:
pypy/trunk/pypy/module/cpyext/object.py
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 forwarding calls from __setattr__ and __delattr__ to tp_setattro
Also a test for PyObject_GenericSetAttr when used to delete attributes.
Modified: pypy/trunk/pypy/module/cpyext/object.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/object.py (original)
+++ pypy/trunk/pypy/module/cpyext/object.py Fri May 28 18:12:45 2010
@@ -320,9 +320,14 @@
over setting the attribute in the instance dictionary. Otherwise, the
attribute is set in the object's __dict__ (if present). Otherwise,
an AttributeError is raised and -1 is returned."""
- from pypy.objspace.descroperation import object_setattr
- w_descr = object_setattr(space)
- return space.get_and_call_function(w_descr, w_obj, w_name, w_value)
+ from pypy.objspace.descroperation import object_setattr, object_delattr
+ if w_value is not None:
+ w_descr = object_setattr(space)
+ space.get_and_call_function(w_descr, w_obj, w_name, w_value)
+ else:
+ w_descr = object_delattr(space)
+ space.get_and_call_function(w_descr, w_obj, w_name)
+ return 0
@cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
def PyObject_IsInstance(space, w_inst, w_cls):
Modified: pypy/trunk/pypy/module/cpyext/slotdefs.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/slotdefs.py (original)
+++ pypy/trunk/pypy/module/cpyext/slotdefs.py Fri May 28 18:12:45 2010
@@ -1,12 +1,11 @@
import re
from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.module.cpyext.api import generic_cpy_call, cpython_api, \
- PyObject
-from pypy.module.cpyext.typeobjectdefs import unaryfunc, wrapperfunc,\
- ternaryfunc, PyTypeObjectPtr, binaryfunc, getattrfunc, lenfunc,\
- ssizeargfunc, ssizessizeargfunc, ssizeobjargproc, iternextfunc,\
- initproc
+from pypy.module.cpyext.api import generic_cpy_call, cpython_api, PyObject
+from pypy.module.cpyext.typeobjectdefs import (
+ unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc,
+ getattrfunc, setattrofunc, lenfunc, ssizeargfunc, ssizessizeargfunc,
+ ssizeobjargproc, iternextfunc, initproc)
from pypy.module.cpyext.pyobject import from_ref
from pypy.module.cpyext.pyerrors import PyErr_Occurred
from pypy.module.cpyext.state import State
@@ -53,6 +52,24 @@
finally:
rffi.free_charp(name_ptr)
+def wrap_setattr(space, w_self, w_args, func):
+ func_target = rffi.cast(setattrofunc, func)
+ check_num_args(space, w_args, 2)
+ w_name, w_value = space.fixedview(w_args)
+ # XXX "Carlo Verre hack"?
+ if generic_cpy_call(space, func_target, w_self, w_name, w_value) < 0:
+ space.fromcache(State).check_and_raise_exception(always=True)
+ return space.w_None
+
+def wrap_delattr(space, w_self, w_args, func):
+ func_target = rffi.cast(setattrofunc, func)
+ check_num_args(space, w_args, 1)
+ w_name, = space.fixedview(w_args)
+ # XXX "Carlo Verre hack"?
+ if generic_cpy_call(space, func_target, w_self, w_name, None) < 0:
+ space.fromcache(State).check_and_raise_exception(always=True)
+ return space.w_None
+
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)
@@ -135,11 +152,15 @@
# adopted from typeobject.c
def FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, FLAGS):
- wrapper = globals().get(WRAPPER, Ellipsis)
if WRAPPER is None:
wrapper = None
+ else:
+ wrapper = globals().get(WRAPPER, Ellipsis)
+
+ # irregular interface, because of tp_getattr/tp_getattro confusion
if NAME == "__getattr__":
wrapper = wrap_getattr
+
function = globals().get(FUNCTION, None)
slotname = ("c_" + SLOT).split(".")
assert FLAGS == 0 or FLAGS == PyWrapperFlag_KEYWORDS
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 May 28 18:12:45 2010
@@ -114,6 +114,25 @@
return kwds;
}
+static int
+foo_setattro(fooobject *self, PyObject *name, PyObject *value)
+{
+ char *name_str;
+ if (!PyString_Check(name)) {
+ PyErr_SetObject(PyExc_AttributeError, name);
+ return -1;
+ }
+ name_str = PyString_AsString(name);
+ if (strcmp(name_str, "set_foo") == 0)
+ {
+ long v = PyInt_AsLong(value);
+ if (v == -1 && PyErr_Occurred())
+ return -1;
+ self->foo = v;
+ }
+ return PyObject_GenericSetAttr(self, name, value);
+}
+
static PyMemberDef foo_members[] = {
{"int_member", T_INT, offsetof(fooobject, foo), 0,
"A helpful docstring."},
@@ -151,7 +170,7 @@
foo_call, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
- 0, /*tp_setattro*/
+ foo_setattro, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/
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 May 28 18:12:45 2010
@@ -72,6 +72,9 @@
del obj.object_member_ex
raises(AttributeError, "del obj.object_member_ex")
+ obj.set_foo = 32
+ assert obj.foo == 32
+
def test_typeobject_string_member(self):
module = self.import_module(name='foo')
obj = module.new()
More information about the Pypy-commit
mailing list