[Python-checkins] bpo-43497: Emit SyntaxWarnings for assertions with tuple constants. (GH-24867)

markshannon webhook-mailer at python.org
Tue Mar 16 07:14:49 EDT 2021


https://github.com/python/cpython/commit/a8ef4572a6b28bcfc0b10b34fa4204954b9dd761
commit: a8ef4572a6b28bcfc0b10b34fa4204954b9dd761
branch: master
author: tsukasa-au <tsukasa-au at users.noreply.github.com>
committer: markshannon <mark at hotpy.org>
date: 2021-03-16T11:14:41Z
summary:

bpo-43497: Emit SyntaxWarnings for assertions with tuple constants. (GH-24867)

* bpo-43497: Emit SyntaxWarnings for assertions with tuple constants.

Add a test that shows that a tuple constant (a tuple, where all of its
members are also compile-time constants) produces a SyntaxWarning. Then
fix this failure.

* Make SyntaxWarnings also work when "optimized".

* Split tests for SyntaxWarning to SyntaxError conversion

SyntaxWarnings emitted by the compiler when configured to be errors are
actually raised as SyntaxError exceptions.

Move these tests into their own method and add a test to ensure they are
raised. Previously we only tested that they were not raised for a
"valid" assertion statement.

files:
A Misc/NEWS.d/next/Core and Builtins/2021-03-15-07-50-30.bpo-43497.Uc5ZCJ.rst
M Lib/test/test_grammar.py
M Python/compile.c

diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py
index 0be869ef69b7c..c15f10b8bc747 100644
--- a/Lib/test/test_grammar.py
+++ b/Lib/test/test_grammar.py
@@ -279,6 +279,7 @@ class GrammarTests(unittest.TestCase):
 
     from test.support import check_syntax_error
     from test.support.warnings_helper import check_syntax_warning
+    from test.support.warnings_helper import check_no_warnings
 
     # single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
     # XXX can't test in a script -- this rule is only used when interactive
@@ -1194,7 +1195,7 @@ def test_assert(self):
 
     # these tests fail if python is run with -O, so check __debug__
     @unittest.skipUnless(__debug__, "Won't work if __debug__ is False")
-    def testAssert2(self):
+    def test_assert_failures(self):
         try:
             assert 0, "msg"
         except AssertionError as e:
@@ -1209,11 +1210,36 @@ def testAssert2(self):
         else:
             self.fail("AssertionError not raised by 'assert False'")
 
+    def test_assert_syntax_warnings(self):
+        # Ensure that we warn users if they provide a non-zero length tuple as
+        # the assertion test.
         self.check_syntax_warning('assert(x, "msg")',
                                   'assertion is always true')
+        self.check_syntax_warning('assert(False, "msg")',
+                                  'assertion is always true')
+        self.check_syntax_warning('assert(False,)',
+                                  'assertion is always true')
+
+        with self.check_no_warnings(category=SyntaxWarning):
+            compile('assert x, "msg"', '<testcase>', 'exec')
+            compile('assert False, "msg"', '<testcase>', 'exec')
+
+    def test_assert_warning_promotes_to_syntax_error(self):
+        # If SyntaxWarning is configured to be an error, it actually raises a
+        # SyntaxError.
+        # https://bugs.python.org/issue35029
         with warnings.catch_warnings():
             warnings.simplefilter('error', SyntaxWarning)
-            compile('assert x, "msg"', '<testcase>', 'exec')
+            try:
+                compile('assert x, "msg" ', '<testcase>', 'exec')
+            except SyntaxError:
+                self.fail('SyntaxError incorrectly raised for \'assert x, "msg"\'')
+            with self.assertRaises(SyntaxError):
+                compile('assert(x, "msg")', '<testcase>', 'exec')
+            with self.assertRaises(SyntaxError):
+                compile('assert(False, "msg")', '<testcase>', 'exec')
+            with self.assertRaises(SyntaxError):
+                compile('assert(False,)', '<testcase>', 'exec')
 
 
     ### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-03-15-07-50-30.bpo-43497.Uc5ZCJ.rst b/Misc/NEWS.d/next/Core and Builtins/2021-03-15-07-50-30.bpo-43497.Uc5ZCJ.rst
new file mode 100644
index 0000000000000..d30677fc5bc15
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2021-03-15-07-50-30.bpo-43497.Uc5ZCJ.rst	
@@ -0,0 +1 @@
+Emit SyntaxWarnings for assertions with tuple constants, this is a regression introduced in python3.7
\ No newline at end of file
diff --git a/Python/compile.c b/Python/compile.c
index ea1bf6bf923af..a1260aadd62e4 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -3355,10 +3355,12 @@ compiler_assert(struct compiler *c, stmt_ty s)
 {
     basicblock *end;
 
-    if (c->c_optimize)
-        return 1;
-    if (s->v.Assert.test->kind == Tuple_kind &&
-        asdl_seq_LEN(s->v.Assert.test->v.Tuple.elts) > 0)
+    /* Always emit a warning if the test is a non-zero length tuple */
+    if ((s->v.Assert.test->kind == Tuple_kind &&
+        asdl_seq_LEN(s->v.Assert.test->v.Tuple.elts) > 0) ||
+        (s->v.Assert.test->kind == Constant_kind &&
+         PyTuple_Check(s->v.Assert.test->v.Constant.value) &&
+         PyTuple_Size(s->v.Assert.test->v.Constant.value) > 0))
     {
         if (!compiler_warn(c, "assertion is always true, "
                               "perhaps remove parentheses?"))
@@ -3366,6 +3368,8 @@ compiler_assert(struct compiler *c, stmt_ty s)
             return 0;
         }
     }
+    if (c->c_optimize)
+        return 1;
     end = compiler_new_block(c);
     if (end == NULL)
         return 0;



More information about the Python-checkins mailing list