From 17f54d5ee4488e388a451b0ca4652c40f1a99929 Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye Date: Mon, 28 Mar 2022 20:17:09 +0300 Subject: [PATCH 1/2] Add warnings for the l suffix --- Doc/c-api/exceptions.rst | 3 +++ Doc/library/exceptions.rst | 4 ++++ Doc/library/warnings.rst | 3 +++ Include/pyerrors.h | 1 + Lib/test/exception_hierarchy.txt | 1 + Lib/test/test_optparse.py | 10 ++++++++++ Misc/Vim/python.vim | 1 + Objects/exceptions.c | 9 +++++++++ PC/os2emx/python27.def | 1 + Python/ast.c | 29 ++++++++++++++++++++++++----- 10 files changed, 57 insertions(+), 5 deletions(-) diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst index 281e4c8473fd24..aeca3572ea467a 100644 --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -690,6 +690,7 @@ the variables: single: PyExc_SyntaxWarning single: PyExc_UnicodeWarning single: PyExc_UserWarning + single: PyExc_Py3xWarning +------------------------------------------+---------------------------------+----------+ | C Name | Python Name | Notes | @@ -714,6 +715,8 @@ the variables: +------------------------------------------+---------------------------------+----------+ | :c:data:`PyExc_UserWarning` | :exc:`UserWarning` | | +------------------------------------------+---------------------------------+----------+ +| :c:data:`PyExc_3xWarning` | :exc:`Py3xWarning` | | ++------------------------------------------+---------------------------------+----------+ Notes: diff --git a/Doc/library/exceptions.rst b/Doc/library/exceptions.rst index 3cb944555bd974..bb8fcb78009076 100644 --- a/Doc/library/exceptions.rst +++ b/Doc/library/exceptions.rst @@ -530,6 +530,10 @@ module for more information. .. versionadded:: 2.6 +.. exception:: Py3xWarning + + Base class for warnings about 3.x compatibility. + Exception hierarchy ------------------- diff --git a/Doc/library/warnings.rst b/Doc/library/warnings.rst index 2f699ea8f55138..6f014f35653410 100644 --- a/Doc/library/warnings.rst +++ b/Doc/library/warnings.rst @@ -94,6 +94,9 @@ following warnings category classes are currently defined: | :exc:`BytesWarning` | Base category for warnings related to | | | bytes and bytearray. | +----------------------------------+-----------------------------------------------+ +| :exc:`Py3xWarning` | Base class for warnings about 3.x | + | compatibility | | ++----------------------------------+-----------------------------------------------+ While these are technically built-in exceptions, they are documented here, because conceptually they belong to the warnings mechanism. diff --git a/Include/pyerrors.h b/Include/pyerrors.h index 51134ef7b2522d..b5b49b5ca88c38 100644 --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -177,6 +177,7 @@ PyAPI_DATA(PyObject *) PyExc_FutureWarning; PyAPI_DATA(PyObject *) PyExc_ImportWarning; PyAPI_DATA(PyObject *) PyExc_UnicodeWarning; PyAPI_DATA(PyObject *) PyExc_BytesWarning; +PyAPI_DATA(PyObject *) PyExc_Py3xWarning; /* Convenience functions */ diff --git a/Lib/test/exception_hierarchy.txt b/Lib/test/exception_hierarchy.txt index 82b6ddfd4bda2c..1fc6628ee8e70a 100644 --- a/Lib/test/exception_hierarchy.txt +++ b/Lib/test/exception_hierarchy.txt @@ -45,6 +45,7 @@ BaseException +-- SyntaxWarning +-- UserWarning +-- FutureWarning + +-- Py3xWarning +-- ImportWarning +-- UnicodeWarning +-- BytesWarning diff --git a/Lib/test/test_optparse.py b/Lib/test/test_optparse.py index dc2ef0b7867516..35d6dad8743e8c 100644 --- a/Lib/test/test_optparse.py +++ b/Lib/test/test_optparse.py @@ -1654,6 +1654,16 @@ def test_numeric_options(self): self.assertParseFail(["-l", "0x12x"], "option -l: invalid long integer value: '0x12x'") + def test_parse_num_3k_warnings(self): + expected = 'the L suffix is not supported in 3.x; simply drop the suffix, \ + or accept the auto fixer modifications' + with check_py3k_warnings((expected, Py3xWarning)): + x = 10L + y = 8L + z = x + y + a = x * y + b = x - y + def test_main(): test_support.run_unittest(__name__) diff --git a/Misc/Vim/python.vim b/Misc/Vim/python.vim index df3f8db0b8da26..a4307717fff78a 100644 --- a/Misc/Vim/python.vim +++ b/Misc/Vim/python.vim @@ -92,6 +92,7 @@ if exists("python_highlight_exceptions") syn keyword pythonException ReferenceError RuntimeError RuntimeWarning syn keyword pythonException StandardError StopIteration SyntaxError syn keyword pythonException SyntaxWarning SystemError SystemExit TabError + syn keyword pythonException Py3xWarning SystemError SystemExit Warning syn keyword pythonException TypeError UnboundLocalError UnicodeDecodeError syn keyword pythonException UnicodeEncodeError UnicodeError syn keyword pythonException UnicodeTranslateError UnicodeWarning diff --git a/Objects/exceptions.c b/Objects/exceptions.c index fc601521208155..1788b08fe67439 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -1981,6 +1981,13 @@ SimpleExtendsException(PyExc_Warning, SyntaxWarning, "Base class for warnings about dubious syntax."); +/* + * 3xWarning extends Warning + */ +SimpleExtendsException(PyExc_Warning, Py3xWarning, + "Base class for warnings about 3.x compatibility."); + + /* * RuntimeWarning extends Warning */ @@ -2104,6 +2111,7 @@ _PyExc_Init(void) PRE_INIT(ImportWarning) PRE_INIT(UnicodeWarning) PRE_INIT(BytesWarning) + PRE_INIT(Py3xWarning) m = Py_InitModule4("exceptions", functions, exceptions_doc, (PyObject *)NULL, PYTHON_API_VERSION); @@ -2173,6 +2181,7 @@ _PyExc_Init(void) POST_INIT(ImportWarning) POST_INIT(UnicodeWarning) POST_INIT(BytesWarning) + POST_INIT(Py3xWarning) PyExc_MemoryErrorInst = BaseException_new(&_PyExc_MemoryError, NULL, NULL); if (!PyExc_MemoryErrorInst) diff --git a/PC/os2emx/python27.def b/PC/os2emx/python27.def index 5477cd22aeb5df..424435fdf4e1e4 100644 --- a/PC/os2emx/python27.def +++ b/PC/os2emx/python27.def @@ -819,6 +819,7 @@ EXPORTS "PyExc_DeprecationWarning" "PyExc_PendingDeprecationWarning" "PyExc_SyntaxWarning" + "PyExc_Py3xWarning" "PyExc_RuntimeWarning" "PyExc_FutureWarning" "PyExc_ImportWarning" diff --git a/Python/ast.c b/Python/ast.c index 10571a3ec2428f..17a5ab8da27727 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -36,7 +36,7 @@ static expr_ty ast_for_testlist_comp(struct compiling *, const node *); /* Note different signature for ast_for_call */ static expr_ty ast_for_call(struct compiling *, const node *, expr_ty); -static PyObject *parsenumber(struct compiling *, const char *); +static PyObject *parsenumber(struct compiling *, const node *n, const char *); static PyObject *parsestr(struct compiling *, const node *n, const char *); static PyObject *parsestrplus(struct compiling *, const node *n); @@ -130,6 +130,19 @@ ast_warn(struct compiling *c, const node *n, char *msg) return 1; } +static int +ast_3x_warn(struct compiling *c, const node *n, char *msg) +{ + if (PyErr_WarnExplicit(PyExc_Py3xWarning, msg, c->c_filename, LINENO(n), + NULL, NULL) < 0) { + /* if -Werr, change it to a SyntaxError */ + if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_Py3xWarning)) + ast_error(n, msg); + return 0; + } + return 1; +} + static int forbidden_check(struct compiling *c, const node *n, const char *x) { @@ -1403,7 +1416,7 @@ ast_for_atom(struct compiling *c, const node *n) return Str(str, LINENO(n), n->n_col_offset, c->c_arena); } case NUMBER: { - PyObject *pynum = parsenumber(c, STR(ch)); + PyObject *pynum = parsenumber(c, n, STR(ch)); if (!pynum) return NULL; @@ -1751,7 +1764,7 @@ ast_for_factor(struct compiling *c, const node *n) return NULL; s[0] = '-'; strcpy(s + 1, STR(pnum)); - pynum = parsenumber(c, s); + pynum = parsenumber(c, n, s); PyObject_FREE(s); if (!pynum) return NULL; @@ -3324,7 +3337,7 @@ ast_for_stmt(struct compiling *c, const node *n) } static PyObject * -parsenumber(struct compiling *c, const char *s) +parsenumber(struct compiling *c, const node *n, const char *s) { const char *end; long x; @@ -3340,8 +3353,14 @@ parsenumber(struct compiling *c, const char *s) #ifndef WITHOUT_COMPLEX imflag = *end == 'j' || *end == 'J'; #endif - if (*end == 'l' || *end == 'L') + if (*end == 'l' || *end == 'L') { + if (Py_Py3kWarningFlag && + !ast_3x_warn(c, n, "the L suffix is not supported in 3.x; simply drop the suffix, \n" + "or accept the auto fixer modifications")) { + return NULL; + } return PyLong_FromString((char *)s, (char **)0, 0); + } x = PyOS_strtol((char *)s, (char **)&end, 0); if (*end == '\0') { if (errno != 0) From db5a6a067f4be63735904a154e47437c28e5122b Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye Date: Mon, 27 Nov 2023 15:42:43 -0400 Subject: [PATCH 2/2] Fix regression introduced way back in the AST code --- Lib/test/test_ast.py | 8 ++++++-- Lib/test/test_optparse.py | 5 ++--- Python/ast.c | 16 +--------------- 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 3cfe6188ac1342..91a4e91f2aebc9 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -494,8 +494,12 @@ def test_literal_eval_issue4907(self): def test_main(): - with test_support.check_py3k_warnings(("backquote not supported", - SyntaxWarning)): + deprecations = [] + if sys.py3kwarning: + deprecations += [ + ("backquote not supported", SyntaxWarning), + ("the L suffix is not supported in 3.x; drop the suffix", SyntaxWarning)] + with test_support.check_warnings(*deprecations): test_support.run_unittest(AST_Tests, ASTHelpers_Test) def main(): diff --git a/Lib/test/test_optparse.py b/Lib/test/test_optparse.py index 35d6dad8743e8c..91c60da4a519b1 100644 --- a/Lib/test/test_optparse.py +++ b/Lib/test/test_optparse.py @@ -1655,9 +1655,8 @@ def test_numeric_options(self): "option -l: invalid long integer value: '0x12x'") def test_parse_num_3k_warnings(self): - expected = 'the L suffix is not supported in 3.x; simply drop the suffix, \ - or accept the auto fixer modifications' - with check_py3k_warnings((expected, Py3xWarning)): + expected = 'the L suffix is not supported in 3.x; drop the suffix' + with test_support.check_warnings(): x = 10L y = 8L z = x + y diff --git a/Python/ast.c b/Python/ast.c index 17a5ab8da27727..d27eec004bb572 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -130,19 +130,6 @@ ast_warn(struct compiling *c, const node *n, char *msg) return 1; } -static int -ast_3x_warn(struct compiling *c, const node *n, char *msg) -{ - if (PyErr_WarnExplicit(PyExc_Py3xWarning, msg, c->c_filename, LINENO(n), - NULL, NULL) < 0) { - /* if -Werr, change it to a SyntaxError */ - if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_Py3xWarning)) - ast_error(n, msg); - return 0; - } - return 1; -} - static int forbidden_check(struct compiling *c, const node *n, const char *x) { @@ -3355,8 +3342,7 @@ parsenumber(struct compiling *c, const node *n, const char *s) #endif if (*end == 'l' || *end == 'L') { if (Py_Py3kWarningFlag && - !ast_3x_warn(c, n, "the L suffix is not supported in 3.x; simply drop the suffix, \n" - "or accept the auto fixer modifications")) { + !ast_warn(c, n, "the L suffix is not supported in 3.x; drop the suffix")) { return NULL; } return PyLong_FromString((char *)s, (char **)0, 0);