Author: Matti Picus <[email protected]>
Branch: pypy-pyarray
Changeset: r67002:95c2319fa157
Date: 2013-09-18 17:07 +0300
http://bitbucket.org/pypy/pypy/changeset/95c2319fa157/
Log: add c test, fix PyNumber_Coerce{,Ex} including PyDecRef example code
for successful call since coerce returns new object
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -338,7 +338,7 @@
return api_function.error_value
if not we_are_translated():
got_integer = isinstance(res, (int, long, float))
- assert got_integer == expect_integer
+ assert got_integer == expect_integer,'got %r not
integer' % res
if res is None:
return None
elif isinstance(res, Reference):
diff --git a/pypy/module/cpyext/number.py b/pypy/module/cpyext/number.py
--- a/pypy/module/cpyext/number.py
+++ b/pypy/module/cpyext/number.py
@@ -3,6 +3,7 @@
from pypy.module.cpyext.pyobject import PyObject, PyObjectP, from_ref,
make_ref, Py_DecRef
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.tool.sourcetools import func_with_new_name
+from pypy.module.cpyext.state import State
@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL)
def PyIndex_Check(space, w_obj):
@@ -56,24 +57,17 @@
"""
return space.index(w_obj)
-@cpython_api([PyObjectP, PyObjectP], rffi.INT_real, error=-1)
+@cpython_api([PyObjectP, PyObjectP], rffi.INT_real, error=CANNOT_FAIL)
def PyNumber_CoerceEx(space, pp1, pp2):
"""This function is similar to PyNumber_Coerce(), except that it returns
1 when the conversion is not possible and when no error is raised.
Reference counts are still not increased in this case."""
- w_obj1 = from_ref(space, pp1[0])
- w_obj2 = from_ref(space, pp2[0])
- w_res = space.try_coerce(w_obj1, w_obj2)
- if w_res is None:
+ retVal = PyNumber_Coerce(space, pp1, pp2)
+ if retVal != 0:
return 1
- else:
- Py_DecRef(space, pp1[0])
- Py_DecRef(space, pp2[0])
- pp1[0] = make_ref(space, space.getitem(w_res, space.wrap(0)))
- pp2[0] = make_ref(space, space.getitem(w_res, space.wrap(1)))
- return 0
+ return 0
-@cpython_api([PyObjectP, PyObjectP], rffi.INT_real, error=-1)
+@cpython_api([PyObjectP, PyObjectP], rffi.INT_real, error=CANNOT_FAIL)
def PyNumber_Coerce(space, pp1, pp2):
"""This function takes the addresses of two variables of type PyObject*.
If
the objects pointed to by *p1 and *p2 have the same type, increment their
@@ -85,15 +79,16 @@
Python statement o1, o2 = coerce(o1, o2)."""
w_obj1 = from_ref(space, pp1[0])
w_obj2 = from_ref(space, pp2[0])
- w_res = space.coerce(w_obj1, w_obj2)
- if w_res is None:
+ try:
+ w_res = space.coerce(w_obj1, w_obj2)
+ except (TypeError, OperationError):
+ state = space.fromcache(State)
+ state.clear_exception()
return -1
- else:
- Py_DecRef(space, pp1[0])
- Py_DecRef(space, pp2[0])
- pp1[0] = make_ref(space, space.getitem(w_res, space.wrap(0)))
- pp2[0] = make_ref(space, space.getitem(w_res, space.wrap(1)))
- return 0
+ w_res1, w_res2 = space.unpackiterable(w_res, 2)
+ pp1[0] = make_ref(space, w_res1)
+ pp2[0] = make_ref(space, w_res2)
+ return 0
def func_rename(newname):
return lambda func: func_with_new_name(func, newname)
diff --git a/pypy/module/cpyext/test/test_number.py
b/pypy/module/cpyext/test/test_number.py
--- a/pypy/module/cpyext/test/test_number.py
+++ b/pypy/module/cpyext/test/test_number.py
@@ -1,6 +1,7 @@
from rpython.rtyper.lltypesystem import lltype
from pypy.module.cpyext.test.test_api import BaseApiTest
from pypy.module.cpyext.pyobject import PyObjectP, from_ref, make_ref,
Py_DecRef
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
class TestIterator(BaseApiTest):
def test_check(self, space, api):
@@ -46,10 +47,10 @@
assert space.str_w(space.repr(from_ref(space, pp2[0]))) == '456.789'
Py_DecRef(space, pp1[0])
Py_DecRef(space, pp2[0])
- # Yes, decrement twice.
+ lltype.free(pp1, flavor='raw')
+ # Yes, decrement twice since we decoupled between w_obj* and pp*[0].
Py_DecRef(space, w_obj1)
Py_DecRef(space, w_obj2)
- lltype.free(pp1, flavor='raw')
lltype.free(pp2, flavor='raw')
def test_number_coerce_ex(self, space, api):
@@ -67,6 +68,8 @@
assert api.PyFloat_Check(w_res)
assert space.unwrap(w_res) == 123.
+ Py_DecRef(space, pl)
+ Py_DecRef(space, pf)
Py_DecRef(space, ppl[0])
Py_DecRef(space, ppf[0])
lltype.free(ppl, flavor='raw')
@@ -97,3 +100,40 @@
api.PyNumber_Power(space.wrap(3), space.wrap(2), space.wrap(5)))
assert 9 == space.unwrap(
api.PyNumber_InPlacePower(space.wrap(3), space.wrap(2),
space.w_None))
+
+class AppTestCNumber(AppTestCpythonExtensionBase):
+ def test_app_coerce(self):
+ mod = self.import_extension('foo', [
+ ("test_fail", "METH_NOARGS",
+ '''
+ PyObject * hello = PyString_FromString("hello");
+ PyObject * float1 = PyFloat_FromDouble(1.0);
+ int retVal = PyNumber_Coerce(&hello, &float1);
+ Py_DECREF(hello);
+ Py_DECREF(float1);
+ return PyInt_FromLong(retVal);
+ '''),
+ ("test", "METH_NOARGS",
+ '''
+ PyObject * float1p = PyFloat_FromDouble(1.0);
+ PyObject * int3p = PyInt_FromLong(3);
+ PyObject * tupl = PyTuple_New(2);
+ PyObject float1 = *float1p;
+ PyObject int3 = *int3p;
+ int retVal = PyNumber_CoerceEx(&int3p, &float1p);
+ if (retVal == 0)
+ {
+ PyTuple_SET_ITEM(tupl, 0, int3p);
+ PyTuple_SET_ITEM(tupl, 1, float1p);
+ }
+ Py_DECREF(&int3);
+ Py_DECREF(&float1);
+ Py_DECREF(int3p);
+ Py_DECREF(float1p);
+ return tupl;
+ ''')])
+ assert mod.test_fail() == -1
+ '''tupl = mod.test()
+ assert tupl[0] == 3.
+ assert tupl[1] == 1.
+ assert isinstance(tupl[0], float)'''
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit