Author: mattip <matti.pi...@gmail.com> Branch: cpyext-ext Changeset: r83281:6bf99bc91614 Date: 2016-03-22 22:03 +0200 http://bitbucket.org/pypy/pypy/changeset/6bf99bc91614/
Log: test, implement slot for __pow__, which is called 'ternary' but accepts two arguments as well diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py --- a/pypy/module/cpyext/slotdefs.py +++ b/pypy/module/cpyext/slotdefs.py @@ -7,7 +7,7 @@ cpython_api, generic_cpy_call, PyObject, Py_ssize_t, Py_TPFLAGS_CHECKTYPES, mangle_name, pypy_decl) from pypy.module.cpyext.typeobjectdefs import ( - unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc, + unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc, ternaryfunc, getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc, inquiry, ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc, cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, objobjargproc, @@ -43,6 +43,17 @@ "expected %d arguments, got %d", n, space.len_w(w_ob)) +def check_num_argsv(space, w_ob, low, high): + from pypy.module.cpyext.tupleobject import PyTuple_CheckExact + if not PyTuple_CheckExact(space, w_ob): + raise OperationError(space.w_SystemError, + space.wrap("PyArg_UnpackTuple() argument list is not a tuple")) + if low <=space.len_w(w_ob) <= high: + return + raise oefmt(space.w_TypeError, + "expected %d-%d arguments, got %d", + low, high, space.len_w(w_ob)) + def wrap_init(space, w_self, w_args, func, w_kwargs): func_init = rffi.cast(initproc, func) res = generic_cpy_call(space, func_init, w_self, w_args, w_kwargs) @@ -85,6 +96,33 @@ Py_DecRef(space, ref) return generic_cpy_call(space, func_binary, args_w[0], w_self) +def wrap_ternaryfunc(space, w_self, w_args, func): + # The third argument is optional + func_ternary = rffi.cast(ternaryfunc, func) + check_num_argsv(space, w_args, 1, 2) + args_w = space.fixedview(w_args) + arg3 = space.w_None + if len(args_w) > 1: + arg3 = args_w[1] + return generic_cpy_call(space, func_ternary, w_self, args_w[0], arg3) + +def wrap_ternaryfunc_r(space, w_self, w_args, func): + # The third argument is optional + func_ternary = rffi.cast(ternaryfunc, func) + check_num_argsv(space, w_args, 1, 2) + args_w = space.fixedview(w_args) + ref = make_ref(space, w_self) + if (not ref.c_ob_type.c_tp_flags & Py_TPFLAGS_CHECKTYPES and + not space.is_true(space.issubtype(space.type(args_w[0]), + space.type(w_self)))): + return space.w_NotImplemented + Py_DecRef(space, ref) + arg3 = space.w_None + if len(args_w) > 1: + arg3 = args_w[1] + return generic_cpy_call(space, func_ternary, args_w[0], w_self, arg3) + + def wrap_inquirypred(space, w_self, w_args, func): func_inquiry = rffi.cast(inquiry, func) check_num_args(space, w_args, 0) diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -775,7 +775,7 @@ raises(SystemError, bool, module.newInt(-1)) raises(ValueError, bool, module.newInt(-42)) - def test_binaryfunc(self): + def test_mathfunc(self): module = self.import_extension('foo', [ ("newInt", "METH_VARARGS", """ @@ -788,6 +788,7 @@ IntLike_Type.tp_as_number = &intlike_as_number; IntLike_Type.tp_flags |= Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES; intlike_as_number.nb_add = intlike_nb_add; + intlike_as_number.nb_power = intlike_nb_pow; if (PyType_Ready(&IntLike_Type) < 0) return NULL; intObj = PyObject_New(IntLikeObject, &IntLike_Type); if (!intObj) { @@ -814,8 +815,9 @@ intObjNoOp->ival = intval; return (PyObject *)intObjNoOp; - """)], + """)], prologue= """ + #include <math.h> typedef struct { PyObject_HEAD @@ -835,6 +837,19 @@ return PyInt_FromLong(val1+val2); } + static PyObject * + intlike_nb_pow(PyObject *self, PyObject *other, PyObject * z) + { + long val2, val1 = ((IntLikeObject *)(self))->ival; + if (PyInt_Check(other)) { + long val2 = PyInt_AsLong(other); + return PyInt_FromLong(val1+val2); + } + + val2 = ((IntLikeObject *)(other))->ival; + return PyInt_FromLong((int)pow(val1,val2)); + } + PyTypeObject IntLike_Type = { PyObject_HEAD_INIT(0) /*ob_size*/ 0, @@ -863,6 +878,7 @@ assert (a + b) == 3 assert (b + c) == 5 assert (d + a) == 5 + assert pow(d,b) == 16 def test_tp_new_in_subclass_of_type(self): module = self.import_module(name='foo3') _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit