Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb4e11a7

Browse files
gh-99266: ctypes: Preserve more detailed exception inArgumentError
Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
1 parent13566a3 commitb4e11a7

File tree

5 files changed

+83
-7
lines changed

5 files changed

+83
-7
lines changed

‎Doc/library/ctypes.rst‎

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,14 @@ integer, string, bytes, a :mod:`ctypes` instance, or an object with an
466466
Return types
467467
^^^^^^^^^^^^
468468

469+
..testsetup::
470+
471+
from ctypes import CDLL, c_char, c_char_p
472+
from ctypes.util import find_library
473+
libc = CDLL(find_library('c'))
474+
strchr = libc.strchr
475+
476+
469477
By default functions are assumed to return the C:c:expr:`int` type. Other
470478
return types can be specified by setting the:attr:`restype` attribute of the
471479
function object.
@@ -502,18 +510,19 @@ If you want to avoid the ``ord("x")`` calls above, you can set the
502510
:attr:`argtypes` attribute, and the second argument will be converted from a
503511
single character Python bytes object into a C char::
504512

513+
..doctest::
514+
505515
>>>strchr.restype= c_char_p
506516
>>>strchr.argtypes= [c_char_p, c_char]
507517
>>>strchr(b"abcdef",b"d")
508-
'def'
518+
b'def'
509519
>>>strchr(b"abcdef",b"def")
510520
Traceback (most recent call last):
511-
File "<stdin>", line 1, in <module>
512-
ArgumentError: argument 2: TypeError: one character string expected
521+
ctypes.ArgumentError: argument 2: TypeError: one character bytes, bytearray or integer expected
513522
>>>print(strchr(b"abcdef",b"x"))
514523
None
515524
>>>strchr(b"abcdef",b"d")
516-
'def'
525+
b'def'
517526
>>>
518527

519528
You can also use a callable Python object (a function or a class for example) as

‎Lib/test/test_ctypes/test_functions.py‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,23 @@ class X(object, _SimpleCData):
5454
classX(object,Structure):
5555
_fields_= []
5656

57+
deftest_c_char_parm(self):
58+
proto=CFUNCTYPE(c_int,c_char)
59+
defcallback(*args):
60+
return0
61+
62+
callback=proto(callback)
63+
64+
self.assertEqual(callback(b"a"),0)
65+
66+
withself.assertRaises(ArgumentError)ascm:
67+
callback(b"abc")
68+
69+
self.assertEqual(str(cm.exception),
70+
"argument 1: TypeError: one character bytes, "
71+
"bytearray or integer expected")
72+
73+
5774
@need_symbol('c_wchar')
5875
deftest_wchar_parm(self):
5976
f=dll._testfunc_i_bhilfd
@@ -62,6 +79,18 @@ def test_wchar_parm(self):
6279
self.assertEqual(result,139)
6380
self.assertEqual(type(result),int)
6481

82+
withself.assertRaises(ArgumentError)ascm:
83+
f(1,2,3,4,5.0,6.0)
84+
self.assertEqual(str(cm.exception),
85+
"argument 2: TypeError: unicode string expected "
86+
"instead of int instance")
87+
88+
withself.assertRaises(ArgumentError)ascm:
89+
f(1,"abc",3,4,5.0,6.0)
90+
self.assertEqual(str(cm.exception),
91+
"argument 2: TypeError: one character unicode string "
92+
"expected")
93+
6594
@need_symbol('c_wchar')
6695
deftest_wchar_result(self):
6796
f=dll._testfunc_i_bhilfd

‎Lib/test/test_ctypes/test_parameters.py‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,29 @@ def test_cw_strings(self):
7878
pa=c_wchar_p.from_param(c_wchar_p("123"))
7979
self.assertEqual(type(pa),c_wchar_p)
8080

81+
deftest_c_char(self):
82+
fromctypesimportc_char
83+
84+
withself.assertRaises(TypeError)ascm:
85+
c_char.from_param(b"abc")
86+
self.assertEqual(str(cm.exception),
87+
"one character bytes, bytearray or integer expected")
88+
89+
@need_symbol('c_wchar')
90+
deftest_c_wchar(self):
91+
fromctypesimportc_wchar
92+
93+
withself.assertRaises(TypeError)ascm:
94+
c_wchar.from_param("abc")
95+
self.assertEqual(str(cm.exception),
96+
"one character unicode string expected")
97+
98+
99+
withself.assertRaises(TypeError)ascm:
100+
c_wchar.from_param(123)
101+
self.assertEqual(str(cm.exception),
102+
"unicode string expected instead of int instance")
103+
81104
deftest_int_pointers(self):
82105
fromctypesimportc_short,c_uint,c_int,c_long,POINTER,pointer
83106
LPINT=POINTER(c_int)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Preserve more detailed error messages in:mod:`ctypes`.

‎Modules/_ctypes/_ctypes.c‎

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2197,6 +2197,7 @@ PyCSimpleType_from_param(PyObject *type, PyObject *value)
21972197
structfielddesc*fd;
21982198
PyObject*as_parameter;
21992199
intres;
2200+
PyObject*exc,*val,*tb;
22002201

22012202
/* If the value is already an instance of the requested type,
22022203
we can use it as is */
@@ -2230,24 +2231,37 @@ PyCSimpleType_from_param(PyObject *type, PyObject *value)
22302231
parg->obj=fd->setfunc(&parg->value,value,0);
22312232
if (parg->obj)
22322233
return (PyObject*)parg;
2233-
PyErr_Clear();
2234+
PyErr_Fetch(&exc,&val,&tb);
22342235
Py_DECREF(parg);
22352236

22362237
if (_PyObject_LookupAttr(value,&_Py_ID(_as_parameter_),&as_parameter)<0) {
2238+
Py_XDECREF(exc);
2239+
Py_XDECREF(val);
2240+
Py_XDECREF(tb);
22372241
returnNULL;
22382242
}
22392243
if (as_parameter) {
22402244
if (_Py_EnterRecursiveCall("while processing _as_parameter_")) {
22412245
Py_DECREF(as_parameter);
2246+
Py_XDECREF(exc);
2247+
Py_XDECREF(val);
2248+
Py_XDECREF(tb);
22422249
returnNULL;
22432250
}
22442251
value=PyCSimpleType_from_param(type,as_parameter);
22452252
_Py_LeaveRecursiveCall();
22462253
Py_DECREF(as_parameter);
2254+
Py_XDECREF(exc);
2255+
Py_XDECREF(val);
2256+
Py_XDECREF(tb);
22472257
returnvalue;
22482258
}
2249-
PyErr_SetString(PyExc_TypeError,
2250-
"wrong type");
2259+
if (exc) {
2260+
PyErr_Restore(exc,val,tb);
2261+
}
2262+
else {
2263+
PyErr_SetString(PyExc_TypeError,"wrong type");
2264+
}
22512265
returnNULL;
22522266
}
22532267

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp