gh-87999: Change warning type for numeric literal followed by keyword (GH-91980)

The warning emitted by the Python parser for a numeric literal
immediately followed by keyword has been changed from deprecation
warning to syntax warning.
This commit is contained in:
Serhiy Storchaka 2022-04-27 20:15:14 +03:00 committed by GitHub
parent f60b4c3d74
commit 43a8bf1ea4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 26 additions and 12 deletions

View File

@ -104,6 +104,7 @@ INVALID_UNDERSCORE_LITERALS = [
class TokenTests(unittest.TestCase): class TokenTests(unittest.TestCase):
from test.support import check_syntax_error from test.support import check_syntax_error
from test.support.warnings_helper import check_syntax_warning
def test_backslash(self): def test_backslash(self):
# Backslash means line continuation: # Backslash means line continuation:
@ -178,7 +179,7 @@ class TokenTests(unittest.TestCase):
def test_float_exponent_tokenization(self): def test_float_exponent_tokenization(self):
# See issue 21642. # See issue 21642.
with warnings.catch_warnings(): with warnings.catch_warnings():
warnings.simplefilter('ignore', DeprecationWarning) warnings.simplefilter('ignore', SyntaxWarning)
self.assertEqual(eval("1 if 1else 0"), 1) self.assertEqual(eval("1 if 1else 0"), 1)
self.assertEqual(eval("1 if 0else 0"), 0) self.assertEqual(eval("1 if 0else 0"), 0)
self.assertRaises(SyntaxError, eval, "0 if 1Else 0") self.assertRaises(SyntaxError, eval, "0 if 1Else 0")
@ -218,12 +219,13 @@ class TokenTests(unittest.TestCase):
with self.subTest(expr=test): with self.subTest(expr=test):
if error: if error:
with warnings.catch_warnings(record=True) as w: with warnings.catch_warnings(record=True) as w:
with self.assertRaises(SyntaxError): with self.assertRaisesRegex(SyntaxError,
r'invalid \w+ literal'):
compile(test, "<testcase>", "eval") compile(test, "<testcase>", "eval")
self.assertEqual(w, []) self.assertEqual(w, [])
else: else:
with self.assertWarns(DeprecationWarning): self.check_syntax_warning(test,
compile(test, "<testcase>", "eval") errtext=r'invalid \w+ literal')
for num in "0xf", "0o7", "0b1", "9", "0", "1.", "1e3", "1j": for num in "0xf", "0o7", "0b1", "9", "0", "1.", "1e3", "1j":
compile(num, "<testcase>", "eval") compile(num, "<testcase>", "eval")
@ -231,15 +233,22 @@ class TokenTests(unittest.TestCase):
check(f"{num}or x", error=(num == "0")) check(f"{num}or x", error=(num == "0"))
check(f"{num}in x") check(f"{num}in x")
check(f"{num}not in x") check(f"{num}not in x")
with warnings.catch_warnings():
warnings.filterwarnings('ignore', '"is" with a literal',
SyntaxWarning)
check(f"{num}is x")
check(f"{num}if x else y") check(f"{num}if x else y")
check(f"x if {num}else y", error=(num == "0xf")) check(f"x if {num}else y", error=(num == "0xf"))
check(f"[{num}for x in ()]") check(f"[{num}for x in ()]")
check(f"{num}spam", error=True) check(f"{num}spam", error=True)
with warnings.catch_warnings():
warnings.filterwarnings('ignore', '"is" with a literal',
SyntaxWarning)
with self.assertWarnsRegex(SyntaxWarning,
r'invalid \w+ literal'):
compile(f"{num}is x", "<testcase>", "eval")
warnings.simplefilter('error', SyntaxWarning)
with self.assertRaisesRegex(SyntaxError,
r'invalid \w+ literal'):
compile(f"{num}is x", "<testcase>", "eval")
check("[0x1ffor x in ()]") check("[0x1ffor x in ()]")
check("[0x1for x in ()]") check("[0x1for x in ()]")
check("[0xfor x in ()]") check("[0xfor x in ()]")

View File

@ -0,0 +1,3 @@
The warning emitted by the Python parser for a numeric literal immediately
followed by keyword has been changed from deprecation warning to syntax
warning.

View File

@ -1139,7 +1139,7 @@ indenterror(struct tok_state *tok)
} }
static int static int
parser_warn(struct tok_state *tok, const char *format, ...) parser_warn(struct tok_state *tok, PyObject *category, const char *format, ...)
{ {
PyObject *errmsg; PyObject *errmsg;
va_list vargs; va_list vargs;
@ -1154,9 +1154,9 @@ parser_warn(struct tok_state *tok, const char *format, ...)
goto error; goto error;
} }
if (PyErr_WarnExplicitObject(PyExc_DeprecationWarning, errmsg, tok->filename, if (PyErr_WarnExplicitObject(category, errmsg, tok->filename,
tok->lineno, NULL, NULL) < 0) { tok->lineno, NULL, NULL) < 0) {
if (PyErr_ExceptionMatches(PyExc_DeprecationWarning)) { if (PyErr_ExceptionMatches(category)) {
/* Replace the DeprecationWarning exception with a SyntaxError /* Replace the DeprecationWarning exception with a SyntaxError
to get a more accurate error report */ to get a more accurate error report */
PyErr_Clear(); PyErr_Clear();
@ -1234,7 +1234,9 @@ verify_end_of_number(struct tok_state *tok, int c, const char *kind)
} }
if (r) { if (r) {
tok_backup(tok, c); tok_backup(tok, c);
if (parser_warn(tok, "invalid %s literal", kind)) { if (parser_warn(tok, PyExc_SyntaxWarning,
"invalid %s literal", kind))
{
return 0; return 0;
} }
tok_nextc(tok); tok_nextc(tok);