diff options
author | Armin Rigo <arigo@tunes.org> | 2012-11-29 17:54:31 -0800 |
---|---|---|
committer | Armin Rigo <arigo@tunes.org> | 2012-11-29 17:54:31 -0800 |
commit | d20eaf7d123376bd2fe22ed0723c4da3281a453c (patch) | |
tree | dc89626a15809f2cc556b8088268a7e9d05eb52d | |
parent | 249faab4740790359142e40e183bf44e99be1c60 (diff) | |
download | cffi-d20eaf7d123376bd2fe22ed0723c4da3281a453c.tar.gz |
Generalize the error reporting: attach the name of the current
function/struct when we get any error.
-rw-r--r-- | cffi/model.py | 4 | ||||
-rw-r--r-- | cffi/vengine_cpy.py | 27 | ||||
-rw-r--r-- | cffi/vengine_gen.py | 30 | ||||
-rw-r--r-- | testing/test_verify.py | 12 |
4 files changed, 44 insertions, 29 deletions
diff --git a/cffi/model.py b/cffi/model.py index 73d8495..3bc1a7c 100644 --- a/cffi/model.py +++ b/cffi/model.py @@ -405,3 +405,7 @@ def global_cache(srctype, ffi, funcname, *args): def pointer_cache(ffi, BType): return global_cache('?', ffi, 'new_pointer_type', BType) + +def attach_exception_info(e, name): + if e.args and type(e.args[0]) is str: + e.args = ('%s: %s' % (name, e.args[0]),) + e.args[1:] diff --git a/cffi/vengine_cpy.py b/cffi/vengine_cpy.py index 96522ce..e832a06 100644 --- a/cffi/vengine_cpy.py +++ b/cffi/vengine_cpy.py @@ -163,13 +163,21 @@ class VCPythonEngine(object): except AttributeError: raise ffiplatform.VerificationError( "not implemented in verify(): %r" % name) - method(tp, realname) + try: + method(tp, realname) + except Exception, e: + model.attach_exception_info(e, name) + raise def _load(self, module, step_name, **kwds): for name, tp in self._get_declarations(): kind, realname = name.split(' ', 1) method = getattr(self, '_%s_cpy_%s' % (step_name, kind)) - method(tp, realname, module, **kwds) + try: + method(tp, realname, module, **kwds) + except Exception, e: + model.attach_exception_info(e, name) + raise def _generate_nothing(self, tp, name): pass @@ -221,7 +229,7 @@ class VCPythonEngine(object): tovar, tp.get_c_name(''), errvalue)) self._prnt(' %s;' % errcode) - def _convert_expr_from_c(self, tp, var, where): + def _convert_expr_from_c(self, tp, var, context): if isinstance(tp, model.PrimitiveType): if tp.is_integer_type(): if tp.is_signed_type(): @@ -242,7 +250,7 @@ class VCPythonEngine(object): elif isinstance(tp, model.StructType): if tp.fldnames is None: raise TypeError("'%s' is used as %s, but is opaque" % ( - tp._get_c_name(''), where)) + tp._get_c_name(''), context)) return '_cffi_from_c_struct((char *)&%s, _cffi_type(%d))' % ( var, self._gettypenum(tp)) elif isinstance(tp, model.EnumType): @@ -328,8 +336,7 @@ class VCPythonEngine(object): # if result_code: prnt(' return %s;' % - self._convert_expr_from_c(tp.result, 'result', - 'result of %s()' % name)) + self._convert_expr_from_c(tp.result, 'result', 'result type')) else: prnt(' Py_INCREF(Py_None);') prnt(' return Py_None;') @@ -464,8 +471,8 @@ class VCPythonEngine(object): def check(realvalue, expectedvalue, msg): if realvalue != expectedvalue: raise ffiplatform.VerificationError( - "in %s: %s (we have %d, but C compiler says %d)" - % (cname, msg, expectedvalue, realvalue)) + "%s (we have %d, but C compiler says %d)" + % (msg, expectedvalue, realvalue)) ffi = self.ffi BStruct = ffi._get_cached_btype(tp) layout, cname = self._struct_pending_verification.pop(tp) @@ -534,7 +541,7 @@ class VCPythonEngine(object): realexpr = name prnt(' i = (%s);' % (realexpr,)) prnt(' o = %s;' % (self._convert_expr_from_c(tp, 'i', - 'type of %s' % name),)) + 'variable type'),)) assert delayed else: prnt(' if (LONG_MIN <= (%s) && (%s) <= LONG_MAX)' % (name, name)) @@ -584,7 +591,7 @@ class VCPythonEngine(object): for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): prnt(' if (%s != %d) {' % (enumerator, enumvalue)) prnt(' PyErr_Format(_cffi_VerificationError,') - prnt(' "in enum %s: %s has the real value %d, ' + prnt(' "enum %s: %s has the real value %d, ' 'not %d",') prnt(' "%s", "%s", (int)%s, %d);' % ( name, enumerator, enumerator, enumvalue)) diff --git a/cffi/vengine_gen.py b/cffi/vengine_gen.py index e100062..389181c 100644 --- a/cffi/vengine_gen.py +++ b/cffi/vengine_gen.py @@ -78,13 +78,21 @@ class VGenericEngine(object): except AttributeError: raise ffiplatform.VerificationError( "not implemented in verify(): %r" % name) - method(tp, realname) + try: + method(tp, realname) + except Exception, e: + model.attach_exception_info(e, name) + raise def _load(self, module, step_name, **kwds): for name, tp in self._get_declarations(): kind, realname = name.split(' ', 1) method = getattr(self, '_%s_gen_%s' % (step_name, kind)) - method(tp, realname, module, **kwds) + try: + method(tp, realname, module, **kwds) + except Exception, e: + model.attach_exception_info(e, name) + raise def _generate_nothing(self, tp, name): pass @@ -154,11 +162,7 @@ class VGenericEngine(object): indirect_args.append(type) tp = model.FunctionPtrType(tuple(indirect_args), tp.result, tp.ellipsis) - try: - BFunc = self.ffi._get_cached_btype(tp) - except TypeError, e: - msg = 'function %s(): %s' % (name, e) - raise TypeError(msg) + BFunc = self.ffi._get_cached_btype(tp) wrappername = '_cffi_f_%s' % name newfunction = module.load_function(BFunc, wrappername) for i, type in indirections: @@ -280,8 +284,8 @@ class VGenericEngine(object): def check(realvalue, expectedvalue, msg): if realvalue != expectedvalue: raise ffiplatform.VerificationError( - "in %s: %s (we have %d, but C compiler says %d)" - % (cname, msg, expectedvalue, realvalue)) + "%s (we have %d, but C compiler says %d)" + % (msg, expectedvalue, realvalue)) ffi = self.ffi BStruct = ffi._get_cached_btype(tp) layout, cname = self._struct_pending_verification.pop(tp) @@ -390,10 +394,10 @@ class VGenericEngine(object): prnt('{') for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): prnt(' if (%s != %d) {' % (enumerator, enumvalue)) - prnt(' snprintf(out_error, 255, "in enum %s: ' - '%s has the real value %d, not %d",') - prnt(' "%s", "%s", (int)%s, %d);' % ( - name, enumerator, enumerator, enumvalue)) + prnt(' snprintf(out_error, 255,' + '"%s has the real value %d, not %d",') + prnt(' "%s", (int)%s, %d);' % ( + enumerator, enumerator, enumvalue)) prnt(' return -1;') prnt(' }') prnt(' return 0;') diff --git a/testing/test_verify.py b/testing/test_verify.py index 513e03a..409e613 100644 --- a/testing/test_verify.py +++ b/testing/test_verify.py @@ -368,13 +368,13 @@ def test_ffi_full_struct(): e = py.test.raises(VerificationError, ffi.verify, "struct foo_s { int y; char x; long *z; };") assert str(e.value) == ( - "in struct foo_s: wrong offset for field 'x'" + "struct foo_s: wrong offset for field 'x'" " (we have 0, but C compiler says 4)") # e = py.test.raises(VerificationError, ffi.verify, "struct foo_s { char x; int y; long *z; char extra; };") assert str(e.value) == ( - "in struct foo_s: wrong total size" + "struct foo_s: wrong total size" " (we have %d, but C compiler says %d)" % ( ffi.sizeof("struct foo_s"), ffi.sizeof("struct foo_s") + ffi.sizeof("long*"))) @@ -387,7 +387,7 @@ def test_ffi_full_struct(): e = py.test.raises(VerificationError, ffi.verify, "struct foo_s { char x; short pad; short y; long *z; };") assert str(e.value) == ( - "in struct foo_s: wrong size for field 'y'" + "struct foo_s: wrong size for field 'y'" " (we have 4, but C compiler says 2)") def test_ffi_nonfull_struct(): @@ -566,7 +566,7 @@ def test_full_enum(): py.test.raises(VerificationError, ffi.verify, "enum ee { EE1, EE2 };") e = py.test.raises(VerificationError, ffi.verify, "enum ee { EE1, EE3, EE2 };") - assert str(e.value) == 'in enum ee: EE2 has the real value 2, not 1' + assert str(e.value) == 'enum ee: EE2 has the real value 2, not 1' # extra items cannot be seen and have no bad consequence anyway lib = ffi.verify("enum ee { EE1, EE2, EE3, EE4 };") assert lib.EE3 == 2 @@ -1395,5 +1395,5 @@ def test_struct_returned_by_func(): "typedef struct { int x; } foo_t; " "foo_t myfunc(void) { foo_t x = { 42 }; return x; }") assert str(e.value) in [ - "'foo_t' is used as result of myfunc(), but is opaque", - "function myfunc(): result type 'struct $foo_t' is opaque"] + "function myfunc: 'foo_t' is used as result type, but is opaque", + "function myfunc: result type 'struct $foo_t' is opaque"] |