[pypy-commit] cffi default: Delay reporting NotImplmentedErrors when building function types with
arigo
noreply at buildbot.pypy.org
Fri Jan 2 19:16:29 CET 2015
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r1619:275285b314a7
Date: 2015-01-02 19:16 +0100
http://bitbucket.org/cffi/cffi/changeset/275285b314a7/
Log: Delay reporting NotImplmentedErrors when building function types
with unsupported arguments. They are now reported only when we
actually try to do a call. Issue #127.
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -4095,24 +4095,26 @@
cf = (CFieldObject *)ct->ct_extra;
for (i=0; i<n; i++) {
Py_ssize_t flat;
- CTypeDescrObject *ct;
+ CTypeDescrObject *ct1;
assert(cf != NULL);
if (cf->cf_bitshift >= 0) {
- PyErr_SetString(PyExc_NotImplementedError,
- "cannot pass as argument or return value "
- "a struct with bit fields");
+ PyErr_Format(PyExc_NotImplementedError,
+ "ctype '%s' not supported as argument or return value"
+ " (it is a struct with bit fields)",
+ ct->ct_name);
return NULL;
}
flat = 1;
- ct = cf->cf_type;
- while (ct->ct_flags & CT_ARRAY) {
- flat *= ct->ct_length;
- ct = ct->ct_itemdescr;
+ ct1 = cf->cf_type;
+ while (ct1->ct_flags & CT_ARRAY) {
+ flat *= ct1->ct_length;
+ ct1 = ct1->ct_itemdescr;
}
if (flat <= 0) {
- PyErr_SetString(PyExc_NotImplementedError,
- "cannot pass as argument or return value "
- "a struct with a zero-length array");
+ PyErr_Format(PyExc_NotImplementedError,
+ "ctype '%s' not supported as argument or return value"
+ " (it is a struct with a zero-length array)",
+ ct->ct_name);
return NULL;
}
nflat += flat;
@@ -4382,11 +4384,6 @@
&fabi))
return NULL;
- if (fresult->ct_flags & CT_UNION) {
- PyErr_SetString(PyExc_NotImplementedError,
- "function returning a union");
- return NULL;
- }
if ((fresult->ct_size < 0 && !(fresult->ct_flags & CT_VOID)) ||
(fresult->ct_flags & CT_ARRAY)) {
char *msg;
@@ -4410,8 +4407,14 @@
cif_description_t *cif_descr;
cif_descr = fb_prepare_cif(fargs, fresult, fabi);
- if (cif_descr == NULL)
- goto error;
+ if (cif_descr == NULL) {
+ if (PyErr_ExceptionMatches(PyExc_NotImplementedError)) {
+ PyErr_Clear(); /* will get the exception if we see an
+ actual call */
+ }
+ else
+ goto error;
+ }
fct->ct_extra = (char *)cif_descr;
}
@@ -4646,8 +4649,9 @@
cif_descr = (cif_description_t *)ct->ct_extra;
if (cif_descr == NULL) {
- PyErr_SetString(PyExc_NotImplementedError,
- "callbacks with '...'");
+ PyErr_Format(PyExc_NotImplementedError,
+ "%s: callback with unsupported argument or "
+ "return type or with '...'", ct->ct_name);
goto error;
}
if (ffi_prep_closure(closure, &cif_descr->cif,
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -1041,11 +1041,12 @@
BInt = new_primitive_type("int")
BArray0 = new_array_type(new_pointer_type(BInt), 0)
BStruct = new_struct_type("struct foo")
+ BStructP = new_pointer_type(BStruct)
complete_struct_or_union(BStruct, [('a', BArray0)])
- py.test.raises(NotImplementedError, new_function_type,
- (BStruct,), BInt, False)
- py.test.raises(NotImplementedError, new_function_type,
- (BInt,), BStruct, False)
+ BFunc = new_function_type((BStruct,), BInt, False)
+ py.test.raises(NotImplementedError, cast(BFunc, 123), cast(BStructP, 123))
+ BFunc2 = new_function_type((BInt,), BStruct, False)
+ py.test.raises(NotImplementedError, cast(BFunc2, 123), 123)
def test_call_function_9():
BInt = new_primitive_type("int")
@@ -1816,7 +1817,8 @@
new_function_type((), new_pointer_type(BFunc))
BUnion = new_union_type("union foo_u")
complete_struct_or_union(BUnion, [])
- py.test.raises(NotImplementedError, new_function_type, (), BUnion)
+ BFunc = new_function_type((), BUnion)
+ py.test.raises(NotImplementedError, cast(BFunc, 123))
py.test.raises(TypeError, new_function_type, (), BArray)
def test_struct_return_in_func():
diff --git a/testing/test_ffi_backend.py b/testing/test_ffi_backend.py
--- a/testing/test_ffi_backend.py
+++ b/testing/test_ffi_backend.py
@@ -19,8 +19,8 @@
ffi.cdef("struct foo_s { int a,b,c,d,e; int x:1; };")
e = py.test.raises(NotImplementedError, ffi.callback,
"struct foo_s foo(void)", lambda: 42)
- assert str(e.value) == ("<struct foo_s(*)(void)>: "
- "cannot pass as argument or return value a struct with bit fields")
+ assert str(e.value) == ("struct foo_s(*)(): "
+ "callback with unsupported argument or return type or with '...'")
def test_inspecttype(self):
ffi = FFI(backend=self.Backend())
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -2069,3 +2069,20 @@
ffi2.cdef("int foo;")
lib2 = ffi2.verify("int foo;", flags=ffi2.RTLD_GLOBAL | ffi2.RTLD_LAZY)
return lib2
+
+def test_consider_not_implemented_function_type():
+ ffi = FFI()
+ ffi.cdef("typedef union { int a; float b; } Data;"
+ "typedef struct { int a:2; } MyStr;"
+ "typedef void (*foofunc_t)(Data);"
+ "typedef MyStr (*barfunc_t)(void);")
+ fooptr = ffi.cast("foofunc_t", 123)
+ barptr = ffi.cast("barfunc_t", 123)
+ # assert did not crash so far
+ e = py.test.raises(NotImplementedError, fooptr, ffi.new("Data *"))
+ assert str(e.value) == (
+ "ctype 'Data' not supported as argument or return value")
+ e = py.test.raises(NotImplementedError, barptr)
+ assert str(e.value) == (
+ "ctype 'MyStr' not supported as argument or return value "
+ "(it is a struct with bit fields)")
More information about the pypy-commit
mailing list