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
