[pypy-commit] pypy cpyext-ext: Test and fix (for nb_float only for now)

arigo pypy.commits at gmail.com
Tue Mar 1 14:16:38 EST 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: cpyext-ext
Changeset: r82641:359d2065421a
Date: 2016-03-01 20:03 +0100
http://bitbucket.org/pypy/pypy/changeset/359d2065421a/

Log:	Test and fix (for nb_float only for now)

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
@@ -349,10 +349,6 @@
     return space.int(w_self)
 
 @cpython_api([PyObject], PyObject, header=None)
-def slot_nb_float(space, w_self):
-    return space.float(w_self)
-
- at cpython_api([PyObject], PyObject, header=None)
 def slot_tp_iter(space, w_self):
     return space.iter(w_self)
 
@@ -406,6 +402,16 @@
         def slot_tp_getattro(space, w_self, w_name):
             return space.call_function(getattr_fn, w_self, w_name)
         api_func = slot_tp_getattro.api_func
+    elif name == 'tp_as_number.c_nb_float':
+        float_fn = w_type.getdictvalue(space, '__float__')
+        if float_fn is None:
+            return
+
+        @cpython_api([PyObject], PyObject, header=header)
+        @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name))
+        def slot_nb_float(space, w_self):
+            return space.call_function(float_fn, w_self)
+        api_func = slot_nb_float.api_func
     else:
         return
 
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
@@ -487,21 +487,36 @@
 
     def test_nb_float(self):
         module = self.import_extension('foo', [
-            ("nb_float", "METH_O",
+            ("nb_float", "METH_VARARGS",
              '''
-                 if (!args->ob_type->tp_as_number ||
-                     !args->ob_type->tp_as_number->nb_float)
+                 PyTypeObject *type = (PyTypeObject *)PyTuple_GET_ITEM(args, 0);
+                 PyObject *obj = PyTuple_GET_ITEM(args, 1);
+                 if (!type->tp_as_number ||
+                     !type->tp_as_number->nb_float)
                  {
                      PyErr_SetNone(PyExc_ValueError);
                      return NULL;
                  }
-                 return args->ob_type->tp_as_number->nb_float(args);
+                 return type->tp_as_number->nb_float(obj);
              '''
              )
             ])
-        assert module.nb_float(10) == 10.0
-        assert module.nb_float(-12.3) == -12.3
-        raises(ValueError, module.nb_float, "123")
+        assert module.nb_float(int, 10) == 10.0
+        assert module.nb_float(float, -12.3) == -12.3
+        raises(ValueError, module.nb_float, str, "123")
+        #
+        # check that calling PyInt_Type->tp_as_number->nb_float(x)
+        # does not invoke a user-defined __float__()
+        class I(int):
+            def __float__(self):
+                return -55.55
+        class F(float):
+            def __float__(self):
+                return -66.66
+        assert float(I(10)) == -55.55
+        assert float(F(10.5)) == -66.66
+        assert module.nb_float(int, I(10)) == 10.0
+        assert module.nb_float(float, F(10.5)) == 10.5
 
     def test_tp_call(self):
         module = self.import_extension('foo', [


More information about the pypy-commit mailing list