[pypy-svn] r72959 - in pypy/branch/cpython-extension/pypy/module/cpyext: . test
xoraxax at codespeak.net
xoraxax at codespeak.net
Sat Mar 27 17:04:56 CET 2010
Author: xoraxax
Date: Sat Mar 27 17:04:54 2010
New Revision: 72959
Added:
pypy/branch/cpython-extension/pypy/module/cpyext/slotdefs.py (contents, props changed)
pypy/branch/cpython-extension/pypy/module/cpyext/typeobjectdefs.py (contents, props changed)
Modified:
pypy/branch/cpython-extension/pypy/module/cpyext/__init__.py
pypy/branch/cpython-extension/pypy/module/cpyext/methodobject.py
pypy/branch/cpython-extension/pypy/module/cpyext/test/foo.c
pypy/branch/cpython-extension/pypy/module/cpyext/test/test_typeobject.py
pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py
Log:
Implement slot wrappers, move code from typeobject.py to typeobjectdefs.py.
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/__init__.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/__init__.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/__init__.py Sat Mar 27 17:04:54 2010
@@ -2,6 +2,7 @@
from pypy.rlib.objectmodel import we_are_translated
import pypy.module.cpyext.api
from pypy.module.cpyext.state import State
+from pypy.module.cpyext.slotdefs import init_slotdefs
class Module(MixedModule):
@@ -17,6 +18,7 @@
state = self.space.fromcache(State)
if not we_are_translated():
state.api_lib = str(pypy.module.cpyext.api.build_bridge(self.space))
+ state.slotdefs = init_slotdefs(self.space)
else:
XXX # build an import library when translating pypy.
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/methodobject.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/methodobject.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/methodobject.py Sat Mar 27 17:04:54 2010
@@ -43,6 +43,33 @@
return self.space.wrap(self.__repr__())
+class W_PyCWrapperObject(Wrappable):
+ def __init__(self, space, pto, method_name, wrapper_func, doc, flags, func):
+ self.space = space
+ self.method_name = method_name
+ self.wrapper_func = wrapper_func
+ self.doc = doc
+ self.flags = flags
+ self.func = func
+ assert flags == 0
+ self.w_objclass = from_ref(space, pto)
+
+ def call(self, w_self, w_args):
+ return generic_cpy_call(self.space, self.wrapper_func, w_self, w_args, self.func)
+
+
+ at unwrap_spec(ObjSpace, W_Root, Arguments)
+def cwrapper_descr_call(space, w_self, __args__):
+ self = space.interp_w(W_PyCWrapperObject, w_self)
+ args_w, kw_w = __args__.unpack()
+ w_args = space.newtuple(args_w[1:])
+ w_self = args_w[0]
+ if kw_w:
+ raise OperationError(space.w_TypeError,
+ space.wrap("keywords not yet supported"))
+ return self.call(w_self, w_args)
+
+
@unwrap_spec(ObjSpace, W_Root, Arguments)
def cfunction_descr_call(space, w_self, __args__):
self = space.interp_w(W_PyCFunctionObject, w_self)
@@ -51,7 +78,7 @@
if kw_w:
raise OperationError(space.w_TypeError,
space.wrap("keywords not yet supported"))
- ret = self.call(None, space.newtuple(args_w))
+ ret = self.call(None, w_args)
return ret
@unwrap_spec(ObjSpace, W_Root, Arguments)
@@ -80,7 +107,6 @@
'builtin_function_or_method',
__call__ = interp2app(cfunction_descr_call),
)
-
W_PyCFunctionObject.typedef.acceptable_as_base_class = False
W_PyCMethodObject.typedef = TypeDef(
@@ -91,13 +117,29 @@
__objclass__ = interp_attrproperty_w('w_objclass', cls=W_PyCMethodObject),
__repr__ = interp2app(W_PyCMethodObject.descr_method_repr),
)
-
W_PyCMethodObject.typedef.acceptable_as_base_class = False
-def PyCFunction_NewEx(space, ml, w_self): # not directly the API sig
+
+W_PyCWrapperObject.typedef = TypeDef(
+ 'wrapper_descriptor',
+ __call__ = interp2app(cwrapper_descr_call),
+ __get__ = interp2app(cmethod_descr_get),
+ __name__ = interp_attrproperty('method_name', cls=W_PyCWrapperObject),
+ __doc__ = interp_attrproperty('doc', cls=W_PyCWrapperObject),
+ __objclass__ = interp_attrproperty_w('w_objclass', cls=W_PyCWrapperObject),
+ # XXX missing: __getattribute__, __repr__
+ )
+W_PyCWrapperObject.typedef.acceptable_as_base_class = False
+
+
+def PyCFunction_NewEx(space, ml, w_self): # not exactly the API sig
return space.wrap(W_PyCFunctionObject(space, ml, w_self))
def PyDescr_NewMethod(space, pto, method):
return space.wrap(W_PyCMethodObject(space, method, pto))
+def PyDescr_NewWrapper(space, pto, method_name, wrapper_func, doc, flags, func):
+ # not exactly the API sig
+ return space.wrap(W_PyCWrapperObject(space, pto, method_name,
+ wrapper_func, doc, flags, func))
Added: pypy/branch/cpython-extension/pypy/module/cpyext/slotdefs.py
==============================================================================
--- (empty file)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/slotdefs.py Sat Mar 27 17:04:54 2010
@@ -0,0 +1,306 @@
+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
+from pypy.module.cpyext.state import State
+from pypy.interpreter.error import OperationError, operationerrfmt
+
+space = None
+
+def is_wrapper_func(func):
+ deco = cpython_api([PyObject, PyObject, rffi.VOIDP_real], PyObject, external=False)
+ return deco(func)
+
+def check_num_args(space, ob, n):
+ from pypy.module.cpyext.tupleobject import PyTuple_CheckExact, \
+ PyTuple_GET_SIZE
+ if not PyTuple_CheckExact(space, ob):
+ raise OperationError(space.w_SystemError,
+ "PyArg_UnpackTuple() argument list is not a tuple")
+ if n == PyTuple_GET_SIZE(space, ob):
+ return
+ raise operationerrfmt(space.w_TypeError,
+ "expected %d arguments, got %zd", n, PyTuple_GET_SIZE(ob))
+
+def wrap_binaryfunc_l(space, w_self, w_args, func):
+ pass
+
+def wrap_binaryfunc_r(space, w_self, w_args, func):
+ pass
+
+ at is_wrapper_func
+def wrap_unaryfunc(space, w_self, w_args, func):
+ func_unary = rffi.cast(unaryfunc, func)
+ check_num_args(space, w_args, 0)
+ return generic_cpy_call(space, func_unary, w_self)
+
+
+PyWrapperFlag_KEYWORDS = 1
+
+# adopted from typeobject.c
+def FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, FLAGS):
+ wrapper = globals().get(WRAPPER, None)
+ if wrapper is not None:
+ wrapper = wrapper.api_func.get_llhelper(space)
+ else:
+ wrapper = lltype.nullptr(wrapperfunc.TO)
+ slotname = ("c_" + SLOT).split(".")
+ return (NAME, slotname, FUNCTION, wrapper, DOC, FLAGS)
+
+def TPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC):
+ return FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, 0)
+
+ETSLOT = TPSLOT
+
+def SQSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC):
+ return ETSLOT(NAME, "tp_as_sequence.c_" + SLOT, FUNCTION, WRAPPER, DOC)
+def MPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC):
+ return ETSLOT(NAME, "tp_as_mapping.c_" + SLOT, FUNCTION, WRAPPER, DOC)
+def NBSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC):
+ return ETSLOT(NAME, "tp_as_number.c_" + SLOT, FUNCTION, WRAPPER, DOC)
+def UNSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC):
+ return ETSLOT(NAME, "tp_as_number.c_" + SLOT, FUNCTION, WRAPPER,
+ "x." + NAME + "() <==> " + DOC)
+def IBSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC):
+ return ETSLOT(NAME, "tp_as_number.c_" + SLOT, FUNCTION, WRAPPER,
+ "x." + NAME + "(y) <==> x" + DOC + "y")
+def BINSLOT(NAME, SLOT, FUNCTION, DOC):
+ return ETSLOT(NAME, "tp_as_number.c_" + SLOT, FUNCTION, wrap_binaryfunc_l, \
+ "x." + NAME + "(y) <==> x" + DOC + "y")
+def RBINSLOT(NAME, SLOT, FUNCTION, DOC):
+ return ETSLOT(NAME, "tp_as_number.c_" + SLOT, FUNCTION, wrap_binaryfunc_r, \
+ "x." + NAME + "(y) <==> y" + DOC + "x")
+def BINSLOTNOTINFIX(NAME, SLOT, FUNCTION, DOC):
+ return ETSLOT(NAME, "tp_as_number.c_" + SLOT, FUNCTION, wrap_binaryfunc_l, \
+ "x." + NAME + "(y) <==> " + DOC)
+def RBINSLOTNOTINFIX(NAME, SLOT, FUNCTION, DOC):
+ return ETSLOT(NAME, "tp_as_number.c_" + SLOT, FUNCTION, wrap_binaryfunc_r, \
+ "x." + NAME + "(y) <==> " + DOC)
+
+# TODO remove all casts
+slotdef_replacements = (
+ ("\s+", " "),
+ ("static [^{]*{", "("),
+ ("};", ")"),
+ (r"(?P<start> +..SLOT\([^,]*, )(?P<fname>[^,]*), (?P<slotcname>[^,]*), (?P<wname>[^,]*)", r"\g<start>'\g<fname>', '\g<slotcname>', '\g<wname>'"),
+ (r"(?P<start> *R?[^ ]{3}SLOT(NOTINFIX)?\([^,]*, )(?P<fname>[^,]*), (?P<slotcname>[^,]*)", r"\g<start>'\g<fname>', '\g<slotcname>'"),
+ ("'NULL'", "None"),
+ ("{NULL}", ""),
+ ("\),", "),\n"),
+ )
+
+"""
+ /* Heap types defining __add__/__mul__ have sq_concat/sq_repeat == NULL.
+ The logic in abstract.c always falls back to nb_add/nb_multiply in
+ this case. Defining both the nb_* and the sq_* slots to call the
+ user-defined methods has unexpected side-effects, as shown by
+ test_descr.notimplemented() */
+"""
+# Instructions for update:
+# Copy new slotdefs from typeobject.c
+# Remove comments
+# Done
+slotdefs = """
+static slotdef slotdefs[] = {
+ SQSLOT("__len__", sq_length, slot_sq_length, wrap_lenfunc,
+ "x.__len__() <==> len(x)"),
+ SQSLOT("__add__", sq_concat, NULL, wrap_binaryfunc,
+ "x.__add__(y) <==> x+y"),
+ SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc,
+ "x.__mul__(n) <==> x*n"),
+ SQSLOT("__rmul__", sq_repeat, NULL, wrap_indexargfunc,
+ "x.__rmul__(n) <==> n*x"),
+ SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item,
+ "x.__getitem__(y) <==> x[y]"),
+ SQSLOT("__getslice__", sq_slice, slot_sq_slice, wrap_ssizessizeargfunc,
+ "x.__getslice__(i, j) <==> x[i:j]\n\
+ \n\
+ Use of negative indices is not supported."),
+ SQSLOT("__setitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_setitem,
+ "x.__setitem__(i, y) <==> x[i]=y"),
+ SQSLOT("__delitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_delitem,
+ "x.__delitem__(y) <==> del x[y]"),
+ SQSLOT("__setslice__", sq_ass_slice, slot_sq_ass_slice,
+ wrap_ssizessizeobjargproc,
+ "x.__setslice__(i, j, y) <==> x[i:j]=y\n\
+ \n\
+ Use of negative indices is not supported."),
+ SQSLOT("__delslice__", sq_ass_slice, slot_sq_ass_slice, wrap_delslice,
+ "x.__delslice__(i, j) <==> del x[i:j]\n\
+ \n\
+ Use of negative indices is not supported."),
+ SQSLOT("__contains__", sq_contains, slot_sq_contains, wrap_objobjproc,
+ "x.__contains__(y) <==> y in x"),
+ SQSLOT("__iadd__", sq_inplace_concat, NULL,
+ wrap_binaryfunc, "x.__iadd__(y) <==> x+=y"),
+ SQSLOT("__imul__", sq_inplace_repeat, NULL,
+ wrap_indexargfunc, "x.__imul__(y) <==> x*=y"),
+
+ MPSLOT("__len__", mp_length, slot_mp_length, wrap_lenfunc,
+ "x.__len__() <==> len(x)"),
+ MPSLOT("__getitem__", mp_subscript, slot_mp_subscript,
+ wrap_binaryfunc,
+ "x.__getitem__(y) <==> x[y]"),
+ MPSLOT("__setitem__", mp_ass_subscript, slot_mp_ass_subscript,
+ wrap_objobjargproc,
+ "x.__setitem__(i, y) <==> x[i]=y"),
+ MPSLOT("__delitem__", mp_ass_subscript, slot_mp_ass_subscript,
+ wrap_delitem,
+ "x.__delitem__(y) <==> del x[y]"),
+
+ BINSLOT("__add__", nb_add, slot_nb_add,
+ "+"),
+ RBINSLOT("__radd__", nb_add, slot_nb_add,
+ "+"),
+ BINSLOT("__sub__", nb_subtract, slot_nb_subtract,
+ "-"),
+ RBINSLOT("__rsub__", nb_subtract, slot_nb_subtract,
+ "-"),
+ BINSLOT("__mul__", nb_multiply, slot_nb_multiply,
+ "*"),
+ RBINSLOT("__rmul__", nb_multiply, slot_nb_multiply,
+ "*"),
+ BINSLOT("__div__", nb_divide, slot_nb_divide,
+ "/"),
+ RBINSLOT("__rdiv__", nb_divide, slot_nb_divide,
+ "/"),
+ BINSLOT("__mod__", nb_remainder, slot_nb_remainder,
+ "%"),
+ RBINSLOT("__rmod__", nb_remainder, slot_nb_remainder,
+ "%"),
+ BINSLOTNOTINFIX("__divmod__", nb_divmod, slot_nb_divmod,
+ "divmod(x, y)"),
+ RBINSLOTNOTINFIX("__rdivmod__", nb_divmod, slot_nb_divmod,
+ "divmod(y, x)"),
+ NBSLOT("__pow__", nb_power, slot_nb_power, wrap_ternaryfunc,
+ "x.__pow__(y[, z]) <==> pow(x, y[, z])"),
+ NBSLOT("__rpow__", nb_power, slot_nb_power, wrap_ternaryfunc_r,
+ "y.__rpow__(x[, z]) <==> pow(x, y[, z])"),
+ UNSLOT("__neg__", nb_negative, slot_nb_negative, wrap_unaryfunc, "-x"),
+ UNSLOT("__pos__", nb_positive, slot_nb_positive, wrap_unaryfunc, "+x"),
+ UNSLOT("__abs__", nb_absolute, slot_nb_absolute, wrap_unaryfunc,
+ "abs(x)"),
+ UNSLOT("__nonzero__", nb_nonzero, slot_nb_nonzero, wrap_inquirypred,
+ "x != 0"),
+ UNSLOT("__invert__", nb_invert, slot_nb_invert, wrap_unaryfunc, "~x"),
+ BINSLOT("__lshift__", nb_lshift, slot_nb_lshift, "<<"),
+ RBINSLOT("__rlshift__", nb_lshift, slot_nb_lshift, "<<"),
+ BINSLOT("__rshift__", nb_rshift, slot_nb_rshift, ">>"),
+ RBINSLOT("__rrshift__", nb_rshift, slot_nb_rshift, ">>"),
+ BINSLOT("__and__", nb_and, slot_nb_and, "&"),
+ RBINSLOT("__rand__", nb_and, slot_nb_and, "&"),
+ BINSLOT("__xor__", nb_xor, slot_nb_xor, "^"),
+ RBINSLOT("__rxor__", nb_xor, slot_nb_xor, "^"),
+ BINSLOT("__or__", nb_or, slot_nb_or, "|"),
+ RBINSLOT("__ror__", nb_or, slot_nb_or, "|"),
+ NBSLOT("__coerce__", nb_coerce, slot_nb_coerce, wrap_coercefunc,
+ "x.__coerce__(y) <==> coerce(x, y)"),
+ UNSLOT("__int__", nb_int, slot_nb_int, wrap_unaryfunc,
+ "int(x)"),
+ UNSLOT("__long__", nb_long, slot_nb_long, wrap_unaryfunc,
+ "long(x)"),
+ UNSLOT("__float__", nb_float, slot_nb_float, wrap_unaryfunc,
+ "float(x)"),
+ UNSLOT("__oct__", nb_oct, slot_nb_oct, wrap_unaryfunc,
+ "oct(x)"),
+ UNSLOT("__hex__", nb_hex, slot_nb_hex, wrap_unaryfunc,
+ "hex(x)"),
+ NBSLOT("__index__", nb_index, slot_nb_index, wrap_unaryfunc,
+ "x[y:z] <==> x[y.__index__():z.__index__()]"),
+ IBSLOT("__iadd__", nb_inplace_add, slot_nb_inplace_add,
+ wrap_binaryfunc, "+"),
+ IBSLOT("__isub__", nb_inplace_subtract, slot_nb_inplace_subtract,
+ wrap_binaryfunc, "-"),
+ IBSLOT("__imul__", nb_inplace_multiply, slot_nb_inplace_multiply,
+ wrap_binaryfunc, "*"),
+ IBSLOT("__idiv__", nb_inplace_divide, slot_nb_inplace_divide,
+ wrap_binaryfunc, "/"),
+ IBSLOT("__imod__", nb_inplace_remainder, slot_nb_inplace_remainder,
+ wrap_binaryfunc, "%"),
+ IBSLOT("__ipow__", nb_inplace_power, slot_nb_inplace_power,
+ wrap_binaryfunc, "**"),
+ IBSLOT("__ilshift__", nb_inplace_lshift, slot_nb_inplace_lshift,
+ wrap_binaryfunc, "<<"),
+ IBSLOT("__irshift__", nb_inplace_rshift, slot_nb_inplace_rshift,
+ wrap_binaryfunc, ">>"),
+ IBSLOT("__iand__", nb_inplace_and, slot_nb_inplace_and,
+ wrap_binaryfunc, "&"),
+ IBSLOT("__ixor__", nb_inplace_xor, slot_nb_inplace_xor,
+ wrap_binaryfunc, "^"),
+ IBSLOT("__ior__", nb_inplace_or, slot_nb_inplace_or,
+ wrap_binaryfunc, "|"),
+ BINSLOT("__floordiv__", nb_floor_divide, slot_nb_floor_divide, "//"),
+ RBINSLOT("__rfloordiv__", nb_floor_divide, slot_nb_floor_divide, "//"),
+ BINSLOT("__truediv__", nb_true_divide, slot_nb_true_divide, "/"),
+ RBINSLOT("__rtruediv__", nb_true_divide, slot_nb_true_divide, "/"),
+ IBSLOT("__ifloordiv__", nb_inplace_floor_divide,
+ slot_nb_inplace_floor_divide, wrap_binaryfunc, "//"),
+ IBSLOT("__itruediv__", nb_inplace_true_divide,
+ slot_nb_inplace_true_divide, wrap_binaryfunc, "/"),
+
+ TPSLOT("__str__", tp_str, slot_tp_str, wrap_unaryfunc,
+ "x.__str__() <==> str(x)"),
+ TPSLOT("__str__", tp_print, NULL, NULL, ""),
+ TPSLOT("__repr__", tp_repr, slot_tp_repr, wrap_unaryfunc,
+ "x.__repr__() <==> repr(x)"),
+ TPSLOT("__repr__", tp_print, NULL, NULL, ""),
+ TPSLOT("__cmp__", tp_compare, _PyObject_SlotCompare, wrap_cmpfunc,
+ "x.__cmp__(y) <==> cmp(x,y)"),
+ TPSLOT("__hash__", tp_hash, slot_tp_hash, wrap_hashfunc,
+ "x.__hash__() <==> hash(x)"),
+ FLSLOT("__call__", tp_call, slot_tp_call, (wrapperfunc)wrap_call,
+ "x.__call__(...) <==> x(...)", PyWrapperFlag_KEYWORDS),
+ TPSLOT("__getattribute__", tp_getattro, slot_tp_getattr_hook,
+ wrap_binaryfunc, "x.__getattribute__('name') <==> x.name"),
+ TPSLOT("__getattribute__", tp_getattr, NULL, NULL, ""),
+ TPSLOT("__getattr__", tp_getattro, slot_tp_getattr_hook, NULL, ""),
+ TPSLOT("__getattr__", tp_getattr, NULL, NULL, ""),
+ TPSLOT("__setattr__", tp_setattro, slot_tp_setattro, wrap_setattr,
+ "x.__setattr__('name', value) <==> x.name = value"),
+ TPSLOT("__setattr__", tp_setattr, NULL, NULL, ""),
+ TPSLOT("__delattr__", tp_setattro, slot_tp_setattro, wrap_delattr,
+ "x.__delattr__('name') <==> del x.name"),
+ TPSLOT("__delattr__", tp_setattr, NULL, NULL, ""),
+ TPSLOT("__lt__", tp_richcompare, slot_tp_richcompare, richcmp_lt,
+ "x.__lt__(y) <==> x<y"),
+ TPSLOT("__le__", tp_richcompare, slot_tp_richcompare, richcmp_le,
+ "x.__le__(y) <==> x<=y"),
+ TPSLOT("__eq__", tp_richcompare, slot_tp_richcompare, richcmp_eq,
+ "x.__eq__(y) <==> x==y"),
+ TPSLOT("__ne__", tp_richcompare, slot_tp_richcompare, richcmp_ne,
+ "x.__ne__(y) <==> x!=y"),
+ TPSLOT("__gt__", tp_richcompare, slot_tp_richcompare, richcmp_gt,
+ "x.__gt__(y) <==> x>y"),
+ TPSLOT("__ge__", tp_richcompare, slot_tp_richcompare, richcmp_ge,
+ "x.__ge__(y) <==> x>=y"),
+ TPSLOT("__iter__", tp_iter, slot_tp_iter, wrap_unaryfunc,
+ "x.__iter__() <==> iter(x)"),
+ TPSLOT("next", tp_iternext, slot_tp_iternext, wrap_next,
+ "x.next() -> the next value, or raise StopIteration"),
+ TPSLOT("__get__", tp_descr_get, slot_tp_descr_get, wrap_descr_get,
+ "descr.__get__(obj[, type]) -> value"),
+ TPSLOT("__set__", tp_descr_set, slot_tp_descr_set, wrap_descr_set,
+ "descr.__set__(obj, value)"),
+ TPSLOT("__delete__", tp_descr_set, slot_tp_descr_set,
+ wrap_descr_delete, "descr.__delete__(obj)"),
+ FLSLOT("__init__", tp_init, slot_tp_init, (wrapperfunc)wrap_init,
+ "x.__init__(...) initializes x; "
+ "see x.__class__.__doc__ for signature",
+ PyWrapperFlag_KEYWORDS),
+ TPSLOT("__new__", tp_new, slot_tp_new, NULL, ""),
+ TPSLOT("__del__", tp_del, slot_tp_del, NULL, ""),
+ {NULL}
+};
+"""
+for regex, repl in slotdef_replacements:
+ slotdefs = re.sub(regex, repl, slotdefs)
+def init_slotdefs(space_):
+ global space
+ space = space_
+ try:
+ return eval(slotdefs)
+ finally:
+ space = None
+
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/test/foo.c
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/test/foo.c (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/test/foo.c Sat Mar 27 17:04:54 2010
@@ -66,6 +66,16 @@
{NULL} /* Sentinel */
};
+static PyObject *
+foo_repr(PyObject *self)
+{
+ PyObject *format;
+
+ format = PyString_FromString("<Foo>");
+ if (format == NULL) return NULL;
+ return format;
+}
+
static PyTypeObject footype = {
PyVarObject_HEAD_INIT(NULL, 0)
@@ -78,7 +88,7 @@
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
- 0, /*tp_repr*/
+ foo_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/test/test_typeobject.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/test/test_typeobject.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/test/test_typeobject.py Sat Mar 27 17:04:54 2010
@@ -19,3 +19,5 @@
assert not "im_func" in dir(module.fooType.copy)
assert module.fooType.copy.__objclass__ is module.fooType
assert "copy" in repr(module.fooType.copy)
+ assert repr(module.fooType) == "<type 'foo.foo'>"
+ assert repr(obj2) == "<Foo>"
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py Sat Mar 27 17:04:54 2010
@@ -1,7 +1,6 @@
import sys
from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.rpython.lltypesystem.lltype import Ptr, FuncType, Void
from pypy.rpython.annlowlevel import llhelper
from pypy.interpreter.gateway import ObjSpace, W_Root
from pypy.interpreter.gateway import interp2app, unwrap_spec
@@ -12,149 +11,15 @@
from pypy.module.cpyext.api import cpython_api, cpython_api_c, cpython_struct, \
PyObject, PyVarObjectFields, Py_ssize_t, Py_TPFLAGS_READYING, \
Py_TPFLAGS_READY, Py_TPFLAGS_HEAPTYPE, make_ref, \
- PyStringObject, ADDR, from_ref
+ PyStringObject, ADDR, from_ref, generic_cpy_call
from pypy.interpreter.module import Module
-from pypy.module.cpyext.modsupport import PyMethodDef, convert_method_defs
+from pypy.module.cpyext.modsupport import convert_method_defs
from pypy.module.cpyext.state import State
-from pypy.module.cpyext.methodobject import generic_cpy_call
+from pypy.module.cpyext.methodobject import PyDescr_NewWrapper
from pypy.module.cpyext.macros import Py_INCREF, Py_DECREF, Py_XDECREF
-
-PyTypeObject = lltype.ForwardReference()
-PyTypeObjectPtr = lltype.Ptr(PyTypeObject)
-PyCFunction = Ptr(FuncType([PyObject, PyObject], PyObject))
-P, FT, PyO = Ptr, FuncType, PyObject
-PyOPtr = Ptr(lltype.Array(PyO, hints={'nolength': True}))
-
-
-# XXX
-PyNumberMethods = PySequenceMethods = PyMappingMethods = \
- PyBufferProcs = PyMemberDef = rffi.VOIDP.TO
-
-freefunc = P(FT([rffi.VOIDP_real], Void))
-destructor = P(FT([PyO], Void))
-printfunc = P(FT([PyO, rffi.VOIDP_real, rffi.INT_real], rffi.INT))
-getattrfunc = P(FT([PyO, rffi.CCHARP], PyO))
-getattrofunc = P(FT([PyO, PyO], PyO))
-setattrfunc = P(FT([PyO, rffi.CCHARP, PyO], rffi.INT_real))
-setattrofunc = P(FT([PyO, PyO, PyO], rffi.INT_real))
-cmpfunc = P(FT([PyO, PyO], rffi.INT_real))
-reprfunc = P(FT([PyO], PyO))
-hashfunc = P(FT([PyO], lltype.Signed))
-richcmpfunc = P(FT([PyO, PyO, rffi.INT_real], PyO))
-getiterfunc = P(FT([PyO], PyO))
-iternextfunc = P(FT([PyO], PyO))
-descrgetfunc = P(FT([PyO, PyO, PyO], PyO))
-descrsetfunc = P(FT([PyO, PyO, PyO], rffi.INT_real))
-initproc = P(FT([PyO, PyO, PyO], rffi.INT_real))
-newfunc = P(FT([PyTypeObjectPtr, PyO, PyO], PyO))
-allocfunc = P(FT([PyTypeObjectPtr, Py_ssize_t], PyO))
-unaryfunc = P(FT([PyO], PyO))
-binaryfunc = P(FT([PyO, PyO], PyO))
-ternaryfunc = P(FT([PyO, PyO, PyO], PyO))
-inquiry = P(FT([PyO], rffi.INT_real))
-lenfunc = P(FT([PyO], Py_ssize_t))
-coercion = P(FT([PyOPtr, PyOPtr], rffi.INT_real))
-intargfunc = P(FT([PyO, rffi.INT_real], PyO))
-intintargfunc = P(FT([PyO, rffi.INT_real, rffi.INT], PyO))
-ssizeargfunc = P(FT([PyO, Py_ssize_t], PyO))
-ssizessizeargfunc = P(FT([PyO, Py_ssize_t, Py_ssize_t], PyO))
-intobjargproc = P(FT([PyO, rffi.INT_real, PyO], rffi.INT))
-intintobjargproc = P(FT([PyO, rffi.INT_real, rffi.INT, PyO], rffi.INT))
-ssizeobjargproc = P(FT([PyO, Py_ssize_t, PyO], rffi.INT_real))
-ssizessizeobjargproc = P(FT([PyO, Py_ssize_t, Py_ssize_t, PyO], rffi.INT_real))
-objobjargproc = P(FT([PyO, PyO, PyO], rffi.INT_real))
-
-objobjproc = P(FT([PyO, PyO], rffi.INT_real))
-visitproc = P(FT([PyO, rffi.VOIDP_real], rffi.INT_real))
-traverseproc = P(FT([PyO, visitproc, rffi.VOIDP_real], rffi.INT_real))
-
-getter = P(FT([PyO, rffi.VOIDP_real], PyO))
-setter = P(FT([PyO, PyO, rffi.VOIDP_real], rffi.INT_real))
-
-PyGetSetDef = cpython_struct("PyGetSetDef", (
- ("name", rffi.CCHARP),
- ("get", getter),
- ("set", setter),
- ("doc", rffi.CCHARP),
- ("closure", rffi.VOIDP_real),
-))
-
-PyTypeObjectFields = []
-PyTypeObjectFields.extend(PyVarObjectFields)
-PyTypeObjectFields.extend([
- ("tp_name", rffi.CCHARP), # For printing, in format "<module>.<name>"
- ("tp_basicsize", Py_ssize_t), ("tp_itemsize", Py_ssize_t), # For allocation
-
- # Methods to implement standard operations
- ("tp_dealloc", destructor),
- ("tp_print", printfunc),
- ("tp_getattr", getattrfunc),
- ("tp_setattr", setattrfunc),
- ("tp_compare", cmpfunc),
- ("tp_repr", reprfunc),
-
- # Method suites for standard classes
- ("tp_as_number", Ptr(PyNumberMethods)),
- ("tp_as_sequence", Ptr(PySequenceMethods)),
- ("tp_as_mapping", Ptr(PyMappingMethods)),
-
- # More standard operations (here for binary compatibility)
- ("tp_hash", hashfunc),
- ("tp_call", ternaryfunc),
- ("tp_str", reprfunc),
- ("tp_getattro", getattrofunc),
- ("tp_setattro", setattrofunc),
-
- # Functions to access object as input/output buffer
- ("tp_as_buffer", Ptr(PyBufferProcs)),
-
- # Flags to define presence of optional/expanded features
- ("tp_flags", lltype.Signed),
-
- ("tp_doc", rffi.CCHARP), # Documentation string
-
- # Assigned meaning in release 2.0
- # call function for all accessible objects
- ("tp_traverse", traverseproc),
-
- # delete references to contained objects
- ("tp_clear", inquiry),
-
- # Assigned meaning in release 2.1
- # rich comparisons
- ("tp_richcompare", richcmpfunc),
-
- # weak reference enabler
- ("tp_weaklistoffset", Py_ssize_t),
-
- # Added in release 2.2
- # Iterators
- ("tp_iter", getiterfunc),
- ("tp_iternext", iternextfunc),
-
- # Attribute descriptor and subclassing stuff
- ("tp_methods", Ptr(PyMethodDef)),
- ("tp_members", Ptr(PyMemberDef)),
- ("tp_getset", Ptr(PyGetSetDef)),
- ("tp_base", Ptr(PyTypeObject)),
- ("tp_dict", PyObject),
- ("tp_descr_get", descrgetfunc),
- ("tp_descr_set", descrsetfunc),
- ("tp_dictoffset", Py_ssize_t), # can be ignored in PyPy
- ("tp_init", initproc),
- ("tp_alloc", allocfunc),
- ("tp_new", newfunc),
- ("tp_free", freefunc), # Low-level free-memory routine
- ("tp_is_gc", inquiry), # For PyObject_IS_GC
- ("tp_bases", PyObject),
- ("tp_mro", PyObject), # method resolution order
- ("tp_cache", PyObject),
- ("tp_subclasses", PyObject),
- ("tp_weaklist", PyObject),
- ("tp_del", destructor),
- ])
-cpython_struct("PyTypeObject", PyTypeObjectFields, PyTypeObject)
-
+from pypy.module.cpyext.typeobjectdefs import PyTypeObjectPtr, PyTypeObject, \
+ PyGetSetDef
+from pypy.module.cpyext.slotdefs import slotdefs
class W_GetSetPropertyEx(GetSetProperty): # XXX fix this to be rpython
@@ -194,21 +59,46 @@
w_descr = PyDescr_NewGetSet(space, getset, pto)
dict_w[name] = w_descr
+def add_operators(space, dict_w, pto):
+ # XXX support PyObject_HashNotImplemented
+ state = space.fromcache(State)
+ for method_name, slot_name, _, wrapper_func, doc, flags in state.slotdefs: # XXX use UI
+ if method_name in dict_w or wrapper_func is None:
+ continue
+ # XXX is this rpython?
+ if len(slot_name) == 1:
+ func = getattr(pto, slot_name[0])
+ else:
+ assert len(slot_name) == 2
+ struct = getattr(pto, slot_name[0])
+ if not struct:
+ continue
+ func = getattr(struct, slot_name[1])
+ func_voidp = rffi.cast(rffi.VOIDP_real, func)
+ if not func:
+ continue
+ dict_w[method_name] = PyDescr_NewWrapper(space, pto, method_name, wrapper_func,
+ doc, flags, func_voidp)
+
class W_PyCTypeObject(W_TypeObject):
def __init__(self, space, pto):
self.pto = pto
bases_w = []
dict_w = {}
+
+ add_operators(space, dict_w, pto)
convert_method_defs(space, dict_w, pto.c_tp_methods, pto)
convert_getset_defs(space, dict_w, pto.c_tp_getset, pto)
# XXX missing: convert_member_defs
+
full_name = rffi.charp2str(pto.c_tp_name)
module_name, extension_name = full_name.split(".", 1)
dict_w["__module__"] = space.wrap(module_name)
+
W_TypeObject.__init__(self, space, extension_name,
bases_w or [space.w_object], dict_w)
- self.__flags__ = _CPYTYPE
+ self.__flags__ = _CPYTYPE # mainly disables lookup optimizations
class W_PyCObject(Wrappable):
def __init__(self, space):
Added: pypy/branch/cpython-extension/pypy/module/cpyext/typeobjectdefs.py
==============================================================================
--- (empty file)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/typeobjectdefs.py Sat Mar 27 17:04:54 2010
@@ -0,0 +1,223 @@
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.rpython.lltypesystem.lltype import Ptr, FuncType, Void
+from pypy.module.cpyext.api import cpython_api, cpython_api_c, cpython_struct, \
+ PyObject, PyVarObjectFields, Py_ssize_t, Py_TPFLAGS_READYING, \
+ Py_TPFLAGS_READY, Py_TPFLAGS_HEAPTYPE, make_ref, \
+ PyStringObject, ADDR, from_ref
+from pypy.module.cpyext.modsupport import PyMethodDef
+
+
+PyTypeObject = lltype.ForwardReference()
+PyTypeObjectPtr = lltype.Ptr(PyTypeObject)
+PyCFunction = Ptr(FuncType([PyObject, PyObject], PyObject))
+P, FT, PyO = Ptr, FuncType, PyObject
+PyOPtr = Ptr(lltype.Array(PyO, hints={'nolength': True}))
+
+
+# XXX
+PyBufferProcs = PyMemberDef = rffi.VOIDP.TO
+
+freefunc = P(FT([rffi.VOIDP_real], Void))
+destructor = P(FT([PyO], Void))
+printfunc = P(FT([PyO, rffi.VOIDP_real, rffi.INT_real], rffi.INT))
+getattrfunc = P(FT([PyO, rffi.CCHARP], PyO))
+getattrofunc = P(FT([PyO, PyO], PyO))
+setattrfunc = P(FT([PyO, rffi.CCHARP, PyO], rffi.INT_real))
+setattrofunc = P(FT([PyO, PyO, PyO], rffi.INT_real))
+cmpfunc = P(FT([PyO, PyO], rffi.INT_real))
+reprfunc = P(FT([PyO], PyO))
+hashfunc = P(FT([PyO], lltype.Signed))
+richcmpfunc = P(FT([PyO, PyO, rffi.INT_real], PyO))
+getiterfunc = P(FT([PyO], PyO))
+iternextfunc = P(FT([PyO], PyO))
+descrgetfunc = P(FT([PyO, PyO, PyO], PyO))
+descrsetfunc = P(FT([PyO, PyO, PyO], rffi.INT_real))
+initproc = P(FT([PyO, PyO, PyO], rffi.INT_real))
+newfunc = P(FT([PyTypeObjectPtr, PyO, PyO], PyO))
+allocfunc = P(FT([PyTypeObjectPtr, Py_ssize_t], PyO))
+unaryfunc = P(FT([PyO], PyO))
+binaryfunc = P(FT([PyO, PyO], PyO))
+ternaryfunc = P(FT([PyO, PyO, PyO], PyO))
+inquiry = P(FT([PyO], rffi.INT_real))
+lenfunc = P(FT([PyO], Py_ssize_t))
+coercion = P(FT([PyOPtr, PyOPtr], rffi.INT_real))
+intargfunc = P(FT([PyO, rffi.INT_real], PyO))
+intintargfunc = P(FT([PyO, rffi.INT_real, rffi.INT], PyO))
+ssizeargfunc = P(FT([PyO, Py_ssize_t], PyO))
+ssizessizeargfunc = P(FT([PyO, Py_ssize_t, Py_ssize_t], PyO))
+intobjargproc = P(FT([PyO, rffi.INT_real, PyO], rffi.INT))
+intintobjargproc = P(FT([PyO, rffi.INT_real, rffi.INT, PyO], rffi.INT))
+ssizeobjargproc = P(FT([PyO, Py_ssize_t, PyO], rffi.INT_real))
+ssizessizeobjargproc = P(FT([PyO, Py_ssize_t, Py_ssize_t, PyO], rffi.INT_real))
+objobjargproc = P(FT([PyO, PyO, PyO], rffi.INT_real))
+
+objobjproc = P(FT([PyO, PyO], rffi.INT_real))
+visitproc = P(FT([PyO, rffi.VOIDP_real], rffi.INT_real))
+traverseproc = P(FT([PyO, visitproc, rffi.VOIDP_real], rffi.INT_real))
+
+getter = P(FT([PyO, rffi.VOIDP_real], PyO))
+setter = P(FT([PyO, PyO, rffi.VOIDP_real], rffi.INT_real))
+
+wrapperfunc = P(FT([PyO, PyO, rffi.VOIDP_real], PyO))
+wrapperfunc_kwds = P(FT([PyO, PyO, rffi.VOIDP_real, PyO], PyO))
+
+
+PyGetSetDef = cpython_struct("PyGetSetDef", (
+ ("name", rffi.CCHARP),
+ ("get", getter),
+ ("set", setter),
+ ("doc", rffi.CCHARP),
+ ("closure", rffi.VOIDP_real),
+))
+
+PyNumberMethods = cpython_struct("PyNumberMethods", (
+ ("nb_add", binaryfunc),
+ ("nb_subtract", binaryfunc),
+ ("nb_multiply", binaryfunc),
+ ("nb_divide", binaryfunc),
+ ("nb_remainder", binaryfunc),
+ ("nb_divmod", binaryfunc),
+ ("nb_power", ternaryfunc),
+ ("nb_negative", unaryfunc),
+ ("nb_positive", unaryfunc),
+ ("nb_absolute", unaryfunc),
+ ("nb_nonzero", inquiry),
+ ("nb_invert", unaryfunc),
+ ("nb_lshift", binaryfunc),
+ ("nb_rshift", binaryfunc),
+ ("nb_and", binaryfunc),
+ ("nb_xor", binaryfunc),
+ ("nb_or", binaryfunc),
+ ("nb_coerce", coercion),
+ ("nb_int", unaryfunc),
+ ("nb_long", unaryfunc),
+ ("nb_float", unaryfunc),
+ ("nb_oct", unaryfunc),
+ ("nb_hex", unaryfunc),
+ ("nb_inplace_add", binaryfunc),
+ ("nb_inplace_subtract", binaryfunc),
+ ("nb_inplace_multiply", binaryfunc),
+ ("nb_inplace_divide", binaryfunc),
+ ("nb_inplace_remainder", binaryfunc),
+ ("nb_inplace_power", ternaryfunc),
+ ("nb_inplace_lshift", binaryfunc),
+ ("nb_inplace_rshift", binaryfunc),
+ ("nb_inplace_and", binaryfunc),
+ ("nb_inplace_xor", binaryfunc),
+ ("nb_inplace_or", binaryfunc),
+
+ ("nb_floor_divide", binaryfunc),
+ ("nb_true_divide", binaryfunc),
+ ("nb_inplace_floor_divide", binaryfunc),
+ ("nb_inplace_true_divide", binaryfunc),
+
+ ("nb_index", unaryfunc),
+))
+
+PySequenceMethods = cpython_struct("PySequenceMethods", (
+ ("sq_length", lenfunc),
+ ("sq_concat", binaryfunc),
+ ("sq_repeat", ssizeargfunc),
+ ("sq_item", ssizeargfunc),
+ ("sq_slice", ssizessizeargfunc),
+ ("sq_ass_item", ssizeobjargproc),
+ ("sq_ass_slice", ssizessizeobjargproc),
+ ("sq_contains", objobjproc),
+ ("sq_inplace_concat", binaryfunc),
+ ("sq_inplace_repeat", ssizeargfunc),
+))
+
+PyMappingMethods = cpython_struct("PyMappingMethods", (
+ ("mp_length", lenfunc),
+ ("mp_subscript", binaryfunc),
+ ("mp_ass_subscript", objobjargproc),
+))
+
+"""
+PyBufferProcs = cpython_struct("PyBufferProcs", (
+ ("bf_getreadbuffer", readbufferproc),
+ ("bf_getwritebuffer", writebufferproc),
+ ("bf_getsegcount", segcountproc),
+ ("bf_getcharbuffer", charbufferproc),
+ ("bf_getbuffer", getbufferproc),
+ ("bf_releasebuffer", releasebufferproc),
+))
+"""
+
+PyTypeObjectFields = []
+PyTypeObjectFields.extend(PyVarObjectFields)
+PyTypeObjectFields.extend([
+ ("tp_name", rffi.CCHARP), # For printing, in format "<module>.<name>"
+ ("tp_basicsize", Py_ssize_t), ("tp_itemsize", Py_ssize_t), # For allocation
+
+ # Methods to implement standard operations
+ ("tp_dealloc", destructor),
+ ("tp_print", printfunc),
+ ("tp_getattr", getattrfunc),
+ ("tp_setattr", setattrfunc),
+ ("tp_compare", cmpfunc),
+ ("tp_repr", reprfunc),
+
+ # Method suites for standard classes
+ ("tp_as_number", Ptr(PyNumberMethods)),
+ ("tp_as_sequence", Ptr(PySequenceMethods)),
+ ("tp_as_mapping", Ptr(PyMappingMethods)),
+
+ # More standard operations (here for binary compatibility)
+ ("tp_hash", hashfunc),
+ ("tp_call", ternaryfunc),
+ ("tp_str", reprfunc),
+ ("tp_getattro", getattrofunc),
+ ("tp_setattro", setattrofunc),
+
+ # Functions to access object as input/output buffer
+ ("tp_as_buffer", Ptr(PyBufferProcs)),
+
+ # Flags to define presence of optional/expanded features
+ ("tp_flags", lltype.Signed),
+
+ ("tp_doc", rffi.CCHARP), # Documentation string
+
+ # Assigned meaning in release 2.0
+ # call function for all accessible objects
+ ("tp_traverse", traverseproc),
+
+ # delete references to contained objects
+ ("tp_clear", inquiry),
+
+ # Assigned meaning in release 2.1
+ # rich comparisons
+ ("tp_richcompare", richcmpfunc),
+
+ # weak reference enabler
+ ("tp_weaklistoffset", Py_ssize_t),
+
+ # Added in release 2.2
+ # Iterators
+ ("tp_iter", getiterfunc),
+ ("tp_iternext", iternextfunc),
+
+ # Attribute descriptor and subclassing stuff
+ ("tp_methods", Ptr(PyMethodDef)),
+ ("tp_members", Ptr(PyMemberDef)),
+ ("tp_getset", Ptr(PyGetSetDef)),
+ ("tp_base", Ptr(PyTypeObject)),
+ ("tp_dict", PyObject),
+ ("tp_descr_get", descrgetfunc),
+ ("tp_descr_set", descrsetfunc),
+ ("tp_dictoffset", Py_ssize_t), # can be ignored in PyPy
+ ("tp_init", initproc),
+ ("tp_alloc", allocfunc),
+ ("tp_new", newfunc),
+ ("tp_free", freefunc), # Low-level free-memory routine
+ ("tp_is_gc", inquiry), # For PyObject_IS_GC
+ ("tp_bases", PyObject),
+ ("tp_mro", PyObject), # method resolution order
+ ("tp_cache", PyObject),
+ ("tp_subclasses", PyObject),
+ ("tp_weaklist", PyObject),
+ ("tp_del", destructor),
+ ])
+cpython_struct("PyTypeObject", PyTypeObjectFields, PyTypeObject)
+
+
More information about the Pypy-commit
mailing list