Skip to content

Commit 92f7965

Browse files
[3.13] pythongh-139640: Fix swallowing syntax warnings in different modules (pythonGH-139755) (pythonGH-140119)
Revert pythonGH-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 279db6b)
1 parent c5ec267 commit 92f7965

File tree

5 files changed

+63
-48
lines changed

5 files changed

+63
-48
lines changed

Include/cpython/warnings.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,3 @@ PyAPI_FUNC(int) PyErr_WarnExplicitFormat(
1818

1919
// DEPRECATED: Use PyErr_WarnEx() instead.
2020
#define PyErr_Warn(category, msg) PyErr_WarnEx((category), (msg), 1)
21-
22-
int _PyErr_WarnExplicitObjectWithContext(
23-
PyObject *category,
24-
PyObject *message,
25-
PyObject *filename,
26-
int lineno);

Lib/test/test_compile.py

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,22 +1528,21 @@ async def name_4():
15281528
[[]]
15291529

15301530
def test_compile_warnings(self):
1531-
# See gh-131927
1532-
# Compile warnings originating from the same file and
1533-
# line are now only emitted once.
1531+
# Each invocation of compile() emits compiler warnings, even if they
1532+
# have the same message and line number.
1533+
source = textwrap.dedent(r"""
1534+
# tokenizer
1535+
1or 0 # line 3
1536+
# code generator
1537+
1 is 1 # line 5
1538+
""")
15341539
with warnings.catch_warnings(record=True) as caught:
15351540
warnings.simplefilter("default")
1536-
compile('1 is 1', '<stdin>', 'eval')
1537-
compile('1 is 1', '<stdin>', 'eval')
1538-
1539-
self.assertEqual(len(caught), 1)
1541+
for i in range(2):
1542+
# Even if compile() is at the same line.
1543+
compile(source, '<stdin>', 'exec')
15401544

1541-
with warnings.catch_warnings(record=True) as caught:
1542-
warnings.simplefilter("always")
1543-
compile('1 is 1', '<stdin>', 'eval')
1544-
compile('1 is 1', '<stdin>', 'eval')
1545-
1546-
self.assertEqual(len(caught), 2)
1545+
self.assertEqual([wm.lineno for wm in caught], [3, 5] * 2)
15471546

15481547
def test_compile_warning_in_finally(self):
15491548
# Ensure that warnings inside finally blocks are
@@ -1554,16 +1553,47 @@ def test_compile_warning_in_finally(self):
15541553
try:
15551554
pass
15561555
finally:
1557-
1 is 1
1556+
1 is 1 # line 5
1557+
try:
1558+
pass
1559+
finally: # nested
1560+
1 is 1 # line 9
15581561
""")
15591562

15601563
with warnings.catch_warnings(record=True) as caught:
1561-
warnings.simplefilter("default")
1564+
warnings.simplefilter("always")
15621565
compile(source, '<stdin>', 'exec')
15631566

1564-
self.assertEqual(len(caught), 1)
1565-
self.assertEqual(caught[0].category, SyntaxWarning)
1566-
self.assertIn("\"is\" with 'int' literal", str(caught[0].message))
1567+
self.assertEqual(sorted(wm.lineno for wm in caught), [5, 9])
1568+
for wm in caught:
1569+
self.assertEqual(wm.category, SyntaxWarning)
1570+
self.assertIn("\"is\" with 'int' literal", str(wm.message))
1571+
1572+
# Other code path is used for "try" with "except*".
1573+
source = textwrap.dedent("""
1574+
try:
1575+
pass
1576+
except *Exception:
1577+
pass
1578+
finally:
1579+
1 is 1 # line 7
1580+
try:
1581+
pass
1582+
except *Exception:
1583+
pass
1584+
finally: # nested
1585+
1 is 1 # line 13
1586+
""")
1587+
1588+
with warnings.catch_warnings(record=True) as caught:
1589+
warnings.simplefilter("always")
1590+
compile(source, '<stdin>', 'exec')
1591+
1592+
self.assertEqual(sorted(wm.lineno for wm in caught), [7, 13])
1593+
for wm in caught:
1594+
self.assertEqual(wm.category, SyntaxWarning)
1595+
self.assertIn("\"is\" with 'int' literal", str(wm.message))
1596+
15671597

15681598
@requires_debug_ranges()
15691599
class TestSourcePositions(unittest.TestCase):
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix swallowing some syntax warnings in different modules if they
2+
accidentally have the same message and are emitted from the same line.
3+
Fix duplicated warnings in the ``finally`` block.

Python/_warnings.c

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1317,28 +1317,6 @@ PyErr_WarnExplicitObject(PyObject *category, PyObject *message,
13171317
return 0;
13181318
}
13191319

1320-
/* Like PyErr_WarnExplicitObject, but automatically sets up context */
1321-
int
1322-
_PyErr_WarnExplicitObjectWithContext(PyObject *category, PyObject *message,
1323-
PyObject *filename, int lineno)
1324-
{
1325-
PyObject *unused_filename, *module, *registry;
1326-
int unused_lineno;
1327-
int stack_level = 1;
1328-
1329-
if (!setup_context(stack_level, NULL, &unused_filename, &unused_lineno,
1330-
&module, &registry)) {
1331-
return -1;
1332-
}
1333-
1334-
int rc = PyErr_WarnExplicitObject(category, message, filename, lineno,
1335-
module, registry);
1336-
Py_DECREF(unused_filename);
1337-
Py_DECREF(registry);
1338-
Py_DECREF(module);
1339-
return rc;
1340-
}
1341-
13421320
int
13431321
PyErr_WarnExplicit(PyObject *category, const char *text,
13441322
const char *filename_str, int lineno,

Python/compile.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ struct compiler {
291291
bool c_save_nested_seqs; /* if true, construct recursive instruction sequences
292292
* (including instructions for nested code objects)
293293
*/
294+
int c_disable_warning;
294295
};
295296

296297
#define INSTR_SEQUENCE(C) ((C)->u->u_instr_sequence)
@@ -1437,6 +1438,9 @@ compiler_push_fblock(struct compiler *c, location loc,
14371438
f->fb_loc = loc;
14381439
f->fb_exit = exit;
14391440
f->fb_datum = datum;
1441+
if (t == FINALLY_END) {
1442+
c->c_disable_warning++;
1443+
}
14401444
return SUCCESS;
14411445
}
14421446

@@ -1448,6 +1452,9 @@ compiler_pop_fblock(struct compiler *c, enum fblocktype t, jump_target_label blo
14481452
u->u_nfblocks--;
14491453
assert(u->u_fblock[u->u_nfblocks].fb_type == t);
14501454
assert(SAME_LABEL(u->u_fblock[u->u_nfblocks].fb_block, block_label));
1455+
if (t == FINALLY_END) {
1456+
c->c_disable_warning--;
1457+
}
14511458
}
14521459

14531460
static int
@@ -6609,15 +6616,18 @@ static int
66096616
compiler_warn(struct compiler *c, location loc,
66106617
const char *format, ...)
66116618
{
6619+
if (c->c_disable_warning) {
6620+
return SUCCESS;
6621+
}
66126622
va_list vargs;
66136623
va_start(vargs, format);
66146624
PyObject *msg = PyUnicode_FromFormatV(format, vargs);
66156625
va_end(vargs);
66166626
if (msg == NULL) {
66176627
return ERROR;
66186628
}
6619-
if (_PyErr_WarnExplicitObjectWithContext(PyExc_SyntaxWarning, msg,
6620-
c->c_filename, loc.lineno) < 0)
6629+
if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, msg,
6630+
c->c_filename, loc.lineno, NULL, NULL) < 0)
66216631
{
66226632
if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) {
66236633
/* Replace the SyntaxWarning exception with a SyntaxError

0 commit comments

Comments
 (0)