From d31e7730cd5d74efbd7320751dacd51d09cc415d Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 21 Oct 2018 10:09:39 +0300 Subject: [PATCH] bpo-35029: Replace the SyntaxWarning exception with a SyntaxError. (GH-9999) If SyntaxWarning was raised as an exception, it will be replaced with a SyntaxError for better error reporting. --- Lib/test/test_grammar.py | 9 ++++ .../2018-10-20-10-26-15.bpo-35029.t4tZcQ.rst | 2 + Python/compile.c | 42 ++++++++++++++----- 3 files changed, 42 insertions(+), 11 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2018-10-20-10-26-15.bpo-35029.t4tZcQ.rst diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index 9dd42b4f5da..3d8b1514f0c 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -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")', '', 'exec') + with warnings.catch_warnings(): + warnings.filterwarnings('error', category=SyntaxWarning) + with self.assertRaisesRegex(SyntaxError, 'assertion is always true'): + compile('assert(x, "msg")', '', 'exec') + compile('assert x, "msg"', '', '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 index 00000000000..3644c4410fb --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-10-20-10-26-15.bpo-35029.t4tZcQ.rst @@ -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. diff --git a/Python/compile.c b/Python/compile.c index 78b7baf3235..11958d38417 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -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)