Fix incorrect stacklevel for struct warnings. (Partial backport of r78690).
diff --git a/Lib/test/test_struct.py b/Lib/test/test_struct.py
index cda7dee..ad754df 100644
--- a/Lib/test/test_struct.py
+++ b/Lib/test/test_struct.py
@@ -2,6 +2,7 @@
import unittest
import struct
import warnings
+import inspect
warnings.filterwarnings("ignore", "struct integer overflow masking is deprecated",
DeprecationWarning)
@@ -106,6 +107,29 @@
self.assertRaises(struct.error, struct.unpack, 'iii', s)
self.assertRaises(struct.error, struct.unpack, 'i', s)
+ def test_warnings_stacklevel(self):
+ # Python versions between 2.6 and 2.6.5 were producing
+ # warning messages at the wrong stacklevel.
+ def inner(fn, *args):
+ return inspect.currentframe().f_lineno, fn(*args)
+
+ def check_warning_stacklevel(fn, *args):
+ with warnings.catch_warnings(record=True) as w:
+ # "always" to make sure __warningregistry__ isn't affected
+ warnings.simplefilter("always")
+ lineno, result = inner(fn, *args)
+ for warn in w:
+ self.assertEqual(warn.lineno, lineno)
+
+ # out of range warnings
+ check_warning_stacklevel(struct.pack, '<L', -1)
+ check_warning_stacklevel(struct.pack, 'L', -1)
+ check_warning_stacklevel(struct.pack, '<h', 65536)
+ check_warning_stacklevel(struct.pack, '<l', 2**100)
+
+ # float warnings
+ check_warning_stacklevel(struct.pack, 'L', 3.1)
+
def test_transitiveness(self):
c = 'a'
b = 1
diff --git a/Modules/_struct.c b/Modules/_struct.c
index ff1aca2..d924cad 100644
--- a/Modules/_struct.c
+++ b/Modules/_struct.c
@@ -160,7 +160,7 @@
PyObject *o;
int res;
PyErr_Clear();
- if (PyErr_WarnEx(PyExc_DeprecationWarning, FLOAT_COERCE, 2) < 0)
+ if (PyErr_WarnEx(PyExc_DeprecationWarning, FLOAT_COERCE, 1) < 0)
return -1;
o = PyNumber_Int(v);
if (o == NULL)
@@ -269,7 +269,7 @@
PyObject *o;
int res;
PyErr_Clear();
- if (PyErr_WarnEx(PyExc_DeprecationWarning, FLOAT_COERCE, 2) < 0)
+ if (PyErr_WarnEx(PyExc_DeprecationWarning, FLOAT_COERCE, 1) < 0)
return -1;
o = PyNumber_Int(v);
if (o == NULL)
@@ -279,7 +279,7 @@
return res;
}
#endif
- if (PyErr_WarnEx(PyExc_DeprecationWarning, INT_OVERFLOW, 2) < 0)
+ if (PyErr_WarnEx(PyExc_DeprecationWarning, INT_OVERFLOW, 1) < 0)
return -1;
wrapped = PyNumber_And(v, pylong_ulong_mask);
if (wrapped == NULL)
@@ -308,7 +308,7 @@
PyObject *o;
int res;
PyErr_Clear();
- if (PyErr_WarnEx(PyExc_DeprecationWarning, FLOAT_COERCE, 2) < 0)
+ if (PyErr_WarnEx(PyExc_DeprecationWarning, FLOAT_COERCE, 1) < 0)
return -1;
o = PyNumber_Int(v);
if (o == NULL)
@@ -321,7 +321,7 @@
wrapped = PyNumber_And(v, pylong_ulong_mask);
if (wrapped == NULL)
return -1;
- if (PyErr_WarnEx(PyExc_DeprecationWarning, INT_OVERFLOW, 2) < 0) {
+ if (PyErr_WarnEx(PyExc_DeprecationWarning, INT_OVERFLOW, 1) < 0) {
Py_DECREF(wrapped);
return -1;
}
@@ -417,7 +417,7 @@
if (msg == NULL)
return -1;
rval = PyErr_WarnEx(PyExc_DeprecationWarning,
- PyString_AS_STRING(msg), 2);
+ PyString_AS_STRING(msg), 1);
Py_DECREF(msg);
if (rval == 0)
return 0;