mirror of
https://github.com/python/cpython.git
synced 2026-01-03 22:12:27 +00:00
[3.13] gh-139640: Fix swallowing syntax warnings in different modules (GH-139755) (GH-140119)
Revert GH-131993.
Fix swallowing some syntax warnings in different modules if they accidentally
have the same message and are emitted from the same line.
Fix duplicated warnings in the "finally" block.
(cherry picked from commit 279db6bede)
This commit is contained in:
parent
c5ec267311
commit
92f7965cf6
5 changed files with 63 additions and 48 deletions
|
|
@ -18,9 +18,3 @@ PyAPI_FUNC(int) PyErr_WarnExplicitFormat(
|
|||
|
||||
// DEPRECATED: Use PyErr_WarnEx() instead.
|
||||
#define PyErr_Warn(category, msg) PyErr_WarnEx((category), (msg), 1)
|
||||
|
||||
int _PyErr_WarnExplicitObjectWithContext(
|
||||
PyObject *category,
|
||||
PyObject *message,
|
||||
PyObject *filename,
|
||||
int lineno);
|
||||
|
|
|
|||
|
|
@ -1528,22 +1528,21 @@ async def name_4():
|
|||
[[]]
|
||||
|
||||
def test_compile_warnings(self):
|
||||
# See gh-131927
|
||||
# Compile warnings originating from the same file and
|
||||
# line are now only emitted once.
|
||||
# Each invocation of compile() emits compiler warnings, even if they
|
||||
# have the same message and line number.
|
||||
source = textwrap.dedent(r"""
|
||||
# tokenizer
|
||||
1or 0 # line 3
|
||||
# code generator
|
||||
1 is 1 # line 5
|
||||
""")
|
||||
with warnings.catch_warnings(record=True) as caught:
|
||||
warnings.simplefilter("default")
|
||||
compile('1 is 1', '<stdin>', 'eval')
|
||||
compile('1 is 1', '<stdin>', 'eval')
|
||||
for i in range(2):
|
||||
# Even if compile() is at the same line.
|
||||
compile(source, '<stdin>', 'exec')
|
||||
|
||||
self.assertEqual(len(caught), 1)
|
||||
|
||||
with warnings.catch_warnings(record=True) as caught:
|
||||
warnings.simplefilter("always")
|
||||
compile('1 is 1', '<stdin>', 'eval')
|
||||
compile('1 is 1', '<stdin>', 'eval')
|
||||
|
||||
self.assertEqual(len(caught), 2)
|
||||
self.assertEqual([wm.lineno for wm in caught], [3, 5] * 2)
|
||||
|
||||
def test_compile_warning_in_finally(self):
|
||||
# Ensure that warnings inside finally blocks are
|
||||
|
|
@ -1554,16 +1553,47 @@ def test_compile_warning_in_finally(self):
|
|||
try:
|
||||
pass
|
||||
finally:
|
||||
1 is 1
|
||||
1 is 1 # line 5
|
||||
try:
|
||||
pass
|
||||
finally: # nested
|
||||
1 is 1 # line 9
|
||||
""")
|
||||
|
||||
with warnings.catch_warnings(record=True) as caught:
|
||||
warnings.simplefilter("default")
|
||||
warnings.simplefilter("always")
|
||||
compile(source, '<stdin>', 'exec')
|
||||
|
||||
self.assertEqual(len(caught), 1)
|
||||
self.assertEqual(caught[0].category, SyntaxWarning)
|
||||
self.assertIn("\"is\" with 'int' literal", str(caught[0].message))
|
||||
self.assertEqual(sorted(wm.lineno for wm in caught), [5, 9])
|
||||
for wm in caught:
|
||||
self.assertEqual(wm.category, SyntaxWarning)
|
||||
self.assertIn("\"is\" with 'int' literal", str(wm.message))
|
||||
|
||||
# Other code path is used for "try" with "except*".
|
||||
source = textwrap.dedent("""
|
||||
try:
|
||||
pass
|
||||
except *Exception:
|
||||
pass
|
||||
finally:
|
||||
1 is 1 # line 7
|
||||
try:
|
||||
pass
|
||||
except *Exception:
|
||||
pass
|
||||
finally: # nested
|
||||
1 is 1 # line 13
|
||||
""")
|
||||
|
||||
with warnings.catch_warnings(record=True) as caught:
|
||||
warnings.simplefilter("always")
|
||||
compile(source, '<stdin>', 'exec')
|
||||
|
||||
self.assertEqual(sorted(wm.lineno for wm in caught), [7, 13])
|
||||
for wm in caught:
|
||||
self.assertEqual(wm.category, SyntaxWarning)
|
||||
self.assertIn("\"is\" with 'int' literal", str(wm.message))
|
||||
|
||||
|
||||
@requires_debug_ranges()
|
||||
class TestSourcePositions(unittest.TestCase):
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
Fix swallowing some syntax warnings in different modules if they
|
||||
accidentally have the same message and are emitted from the same line.
|
||||
Fix duplicated warnings in the ``finally`` block.
|
||||
|
|
@ -1317,28 +1317,6 @@ PyErr_WarnExplicitObject(PyObject *category, PyObject *message,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Like PyErr_WarnExplicitObject, but automatically sets up context */
|
||||
int
|
||||
_PyErr_WarnExplicitObjectWithContext(PyObject *category, PyObject *message,
|
||||
PyObject *filename, int lineno)
|
||||
{
|
||||
PyObject *unused_filename, *module, *registry;
|
||||
int unused_lineno;
|
||||
int stack_level = 1;
|
||||
|
||||
if (!setup_context(stack_level, NULL, &unused_filename, &unused_lineno,
|
||||
&module, ®istry)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rc = PyErr_WarnExplicitObject(category, message, filename, lineno,
|
||||
module, registry);
|
||||
Py_DECREF(unused_filename);
|
||||
Py_DECREF(registry);
|
||||
Py_DECREF(module);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
PyErr_WarnExplicit(PyObject *category, const char *text,
|
||||
const char *filename_str, int lineno,
|
||||
|
|
|
|||
|
|
@ -291,6 +291,7 @@ struct compiler {
|
|||
bool c_save_nested_seqs; /* if true, construct recursive instruction sequences
|
||||
* (including instructions for nested code objects)
|
||||
*/
|
||||
int c_disable_warning;
|
||||
};
|
||||
|
||||
#define INSTR_SEQUENCE(C) ((C)->u->u_instr_sequence)
|
||||
|
|
@ -1437,6 +1438,9 @@ compiler_push_fblock(struct compiler *c, location loc,
|
|||
f->fb_loc = loc;
|
||||
f->fb_exit = exit;
|
||||
f->fb_datum = datum;
|
||||
if (t == FINALLY_END) {
|
||||
c->c_disable_warning++;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -1448,6 +1452,9 @@ compiler_pop_fblock(struct compiler *c, enum fblocktype t, jump_target_label blo
|
|||
u->u_nfblocks--;
|
||||
assert(u->u_fblock[u->u_nfblocks].fb_type == t);
|
||||
assert(SAME_LABEL(u->u_fblock[u->u_nfblocks].fb_block, block_label));
|
||||
if (t == FINALLY_END) {
|
||||
c->c_disable_warning--;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -6609,6 +6616,9 @@ static int
|
|||
compiler_warn(struct compiler *c, location loc,
|
||||
const char *format, ...)
|
||||
{
|
||||
if (c->c_disable_warning) {
|
||||
return SUCCESS;
|
||||
}
|
||||
va_list vargs;
|
||||
va_start(vargs, format);
|
||||
PyObject *msg = PyUnicode_FromFormatV(format, vargs);
|
||||
|
|
@ -6616,8 +6626,8 @@ compiler_warn(struct compiler *c, location loc,
|
|||
if (msg == NULL) {
|
||||
return ERROR;
|
||||
}
|
||||
if (_PyErr_WarnExplicitObjectWithContext(PyExc_SyntaxWarning, msg,
|
||||
c->c_filename, loc.lineno) < 0)
|
||||
if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, msg,
|
||||
c->c_filename, loc.lineno, NULL, NULL) < 0)
|
||||
{
|
||||
if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) {
|
||||
/* Replace the SyntaxWarning exception with a SyntaxError
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue