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

Commitd9d6909

Browse files
gh-115011: Improve support of __index__() in setters of members with unsigned integer type (GH-115029)
Setters for members with an unsigned integer type now supportthe same range of valid values for objects that has a __index__()method as for int.Previously, Py_T_UINT, Py_T_ULONG and Py_T_ULLONG did not supportobjects that has a __index__() method larger than LONG_MAX.Py_T_ULLONG did not support negative ints. Now it supports them andemits a RuntimeWarning.
1 parentd2c4baa commitd9d6909

File tree

3 files changed

+61
-67
lines changed

3 files changed

+61
-67
lines changed

‎Lib/test/test_capi/test_structmembers.py‎

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -81,36 +81,22 @@ def _test_int_range(self, name, minval, maxval, *, hardlimit=None,
8181
self._test_warn(name,maxval+1,minval)
8282
self._test_warn(name,hardmaxval)
8383

84-
ifindexlimitisNone:
85-
indexlimit=hardlimit
86-
ifnotindexlimit:
84+
ifindexlimitisFalse:
8785
self.assertRaises(TypeError,setattr,ts,name,Index(minval))
8886
self.assertRaises(TypeError,setattr,ts,name,Index(maxval))
8987
else:
90-
hardminindexval,hardmaxindexval=indexlimit
9188
self._test_write(name,Index(minval),minval)
92-
ifminval<hardminindexval:
93-
self._test_write(name,Index(hardminindexval),hardminindexval)
94-
ifmaxval<hardmaxindexval:
95-
self._test_write(name,Index(maxval),maxval)
96-
else:
97-
self._test_write(name,Index(hardmaxindexval),hardmaxindexval)
98-
self._test_overflow(name,Index(hardminindexval-1))
99-
ifnamein ('T_UINT','T_ULONG'):
100-
self.assertRaises(TypeError,setattr,self.ts,name,
101-
Index(hardmaxindexval+1))
102-
self.assertRaises(TypeError,setattr,self.ts,name,
103-
Index(2**1000))
104-
else:
105-
self._test_overflow(name,Index(hardmaxindexval+1))
106-
self._test_overflow(name,Index(2**1000))
89+
self._test_write(name,Index(maxval),maxval)
90+
self._test_overflow(name,Index(hardminval-1))
91+
self._test_overflow(name,Index(hardmaxval+1))
92+
self._test_overflow(name,Index(2**1000))
10793
self._test_overflow(name,Index(-2**1000))
108-
ifhardminindexval<minvalandname!='T_ULONGLONG':
109-
self._test_warn(name,Index(hardminindexval))
110-
self._test_warn(name,Index(minval-1))
111-
ifmaxval<hardmaxindexval:
112-
self._test_warn(name,Index(maxval+1))
113-
self._test_warn(name,Index(hardmaxindexval))
94+
ifhardminval<minval:
95+
self._test_warn(name,Index(hardminval))
96+
self._test_warn(name,Index(minval-1),maxval)
97+
ifmaxval<hardmaxval:
98+
self._test_warn(name,Index(maxval+1),minval)
99+
self._test_warn(name,Index(hardmaxval))
114100

115101
deftest_bool(self):
116102
ts=self.ts
@@ -138,22 +124,20 @@ def test_int(self):
138124
self._test_int_range('T_INT',INT_MIN,INT_MAX,
139125
hardlimit=(LONG_MIN,LONG_MAX))
140126
self._test_int_range('T_UINT',0,UINT_MAX,
141-
hardlimit=(LONG_MIN,ULONG_MAX),
142-
indexlimit=(LONG_MIN,LONG_MAX))
127+
hardlimit=(LONG_MIN,ULONG_MAX))
143128

144129
deftest_long(self):
145130
self._test_int_range('T_LONG',LONG_MIN,LONG_MAX)
146131
self._test_int_range('T_ULONG',0,ULONG_MAX,
147-
hardlimit=(LONG_MIN,ULONG_MAX),
148-
indexlimit=(LONG_MIN,LONG_MAX))
132+
hardlimit=(LONG_MIN,ULONG_MAX))
149133

150134
deftest_py_ssize_t(self):
151135
self._test_int_range('T_PYSSIZET',PY_SSIZE_T_MIN,PY_SSIZE_T_MAX,indexlimit=False)
152136

153137
deftest_longlong(self):
154138
self._test_int_range('T_LONGLONG',LLONG_MIN,LLONG_MAX)
155139
self._test_int_range('T_ULONGLONG',0,ULLONG_MAX,
156-
indexlimit=(LONG_MIN,LONG_MAX))
140+
hardlimit=(LONG_MIN,ULLONG_MAX))
157141

158142
deftest_bad_assignments(self):
159143
ts=self.ts
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Setters for members with an unsigned integer type now support the same range
2+
of valid values for objects that has a:meth:`~object.__index__` method as
3+
for:class:`int`.

‎Python/structmember.c‎

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
/* Map C struct members to Python object attributes */
33

44
#include"Python.h"
5+
#include"pycore_abstract.h"// _PyNumber_Index()
6+
#include"pycore_long.h"// _PyLong_IsNegative()
57

68

79
PyObject*
@@ -200,27 +202,22 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
200202
casePy_T_UINT: {
201203
/* XXX: For compatibility, accept negative int values
202204
as well. */
203-
intoverflow;
204-
longlong_val=PyLong_AsLongAndOverflow(v,&overflow);
205-
if (long_val==-1&&PyErr_Occurred()) {
206-
return-1;
207-
}
208-
if (overflow<0) {
209-
PyErr_SetString(PyExc_OverflowError,
210-
"Python int too large to convert to C long");
205+
v=_PyNumber_Index(v);
206+
if (v==NULL) {
211207
return-1;
212208
}
213-
elseif (!overflow) {
214-
*(unsignedint*)addr= (unsignedint)(unsigned long)long_val;
215-
if (long_val<0) {
216-
WARN("Writing negative value into unsigned field");
217-
}
218-
elseif ((unsigned long)long_val>UINT_MAX) {
219-
WARN("Truncation of value to unsigned short");
209+
if (_PyLong_IsNegative((PyLongObject*)v)) {
210+
longlong_val=PyLong_AsLong(v);
211+
Py_DECREF(v);
212+
if (long_val==-1&&PyErr_Occurred()) {
213+
return-1;
220214
}
215+
*(unsignedint*)addr= (unsignedint)(unsigned long)long_val;
216+
WARN("Writing negative value into unsigned field");
221217
}
222218
else {
223219
unsigned longulong_val=PyLong_AsUnsignedLong(v);
220+
Py_DECREF(v);
224221
if (ulong_val== (unsigned long)-1&&PyErr_Occurred()) {
225222
return-1;
226223
}
@@ -240,24 +237,22 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
240237
casePy_T_ULONG: {
241238
/* XXX: For compatibility, accept negative int values
242239
as well. */
243-
intoverflow;
244-
longlong_val=PyLong_AsLongAndOverflow(v,&overflow);
245-
if (long_val==-1&&PyErr_Occurred()) {
246-
return-1;
247-
}
248-
if (overflow<0) {
249-
PyErr_SetString(PyExc_OverflowError,
250-
"Python int too large to convert to C long");
240+
v=_PyNumber_Index(v);
241+
if (v==NULL) {
251242
return-1;
252243
}
253-
elseif (!overflow) {
254-
*(unsigned long*)addr= (unsigned long)long_val;
255-
if (long_val<0) {
256-
WARN("Writing negative value into unsigned field");
244+
if (_PyLong_IsNegative((PyLongObject*)v)) {
245+
longlong_val=PyLong_AsLong(v);
246+
Py_DECREF(v);
247+
if (long_val==-1&&PyErr_Occurred()) {
248+
return-1;
257249
}
250+
*(unsigned long*)addr= (unsigned long)long_val;
251+
WARN("Writing negative value into unsigned field");
258252
}
259253
else {
260254
unsigned longulong_val=PyLong_AsUnsignedLong(v);
255+
Py_DECREF(v);
261256
if (ulong_val== (unsigned long)-1&&PyErr_Occurred()) {
262257
return-1;
263258
}
@@ -313,18 +308,30 @@ PyMember_SetOne(char *addr, PyMemberDef *l, PyObject *v)
313308
return-1;
314309
break;
315310
}
316-
casePy_T_ULONGLONG:{
317-
unsigned long longvalue;
318-
/* ??? PyLong_AsLongLong accepts an int, but PyLong_AsUnsignedLongLong
319-
doesn't ??? */
320-
if (PyLong_Check(v))
321-
*(unsigned long long*)addr=value=PyLong_AsUnsignedLongLong(v);
322-
else
323-
*(unsigned long long*)addr=value=PyLong_AsLong(v);
324-
if ((value== (unsigned long long)-1)&&PyErr_Occurred())
311+
casePy_T_ULONGLONG: {
312+
v=_PyNumber_Index(v);
313+
if (v==NULL) {
325314
return-1;
326-
break;
327315
}
316+
if (_PyLong_IsNegative((PyLongObject*)v)) {
317+
longlong_val=PyLong_AsLong(v);
318+
Py_DECREF(v);
319+
if (long_val==-1&&PyErr_Occurred()) {
320+
return-1;
321+
}
322+
*(unsigned long long*)addr= (unsigned long long)(long long)long_val;
323+
WARN("Writing negative value into unsigned field");
324+
}
325+
else {
326+
unsigned long longulonglong_val=PyLong_AsUnsignedLongLong(v);
327+
Py_DECREF(v);
328+
if (ulonglong_val== (unsigned long long)-1&&PyErr_Occurred()) {
329+
return-1;
330+
}
331+
*(unsigned long long*)addr=ulonglong_val;
332+
}
333+
break;
334+
}
328335
default:
329336
PyErr_Format(PyExc_SystemError,
330337
"bad memberdescr type for %s",l->name);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp