gh-107455: ctypes: Improve error messages when converting to an incompatible type (#107456)

This commit is contained in:
Tomas R 2023-08-03 07:29:03 +02:00 committed by GitHub
parent 1cd479c6d3
commit 62a3a15119
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 11 deletions

View File

@ -4,8 +4,8 @@ import sys
import unittest
from ctypes import (CDLL, Structure, Array, CFUNCTYPE,
byref, POINTER, pointer, ArgumentError,
c_char, c_wchar, c_byte, c_char_p,
c_short, c_int, c_long, c_longlong,
c_char, c_wchar, c_byte, c_char_p, c_wchar_p,
c_short, c_int, c_long, c_longlong, c_void_p,
c_float, c_double, c_longdouble)
from _ctypes import _Pointer, _SimpleCData
@ -92,6 +92,54 @@ class FunctionTestCase(unittest.TestCase):
"argument 2: TypeError: one character unicode string "
"expected")
def test_c_char_p_parm(self):
"""Test the error message when converting an incompatible type to c_char_p."""
proto = CFUNCTYPE(c_int, c_char_p)
def callback(*args):
return 0
callback = proto(callback)
self.assertEqual(callback(b"abc"), 0)
with self.assertRaises(ArgumentError) as cm:
callback(10)
self.assertEqual(str(cm.exception),
"argument 1: TypeError: 'int' object cannot be "
"interpreted as ctypes.c_char_p")
def test_c_wchar_p_parm(self):
"""Test the error message when converting an incompatible type to c_wchar_p."""
proto = CFUNCTYPE(c_int, c_wchar_p)
def callback(*args):
return 0
callback = proto(callback)
self.assertEqual(callback("abc"), 0)
with self.assertRaises(ArgumentError) as cm:
callback(10)
self.assertEqual(str(cm.exception),
"argument 1: TypeError: 'int' object cannot be "
"interpreted as ctypes.c_wchar_p")
def test_c_void_p_parm(self):
"""Test the error message when converting an incompatible type to c_void_p."""
proto = CFUNCTYPE(c_int, c_void_p)
def callback(*args):
return 0
callback = proto(callback)
self.assertEqual(callback(5), 0)
with self.assertRaises(ArgumentError) as cm:
callback(2.5)
self.assertEqual(str(cm.exception),
"argument 1: TypeError: 'float' object cannot be "
"interpreted as ctypes.c_void_p")
def test_wchar_result(self):
f = dll._testfunc_i_bhilfd
f.argtypes = [c_byte, c_short, c_int, c_long, c_float, c_double]

View File

@ -0,0 +1,3 @@
Improve error messages when converting an incompatible type to
:class:`ctypes.c_char_p`, :class:`ctypes.c_wchar_p` and
:class:`ctypes.c_void_p`.

View File

@ -1728,9 +1728,9 @@ c_wchar_p_from_param(PyObject *type, PyObject *value)
Py_DECREF(as_parameter);
return value;
}
/* XXX better message */
PyErr_SetString(PyExc_TypeError,
"wrong type");
PyErr_Format(PyExc_TypeError,
"'%.200s' object cannot be interpreted "
"as ctypes.c_wchar_p", Py_TYPE(value)->tp_name);
return NULL;
}
@ -1792,9 +1792,9 @@ c_char_p_from_param(PyObject *type, PyObject *value)
Py_DECREF(as_parameter);
return value;
}
/* XXX better message */
PyErr_SetString(PyExc_TypeError,
"wrong type");
PyErr_Format(PyExc_TypeError,
"'%.200s' object cannot be interpreted "
"as ctypes.c_char_p", Py_TYPE(value)->tp_name);
return NULL;
}
@ -1927,9 +1927,9 @@ c_void_p_from_param(PyObject *type, PyObject *value)
Py_DECREF(as_parameter);
return value;
}
/* XXX better message */
PyErr_SetString(PyExc_TypeError,
"wrong type");
PyErr_Format(PyExc_TypeError,
"'%.200s' object cannot be interpreted "
"as ctypes.c_void_p", Py_TYPE(value)->tp_name);
return NULL;
}