PY_SSIZE_T_MAX, PY_SSIZE_T_MIN,
)
+
+class Index:
+ def __init__(self, value):
+ self.value = value
+ def __index__(self):
+ return self.value
+
# There are two classes: one using <structmember.h> and another using
# `Py_`-prefixed API. They should behave the same in Python
self.assertEqual(ts.T_INT, INT_MIN)
ts.T_UINT = UINT_MAX
self.assertEqual(ts.T_UINT, UINT_MAX)
+ ts.T_UINT = Index(0)
+ self.assertEqual(ts.T_UINT, 0)
+ ts.T_UINT = Index(INT_MAX)
+ self.assertEqual(ts.T_UINT, INT_MAX)
def test_long(self):
ts = self.ts
self.assertEqual(ts.T_LONG, LONG_MIN)
ts.T_ULONG = ULONG_MAX
self.assertEqual(ts.T_ULONG, ULONG_MAX)
+ ts.T_ULONG = Index(0)
+ self.assertEqual(ts.T_ULONG, 0)
+ ts.T_ULONG = Index(LONG_MAX)
+ self.assertEqual(ts.T_ULONG, LONG_MAX)
def test_py_ssize_t(self):
ts = self.ts
with warnings_helper.check_warnings(('', RuntimeWarning)):
ts.T_USHORT = USHRT_MAX+1
+ def test_int(self):
+ ts = self.ts
+ if LONG_MIN < INT_MIN:
+ with self.assertWarns(RuntimeWarning):
+ ts.T_INT = INT_MIN-1
+ if LONG_MAX > INT_MAX:
+ with self.assertWarns(RuntimeWarning):
+ ts.T_INT = INT_MAX+1
+
+ def test_uint(self):
+ ts = self.ts
+ with self.assertWarns(RuntimeWarning):
+ ts.T_UINT = -1
+ if ULONG_MAX > UINT_MAX:
+ with self.assertWarns(RuntimeWarning):
+ ts.T_UINT = UINT_MAX+1
+
+ def test_ulong(self):
+ ts = self.ts
+ with self.assertWarns(RuntimeWarning):
+ ts.T_ULONG = -1
+
class TestWarnings_OldAPI(TestWarnings, unittest.TestCase):
cls = _test_structmembersType_OldAPI
WARN("Truncation of value to int");
break;
}
- case T_UINT:{
- unsigned long ulong_val = PyLong_AsUnsignedLong(v);
- if ((ulong_val == (unsigned long)-1) && PyErr_Occurred()) {
- /* XXX: For compatibility, accept negative int values
- as well. */
- PyErr_Clear();
- ulong_val = PyLong_AsLong(v);
- if ((ulong_val == (unsigned long)-1) &&
- PyErr_Occurred())
+ case T_UINT: {
+ /* XXX: For compatibility, accept negative int values
+ as well. */
+ int overflow;
+ long long_val = PyLong_AsLongAndOverflow(v, &overflow);
+ if (long_val == -1 && PyErr_Occurred()) {
+ return -1;
+ }
+ if (overflow < 0) {
+ PyErr_SetString(PyExc_OverflowError,
+ "Python int too large to convert to C long");
+ return -1;
+ }
+ else if (!overflow) {
+ *(unsigned int *)addr = (unsigned int)(unsigned long)long_val;
+ if (long_val < 0) {
+ WARN("Writing negative value into unsigned field");
+ }
+ else if ((unsigned long)long_val > UINT_MAX) {
+ WARN("Truncation of value to unsigned short");
+ }
+ }
+ else {
+ unsigned long ulong_val = PyLong_AsUnsignedLong(v);
+ if (ulong_val == (unsigned long)-1 && PyErr_Occurred()) {
return -1;
- *(unsigned int *)addr = (unsigned int)ulong_val;
- WARN("Writing negative value into unsigned field");
- } else
- *(unsigned int *)addr = (unsigned int)ulong_val;
- if (ulong_val > UINT_MAX)
- WARN("Truncation of value to unsigned int");
- break;
+ }
+ *(unsigned int*)addr = (unsigned int)ulong_val;
+ if (ulong_val > UINT_MAX) {
+ WARN("Truncation of value to unsigned int");
+ }
}
+ break;
+ }
case T_LONG:{
*(long*)addr = PyLong_AsLong(v);
if ((*(long*)addr == -1) && PyErr_Occurred())
return -1;
break;
}
- case T_ULONG:{
- *(unsigned long*)addr = PyLong_AsUnsignedLong(v);
- if ((*(unsigned long*)addr == (unsigned long)-1)
- && PyErr_Occurred()) {
- /* XXX: For compatibility, accept negative int values
- as well. */
- PyErr_Clear();
- *(unsigned long*)addr = PyLong_AsLong(v);
- if ((*(unsigned long*)addr == (unsigned long)-1)
- && PyErr_Occurred())
+ case T_ULONG: {
+ /* XXX: For compatibility, accept negative int values
+ as well. */
+ int overflow;
+ long long_val = PyLong_AsLongAndOverflow(v, &overflow);
+ if (long_val == -1 && PyErr_Occurred()) {
+ return -1;
+ }
+ if (overflow < 0) {
+ PyErr_SetString(PyExc_OverflowError,
+ "Python int too large to convert to C long");
+ return -1;
+ }
+ else if (!overflow) {
+ *(unsigned long *)addr = (unsigned long)long_val;
+ if (long_val < 0) {
+ WARN("Writing negative value into unsigned field");
+ }
+ }
+ else {
+ unsigned long ulong_val = PyLong_AsUnsignedLong(v);
+ if (ulong_val == (unsigned long)-1 && PyErr_Occurred()) {
return -1;
- WARN("Writing negative value into unsigned field");
+ }
+ *(unsigned long*)addr = ulong_val;
}
break;
- }
+ }
case T_PYSSIZET:{
*(Py_ssize_t*)addr = PyLong_AsSsize_t(v);
if ((*(Py_ssize_t*)addr == (Py_ssize_t)-1)