Commits

Armin Rigo  committed 909b497

Generalize the error reporting: attach the name of the current
function/struct when we get any error.

  • Participants
  • Parent commits 5498063

Comments (0)

Files changed (4)

File cffi/model.py

 
 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:]

File cffi/vengine_cpy.py

             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
             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():
         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):
         #
         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;')
             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)
                 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))
         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))

File cffi/vengine_gen.py

             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
                     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:
             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)
         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;')

File testing/test_verify.py

     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*")))
     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():
     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
                        "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"]