cython-devel

changeset 1238:d0c4b0a150ca

Buffers: Better error messages + bugfix
author Dag Sverre Seljebotn <dagss@student.matnat.uio.no>
date Mon Oct 13 22:11:27 2008 +0200 (3 years ago)
parents aa87fed4f334
children 5a7f83a639f7
files Cython/Compiler/Buffer.py tests/run/bufaccess.pyx tests/run/numpy_test.pyx
line diff
1.1 --- a/Cython/Compiler/Buffer.py Sat Oct 11 19:00:26 2008 +0200 1.2 +++ b/Cython/Compiler/Buffer.py Mon Oct 13 22:11:27 2008 +0200 1.3 @@ -520,8 +520,7 @@ 1.4 1.5 def put_assert(cond, msg): 1.6 defcode.putln("if (!(%s)) {" % cond) 1.7 - msg += ", got '%s'" 1.8 - defcode.putln('PyErr_Format(PyExc_ValueError, "%s", ts);' % msg) 1.9 + defcode.putln('PyErr_Format(PyExc_ValueError, "Buffer dtype mismatch (%s)", __Pyx_DescribeTokenInFormatString(ts));' % msg) 1.10 defcode.putln("return NULL;") 1.11 defcode.putln("}") 1.12 1.13 @@ -583,14 +582,7 @@ 1.14 (char, ctype, against, ctype)) 1.15 defcode.putln("default: ok = 0;") 1.16 defcode.putln("}") 1.17 - defcode.putln("if (!ok) {") 1.18 - if dtype.typestring is not None: 1.19 - errmsg = "Buffer datatype mismatch (expected '%s', got '%%s')" % dtype.typestring 1.20 - else: 1.21 - errmsg = "Buffer datatype mismatch (rejecting on '%s')" 1.22 - defcode.putln('PyErr_Format(PyExc_ValueError, "%s", ts);' % errmsg) 1.23 - defcode.putln("return NULL;"); 1.24 - defcode.putln("}") 1.25 + put_assert("ok", "expected %s, got %%s" % dtype) 1.26 defcode.putln("++ts;") 1.27 elif complex_possible: 1.28 # Could be a struct representing a complex number, so allow 1.29 @@ -605,9 +597,7 @@ 1.30 real_t.declaration_code(""), 1.31 imag_t.declaration_code(""))) 1.32 defcode.putln('PyErr_SetString(PyExc_ValueError, "Cannot store complex number in \'%s\' as \'%s\' differs from \'%s\' in size.");' % ( 1.33 - dtype.declaration_code("", for_display=True), 1.34 - real_t.declaration_code("", for_display=True), 1.35 - imag_t.declaration_code("", for_display=True))) 1.36 + dtype, real_t, imag_t)) 1.37 defcode.putln("return NULL;") 1.38 defcode.putln("}") 1.39 check_real, check_imag = [x[2] for x in field_blocks] 1.40 @@ -624,21 +614,23 @@ 1.41 defcode.putln("int n, count;") 1.42 defcode.putln("ts = __Pyx_ConsumeWhitespace(ts); if (!ts) return NULL;") 1.43 1.44 - for n, type, checker in field_blocks: 1.45 + next_types = [x[1] for x in field_blocks[1:]] + ["end"] 1.46 + for (n, type, checker), next_type in zip(field_blocks, next_types): 1.47 if n == 1: 1.48 defcode.putln("if (*ts == '1') ++ts;") 1.49 else: 1.50 defcode.putln("n = %d;" % n); 1.51 defcode.putln("do {") 1.52 defcode.putln("ts = __Pyx_ParseTypestringRepeat(ts, &count); n -= count;") 1.53 + put_assert("n >= 0", "expected %s, got %%s" % next_type) 1.54 1.55 simple = type.is_simple_buffer_dtype() 1.56 if not simple: 1.57 - put_assert("*ts == 'T' && *(ts+1) == '{'", "Expected start of %s" % type.declaration_code("", for_display=True)) 1.58 + put_assert("*ts == 'T' && *(ts+1) == '{'", "expected %s, got %%s" % type) 1.59 defcode.putln("ts += 2;") 1.60 defcode.putln("ts = %s(ts); if (!ts) return NULL;" % checker) 1.61 if not simple: 1.62 - put_assert("*ts == '}'", "Expected end of '%s'" % type.declaration_code("", for_display=True)) 1.63 + put_assert("*ts == '}'", "expected end of %s struct, got %%s" % type) 1.64 defcode.putln("++ts;") 1.65 1.66 if n > 1: 1.67 @@ -689,7 +681,8 @@ 1.68 if (!ts) goto fail; 1.69 if (*ts != 0) { 1.70 PyErr_Format(PyExc_ValueError, 1.71 - "Buffer format string specifies more data than '%(dtype_name)s' can hold (expected end, got '%%s')", ts); 1.72 + "Buffer dtype mismatch (expected end, got %%s)", 1.73 + __Pyx_DescribeTokenInFormatString(ts)); 1.74 goto fail; 1.75 } 1.76 } else { 1.77 @@ -822,6 +815,7 @@ 1.78 static INLINE void __Pyx_ZeroBuffer(Py_buffer* buf); /*proto*/ 1.79 static INLINE const char* __Pyx_ConsumeWhitespace(const char* ts); /*proto*/ 1.80 static void __Pyx_BufferNdimError(Py_buffer* buffer, int expected_ndim); /*proto*/ 1.81 +static const char* __Pyx_DescribeTokenInFormatString(const char* ts); /*proto*/ 1.82 """, """ 1.83 static INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) { 1.84 if (info->buf == NULL) return; 1.85 @@ -864,6 +858,34 @@ 1.86 expected_ndim, buffer->ndim); 1.87 } 1.88 1.89 +static const char* __Pyx_DescribeTokenInFormatString(const char* ts) { 1.90 + switch (*ts) { 1.91 + case 'b': return "char"; 1.92 + case 'B': return "unsigned char"; 1.93 + case 'h': return "short"; 1.94 + case 'H': return "unsigned short"; 1.95 + case 'i': return "int"; 1.96 + case 'I': return "unsigned int"; 1.97 + case 'l': return "long"; 1.98 + case 'L': return "unsigned long"; 1.99 + case 'q': return "long long"; 1.100 + case 'Q': return "unsigned long long"; 1.101 + case 'f': return "float"; 1.102 + case 'd': return "double"; 1.103 + case 'g': return "long double"; 1.104 + case 'Z': switch (*(ts+1)) { 1.105 + case 'f': return "complex float"; 1.106 + case 'd': return "complex double"; 1.107 + case 'g': return "complex long double"; 1.108 + default: return "unparseable format string"; 1.109 + } 1.110 + case 'T': return "a struct"; 1.111 + case 'O': return "Python object"; 1.112 + case 'P': return "a pointer"; 1.113 + default: return "unparseable format string"; 1.114 + } 1.115 +} 1.116 + 1.117 """] 1.118 1.119
2.1 --- a/tests/run/bufaccess.pyx Sat Oct 11 19:00:26 2008 +0200 2.2 +++ b/tests/run/bufaccess.pyx Mon Oct 13 22:11:27 2008 +0200 2.3 @@ -373,14 +373,14 @@ 2.4 @testcase 2.5 def wrong_string(object[int] buf): 2.6 """ 2.7 - >>> wrong_string(IntMockBuffer(None, [1,2], format="iasdf")) 2.8 + >>> wrong_string(IntMockBuffer(None, [1,2], format="if")) 2.9 Traceback (most recent call last): 2.10 ... 2.11 - ValueError: Buffer format string specifies more data than 'int' can hold (expected end, got 'asdf') 2.12 + ValueError: Buffer dtype mismatch (expected end, got float) 2.13 >>> wrong_string(IntMockBuffer(None, [1,2], format="$$")) 2.14 Traceback (most recent call last): 2.15 ... 2.16 - ValueError: Buffer datatype mismatch (expected 'i', got '$$') 2.17 + ValueError: Buffer dtype mismatch (expected int, got unparseable format string) 2.18 """ 2.19 print buf[1] 2.20 2.21 @@ -532,7 +532,7 @@ 2.22 >>> fmtst1(IntMockBuffer("A", range(3))) 2.23 Traceback (most recent call last): 2.24 ... 2.25 - ValueError: Buffer datatype mismatch (expected 'f', got 'i') 2.26 + ValueError: Buffer dtype mismatch (expected float, got int) 2.27 """ 2.28 cdef object[float] a = buf 2.29 2.30 @@ -542,7 +542,7 @@ 2.31 >>> fmtst2(FloatMockBuffer("A", range(3))) 2.32 Traceback (most recent call last): 2.33 ... 2.34 - ValueError: Buffer datatype mismatch (expected 'i', got 'f') 2.35 + ValueError: Buffer dtype mismatch (expected int, got float) 2.36 """ 2.37 2.38 @testcase 2.39 @@ -849,7 +849,7 @@ 2.40 >>> printbuf_td_cy_int(ShortMockBuffer(None, range(3)), (3,)) 2.41 Traceback (most recent call last): 2.42 ... 2.43 - ValueError: Buffer datatype mismatch (rejecting on 'h') 2.44 + ValueError: Buffer dtype mismatch (expected bufaccess.td_cy_int, got short) 2.45 2.46 """ 2.47 cdef int i 2.48 @@ -865,7 +865,7 @@ 2.49 >>> printbuf_td_h_short(IntMockBuffer(None, range(3)), (3,)) 2.50 Traceback (most recent call last): 2.51 ... 2.52 - ValueError: Buffer datatype mismatch (rejecting on 'i') 2.53 + ValueError: Buffer dtype mismatch (expected bufaccess.td_h_short, got int) 2.54 """ 2.55 cdef int i 2.56 for i in range(shape[0]): 2.57 @@ -880,7 +880,7 @@ 2.58 >>> printbuf_td_h_cy_short(IntMockBuffer(None, range(3)), (3,)) 2.59 Traceback (most recent call last): 2.60 ... 2.61 - ValueError: Buffer datatype mismatch (rejecting on 'i') 2.62 + ValueError: Buffer dtype mismatch (expected bufaccess.td_h_cy_short, got int) 2.63 """ 2.64 cdef int i 2.65 for i in range(shape[0]): 2.66 @@ -895,7 +895,7 @@ 2.67 >>> printbuf_td_h_ushort(ShortMockBuffer(None, range(3)), (3,)) 2.68 Traceback (most recent call last): 2.69 ... 2.70 - ValueError: Buffer datatype mismatch (rejecting on 'h') 2.71 + ValueError: Buffer dtype mismatch (expected bufaccess.td_h_ushort, got short) 2.72 """ 2.73 cdef int i 2.74 for i in range(shape[0]): 2.75 @@ -910,7 +910,7 @@ 2.76 >>> printbuf_td_h_double(FloatMockBuffer(None, [0.25, 1, 3.125]), (3,)) 2.77 Traceback (most recent call last): 2.78 ... 2.79 - ValueError: Buffer datatype mismatch (rejecting on 'f') 2.80 + ValueError: Buffer dtype mismatch (expected bufaccess.td_h_double, got float) 2.81 """ 2.82 cdef int i 2.83 for i in range(shape[0]): 2.84 @@ -1328,10 +1328,14 @@ 2.85 1 2 3 4 5 2.86 >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="bbqii")) 2.87 1 2 3 4 5 2.88 + >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="23bqii")) 2.89 + Traceback (most recent call last): 2.90 + ... 2.91 + ValueError: Buffer dtype mismatch (expected long long, got char) 2.92 >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="i")) 2.93 Traceback (most recent call last): 2.94 ... 2.95 - ValueError: Buffer datatype mismatch (expected 'b', got 'i') 2.96 + ValueError: Buffer dtype mismatch (expected char, got int) 2.97 """ 2.98 print buf[0].a, buf[0].b, buf[0].c, buf[0].d, buf[0].e 2.99 2.100 @@ -1345,7 +1349,11 @@ 2.101 >>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="iiiii")) 2.102 Traceback (most recent call last): 2.103 ... 2.104 - ValueError: Expected start of SmallStruct, got 'iiiii' 2.105 + ValueError: Buffer dtype mismatch (expected SmallStruct, got int) 2.106 + >>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="T{iii}T{ii}i")) 2.107 + Traceback (most recent call last): 2.108 + ... 2.109 + ValueError: Buffer dtype mismatch (expected end of SmallStruct struct, got int) 2.110 """ 2.111 print buf[0].x.a, buf[0].x.b, buf[0].y.a, buf[0].y.b, buf[0].z 2.112
3.1 --- a/tests/run/numpy_test.pyx Sat Oct 11 19:00:26 2008 +0200 3.2 +++ b/tests/run/numpy_test.pyx Mon Oct 13 22:11:27 2008 +0200 3.3 @@ -144,7 +144,7 @@ 3.4 ]))) 3.5 Traceback (most recent call last): 3.6 ... 3.7 - ValueError: Buffer datatype mismatch (expected 'i', got 'f}T{ii}') 3.8 + ValueError: Buffer dtype mismatch (expected int, got float) 3.9 3.10 >>> test_good_cast() 3.11 True