From 4f06d604c40f12a1d59e3bfda061f3dd7bce6e45 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 9 Aug 2014 09:33:05 +0300 Subject: [PATCH] Issue #22161: Conformed arguments type checks in ctype to actually supported types. Corrected error messages about bytes arguments. --- Lib/ctypes/__init__.py | 4 ++-- Lib/ctypes/test/test_buffers.py | 4 ++++ Lib/ctypes/test/test_bytes.py | 15 +++++++++++++++ Lib/ctypes/test/test_structures.py | 2 +- Modules/_ctypes/_ctypes.c | 27 +++++---------------------- Modules/_ctypes/cfield.c | 6 +++--- 6 files changed, 30 insertions(+), 28 deletions(-) diff --git a/Lib/ctypes/__init__.py b/Lib/ctypes/__init__.py index e34c646e2d1..5c803ffcb39 100644 --- a/Lib/ctypes/__init__.py +++ b/Lib/ctypes/__init__.py @@ -49,7 +49,7 @@ def create_string_buffer(init, size=None): create_string_buffer(anInteger) -> character array create_string_buffer(aString, anInteger) -> character array """ - if isinstance(init, (str, bytes)): + if isinstance(init, bytes): if size is None: size = len(init)+1 buftype = c_char * size @@ -284,7 +284,7 @@ def create_unicode_buffer(init, size=None): create_unicode_buffer(anInteger) -> character array create_unicode_buffer(aString, anInteger) -> character array """ - if isinstance(init, (str, bytes)): + if isinstance(init, str): if size is None: size = len(init)+1 buftype = c_wchar * size diff --git a/Lib/ctypes/test/test_buffers.py b/Lib/ctypes/test/test_buffers.py index 8fa883cc528..166faaf4e4b 100644 --- a/Lib/ctypes/test/test_buffers.py +++ b/Lib/ctypes/test/test_buffers.py @@ -21,6 +21,8 @@ class StringBufferTestCase(unittest.TestCase): self.assertEqual(b[::2], b"ac") self.assertEqual(b[::5], b"a") + self.assertRaises(TypeError, create_string_buffer, "abc") + def test_buffer_interface(self): self.assertEqual(len(bytearray(create_string_buffer(0))), 0) self.assertEqual(len(bytearray(create_string_buffer(1))), 1) @@ -43,6 +45,8 @@ class StringBufferTestCase(unittest.TestCase): self.assertEqual(b[::2], "ac") self.assertEqual(b[::5], "a") + self.assertRaises(TypeError, create_unicode_buffer, b"abc") + @need_symbol('c_wchar') def test_unicode_conversion(self): b = create_unicode_buffer("abc") diff --git a/Lib/ctypes/test/test_bytes.py b/Lib/ctypes/test/test_bytes.py index 363b3f84b6a..20fa0565034 100644 --- a/Lib/ctypes/test/test_bytes.py +++ b/Lib/ctypes/test/test_bytes.py @@ -6,27 +6,40 @@ from ctypes import * class BytesTest(unittest.TestCase): def test_c_char(self): x = c_char(b"x") + self.assertRaises(TypeError, c_char, "x") x.value = b"y" + with self.assertRaises(TypeError): + x.value = "y" c_char.from_param(b"x") + self.assertRaises(TypeError, c_char.from_param, "x") (c_char * 3)(b"a", b"b", b"c") + self.assertRaises(TypeError, c_char * 3, "a", "b", "c") def test_c_wchar(self): x = c_wchar("x") + self.assertRaises(TypeError, c_wchar, b"x") x.value = "y" + with self.assertRaises(TypeError): + x.value = b"y" c_wchar.from_param("x") + self.assertRaises(TypeError, c_wchar.from_param, b"x") (c_wchar * 3)("a", "b", "c") + self.assertRaises(TypeError, c_wchar * 3, b"a", b"b", b"c") def test_c_char_p(self): c_char_p(b"foo bar") + self.assertRaises(TypeError, c_char_p, "foo bar") def test_c_wchar_p(self): c_wchar_p("foo bar") + self.assertRaises(TypeError, c_wchar_p, b"foo bar") def test_struct(self): class X(Structure): _fields_ = [("a", c_char * 3)] x = X(b"abc") + self.assertRaises(TypeError, X, "abc") self.assertEqual(x.a, b"abc") self.assertEqual(type(x.a), bytes) @@ -35,6 +48,7 @@ class BytesTest(unittest.TestCase): _fields_ = [("a", c_wchar * 3)] x = X("abc") + self.assertRaises(TypeError, X, b"abc") self.assertEqual(x.a, "abc") self.assertEqual(type(x.a), str) @@ -46,5 +60,6 @@ class BytesTest(unittest.TestCase): BSTR("abc") + if __name__ == '__main__': unittest.main() diff --git a/Lib/ctypes/test/test_structures.py b/Lib/ctypes/test/test_structures.py index d1acc92b347..84d456c3cc3 100644 --- a/Lib/ctypes/test/test_structures.py +++ b/Lib/ctypes/test/test_structures.py @@ -322,7 +322,7 @@ class StructureTestCase(unittest.TestCase): self.assertEqual(cls, RuntimeError) self.assertEqual(msg, "(Phone) : " - "expected string, int found") + "expected bytes, int found") cls, msg = self.get_except(Person, b"Someone", (b"a", b"b", b"c")) self.assertEqual(cls, RuntimeError) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 01adbb5655a..fd00e5338cf 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -1080,7 +1080,7 @@ CharArray_set_raw(CDataObject *self, PyObject *value) ptr = view.buf; if (size > self->b_size) { PyErr_SetString(PyExc_ValueError, - "string too long"); + "byte string too long"); goto fail; } @@ -1132,7 +1132,7 @@ CharArray_set_value(CDataObject *self, PyObject *value) size = PyBytes_GET_SIZE(value); if (size > self->b_size) { PyErr_SetString(PyExc_ValueError, - "string too long"); + "byte string too long"); Py_DECREF(value); return -1; } @@ -1471,7 +1471,7 @@ c_wchar_p_from_param(PyObject *type, PyObject *value) Py_INCREF(Py_None); return Py_None; } - if (PyUnicode_Check(value) || PyBytes_Check(value)) { + if (PyUnicode_Check(value)) { PyCArgObject *parg; struct fielddesc *fd = _ctypes_get_fielddesc("Z"); @@ -1623,25 +1623,8 @@ c_void_p_from_param(PyObject *type, PyObject *value) return (PyObject *)parg; } /* XXX struni: remove later */ -/* string */ - if (PyBytes_Check(value)) { - PyCArgObject *parg; - struct fielddesc *fd = _ctypes_get_fielddesc("z"); - - parg = PyCArgObject_new(); - if (parg == NULL) - return NULL; - parg->pffi_type = &ffi_type_pointer; - parg->tag = 'z'; - parg->obj = fd->setfunc(&parg->value, value, 0); - if (parg->obj == NULL) { - Py_DECREF(parg); - return NULL; - } - return (PyObject *)parg; - } /* bytes */ - if (PyByteArray_Check(value)) { + if (PyBytes_Check(value)) { PyCArgObject *parg; struct fielddesc *fd = _ctypes_get_fielddesc("z"); @@ -3218,7 +3201,7 @@ _get_name(PyObject *obj, char **pname) return *pname ? 1 : 0; } PyErr_SetString(PyExc_TypeError, - "function name must be string or integer"); + "function name must be string, bytes object or integer"); return 0; } diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c index 79d60f3728d..2078291731d 100644 --- a/Modules/_ctypes/cfield.c +++ b/Modules/_ctypes/cfield.c @@ -1160,7 +1160,7 @@ c_set(void *ptr, PyObject *value, Py_ssize_t size) } error: PyErr_Format(PyExc_TypeError, - "one character string expected"); + "one character bytes, bytearray or integer expected"); return NULL; } @@ -1295,7 +1295,7 @@ s_set(void *ptr, PyObject *value, Py_ssize_t length) Py_INCREF(value); } else { PyErr_Format(PyExc_TypeError, - "expected string, %s found", + "expected bytes, %s found", value->ob_type->tp_name); return NULL; } @@ -1311,7 +1311,7 @@ s_set(void *ptr, PyObject *value, Py_ssize_t length) ++size; } else if (size > length) { PyErr_Format(PyExc_ValueError, - "string too long (%zd, maximum length %zd)", + "bytes too long (%zd, maximum length %zd)", size, length); Py_DECREF(value); return NULL;