]> granicus.if.org Git - python/commitdiff
bpo-35029: Replace the SyntaxWarning exception with a SyntaxError. (GH-9999)
authorSerhiy Storchaka <storchaka@gmail.com>
Sun, 21 Oct 2018 07:09:39 +0000 (10:09 +0300)
committerGitHub <noreply@github.com>
Sun, 21 Oct 2018 07:09:39 +0000 (10:09 +0300)
If SyntaxWarning was raised as an exception, it will be replaced
with a SyntaxError for better error reporting.

Lib/test/test_grammar.py
Misc/NEWS.d/next/Core and Builtins/2018-10-20-10-26-15.bpo-35029.t4tZcQ.rst [new file with mode: 0644]
Python/compile.c

index 9dd42b4f5dab50bd489345654c2c2f9f49443a89..3d8b1514f0cd117fec780e3395409d9cdb877fd6 100644 (file)
@@ -5,6 +5,7 @@ from test.support import check_syntax_error
 import inspect
 import unittest
 import sys
+import warnings
 # testing import *
 from sys import *
 
@@ -1099,6 +1100,14 @@ class GrammarTests(unittest.TestCase):
         else:
             self.fail("AssertionError not raised by 'assert False'")
 
+        with self.assertWarnsRegex(SyntaxWarning, 'assertion is always true'):
+            compile('assert(x, "msg")', '<testcase>', 'exec')
+        with warnings.catch_warnings():
+            warnings.filterwarnings('error', category=SyntaxWarning)
+            with self.assertRaisesRegex(SyntaxError, 'assertion is always true'):
+                compile('assert(x, "msg")', '<testcase>', 'exec')
+            compile('assert x, "msg"', '<testcase>', 'exec')
+
 
     ### compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
     # Tested below
diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-10-20-10-26-15.bpo-35029.t4tZcQ.rst b/Misc/NEWS.d/next/Core and Builtins/2018-10-20-10-26-15.bpo-35029.t4tZcQ.rst
new file mode 100644 (file)
index 0000000..3644c44
--- /dev/null
@@ -0,0 +1,2 @@
+:exc:`SyntaxWarning` raised as an exception at code generation time will be
+now replaced with a :exc:`SyntaxError` for better error reporting.
index 78b7baf3235f8fbed9915e17c57980240bd37aaa..11958d3841752a21c34a36a56b4c43f9c78f77e1 100644 (file)
@@ -174,6 +174,7 @@ static int compiler_addop(struct compiler *, int);
 static int compiler_addop_i(struct compiler *, int, Py_ssize_t);
 static int compiler_addop_j(struct compiler *, int, basicblock *, int);
 static int compiler_error(struct compiler *, const char *);
+static int compiler_warn(struct compiler *, const char *);
 static int compiler_nameop(struct compiler *, identifier, expr_context_ty);
 
 static PyCodeObject *compiler_mod(struct compiler *, mod_ty);
@@ -2971,7 +2972,6 @@ compiler_assert(struct compiler *c, stmt_ty s)
 {
     static PyObject *assertion_error = NULL;
     basicblock *end;
-    PyObject* msg;
 
     if (c->c_optimize)
         return 1;
@@ -2981,18 +2981,13 @@ compiler_assert(struct compiler *c, stmt_ty s)
             return 0;
     }
     if (s->v.Assert.test->kind == Tuple_kind &&
-        asdl_seq_LEN(s->v.Assert.test->v.Tuple.elts) > 0) {
-        msg = PyUnicode_FromString("assertion is always true, "
-                                   "perhaps remove parentheses?");
-        if (msg == NULL)
-            return 0;
-        if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, msg,
-                                     c->c_filename, c->u->u_lineno,
-                                     NULL, NULL) == -1) {
-            Py_DECREF(msg);
+        asdl_seq_LEN(s->v.Assert.test->v.Tuple.elts) > 0)
+    {
+        if (!compiler_warn(c, "assertion is always true, "
+                              "perhaps remove parentheses?"))
+        {
             return 0;
         }
-        Py_DECREF(msg);
     }
     end = compiler_new_block(c);
     if (end == NULL)
@@ -4793,6 +4788,31 @@ compiler_error(struct compiler *c, const char *errstr)
     return 0;
 }
 
+/* Emits a SyntaxWarning and returns 1 on success.
+   If a SyntaxWarning raised as error, replaces it with a SyntaxError
+   and returns 0.
+*/
+static int
+compiler_warn(struct compiler *c, const char *errstr)
+{
+    PyObject *msg = PyUnicode_FromString(errstr);
+    if (msg == NULL) {
+        return 0;
+    }
+    if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, msg, c->c_filename,
+                                 c->u->u_lineno, NULL, NULL) < 0)
+    {
+        Py_DECREF(msg);
+        if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) {
+            PyErr_Clear();
+            return compiler_error(c, errstr);
+        }
+        return 0;
+    }
+    Py_DECREF(msg);
+    return 1;
+}
+
 static int
 compiler_handle_subscr(struct compiler *c, const char *kind,
                        expr_context_ty ctx)