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

Reply via email to