From fa31b6b63f261ab23d824c3d24f3bd8f7ba94398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Noord?= <13665637+DanielNoord@users.noreply.github.com> Date: Thu, 10 Feb 2022 09:13:54 +0100 Subject: [PATCH 1/4] Fix parsing of long lines when ``missing-final-newline`` is enabled --- ChangeLog | 4 ++++ doc/whatsnew/2.13.rst | 4 ++++ pylint/utils/pragma_parser.py | 7 ++----- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index bcebfa4478..e70d328e1a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -201,6 +201,10 @@ Release date: TBA Closes #5569 +* Fix parsing of long lines when ``missing-final-newline`` is enabled. + + Closes #5724 + * Fix false positives for ``used-before-assignment`` from using named expressions in a ternary operator test and using that expression as a call argument. diff --git a/doc/whatsnew/2.13.rst b/doc/whatsnew/2.13.rst index 629798f421..ddc0c00ca1 100644 --- a/doc/whatsnew/2.13.rst +++ b/doc/whatsnew/2.13.rst @@ -261,6 +261,10 @@ Other Changes Closes #5771 Ref PyCQA/astroid#1382 +* Fix parsing of long lines when ``missing-final-newline`` is enabled. + + Closes #5724 + * Fix ``unnecessary_dict_index_lookup`` false positive when deleting a dictionary's entry. Closes #4716 diff --git a/pylint/utils/pragma_parser.py b/pylint/utils/pragma_parser.py index 0bf25de7ce..745963a2bb 100644 --- a/pylint/utils/pragma_parser.py +++ b/pylint/utils/pragma_parser.py @@ -9,12 +9,9 @@ # so that an option can be continued with the reasons # why it is active or disabled. OPTION_RGX = r""" - \s* # Any number of whitespace - \#? # One or zero hash - .* # Anything (as much as possible) - (\s* # Beginning of first matched group and any number of whitespaces + ( # Beginning of first matched group and any number of whitespaces \# # Beginning of comment - .*? # Anything (as little as possible) + \s*? # Any whitespaces (as little as possible) \bpylint: # pylint word and column \s* # Any number of whitespaces ([^;#\n]+)) # Anything except semicolon or hash or newline (it is the second matched group) From c9f8cbd1d1b11ea7382502c4a5b55cddca73597e Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Wed, 16 Mar 2022 06:30:23 +0300 Subject: [PATCH 2/4] Adapt fa31b6b6 to be backward-compatible Fixes #5724 Also address comments from the PR PyCQA/pylint#5786 --- CONTRIBUTORS.txt | 1 + ChangeLog | 2 +- doc/whatsnew/2.13.rst | 2 +- pylint/utils/pragma_parser.py | 21 +++++++++++++-------- tests/checkers/unittest_refactoring.py | 9 +++++++++ tests/regrtest_data/issue_5724.py | 1 + 6 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 tests/regrtest_data/issue_5724.py diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 01c49f1b7e..989f9297d0 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -355,3 +355,4 @@ contributors: - Daniel Brookman - Téo Bouvard - Konrad Weihmann +- Sergey B Kirpichev diff --git a/ChangeLog b/ChangeLog index e70d328e1a..99ad7a2374 100644 --- a/ChangeLog +++ b/ChangeLog @@ -201,7 +201,7 @@ Release date: TBA Closes #5569 -* Fix parsing of long lines when ``missing-final-newline`` is enabled. +* Optimize parsing of long lines when ``missing-final-newline`` is enabled. Closes #5724 diff --git a/doc/whatsnew/2.13.rst b/doc/whatsnew/2.13.rst index ddc0c00ca1..d0696f1dbe 100644 --- a/doc/whatsnew/2.13.rst +++ b/doc/whatsnew/2.13.rst @@ -261,7 +261,7 @@ Other Changes Closes #5771 Ref PyCQA/astroid#1382 -* Fix parsing of long lines when ``missing-final-newline`` is enabled. +* Optimize parsing of long lines when ``missing-final-newline`` is enabled. Closes #5724 diff --git a/pylint/utils/pragma_parser.py b/pylint/utils/pragma_parser.py index 745963a2bb..1d31b8de52 100644 --- a/pylint/utils/pragma_parser.py +++ b/pylint/utils/pragma_parser.py @@ -9,14 +9,19 @@ # so that an option can be continued with the reasons # why it is active or disabled. OPTION_RGX = r""" - ( # Beginning of first matched group and any number of whitespaces - \# # Beginning of comment - \s*? # Any whitespaces (as little as possible) - \bpylint: # pylint word and column - \s* # Any number of whitespaces - ([^;#\n]+)) # Anything except semicolon or hash or newline (it is the second matched group) - # and end of the first matched group - [;#]{0,1}""" # From 0 to 1 repetition of semicolon or hash + (?:^\s*\#.* # Comment line or + |\s* # any number of whitespaces or + |\s*\#.* # a beginning of line comment + (?=\#.*?\bpylint:)) # with a following next "pylint:" pragma + (\# # Beginning of comment + .*? # Anything (as little as possible) + \bpylint: # pylint word and column + \s* # Any number of whitespaces + ([^;#\n]+)) # Anything except semicolon or hash or + # newline (it is the second matched group) + # and end of the first matched group + [;#]{0,1} # From 0 to 1 repetition of semicolon or hash +""" OPTION_PO = re.compile(OPTION_RGX, re.VERBOSE) diff --git a/tests/checkers/unittest_refactoring.py b/tests/checkers/unittest_refactoring.py index a2694200b7..e0a411203d 100644 --- a/tests/checkers/unittest_refactoring.py +++ b/tests/checkers/unittest_refactoring.py @@ -32,3 +32,12 @@ def test_process_tokens() -> None: with pytest.raises(SystemExit) as cm: Run([os.path.join(REGR_DATA, "very_long_line.py")], reporter=TextReporter()) assert cm.value.code == 0 + + +@pytest.mark.skipif(not hasattr(signal, "setitimer"), reason="Assumes POSIX signals") +def test_issue_5724() -> None: + with timeout(25.0): + with pytest.raises(SystemExit) as cm: + Run([os.path.join(REGR_DATA, "issue_5724.py"), + "--enable=missing-final-newline"], reporter=TextReporter()) + assert cm.value.code == 0 diff --git a/tests/regrtest_data/issue_5724.py b/tests/regrtest_data/issue_5724.py new file mode 100644 index 0000000000..dad184c432 --- /dev/null +++ b/tests/regrtest_data/issue_5724.py @@ -0,0 +1 @@ +a = "a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #a #" From 499592aa22398812eb6482a8f48a0a87cc577f96 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 16 Mar 2022 05:19:45 +0000 Subject: [PATCH 3/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/checkers/unittest_refactoring.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/checkers/unittest_refactoring.py b/tests/checkers/unittest_refactoring.py index e0a411203d..abb93bc7b2 100644 --- a/tests/checkers/unittest_refactoring.py +++ b/tests/checkers/unittest_refactoring.py @@ -38,6 +38,11 @@ def test_process_tokens() -> None: def test_issue_5724() -> None: with timeout(25.0): with pytest.raises(SystemExit) as cm: - Run([os.path.join(REGR_DATA, "issue_5724.py"), - "--enable=missing-final-newline"], reporter=TextReporter()) + Run( + [ + os.path.join(REGR_DATA, "issue_5724.py"), + "--enable=missing-final-newline", + ], + reporter=TextReporter(), + ) assert cm.value.code == 0 From 9a17ac3d5993ea8c1a7282dab00c52b0cc890a5f Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Wed, 16 Mar 2022 13:18:04 +0300 Subject: [PATCH 4/4] Address PR comments --- pylint/utils/pragma_parser.py | 23 +++++++++++------------ tests/checkers/unittest_refactoring.py | 1 + 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pylint/utils/pragma_parser.py b/pylint/utils/pragma_parser.py index 1d31b8de52..e09cba7c9e 100644 --- a/pylint/utils/pragma_parser.py +++ b/pylint/utils/pragma_parser.py @@ -9,18 +9,17 @@ # so that an option can be continued with the reasons # why it is active or disabled. OPTION_RGX = r""" - (?:^\s*\#.* # Comment line or - |\s* # any number of whitespaces or - |\s*\#.* # a beginning of line comment - (?=\#.*?\bpylint:)) # with a following next "pylint:" pragma - (\# # Beginning of comment - .*? # Anything (as little as possible) - \bpylint: # pylint word and column - \s* # Any number of whitespaces - ([^;#\n]+)) # Anything except semicolon or hash or - # newline (it is the second matched group) - # and end of the first matched group - [;#]{0,1} # From 0 to 1 repetition of semicolon or hash + (?:^\s*\#.*|\s*| # Comment line, or whitespaces, + \s*\#.*(?=\#.*?\bpylint:)) # or a beginning of an inline comment + # followed by "pylint:" pragma + (\# # Beginning of comment + .*? # Anything (as little as possible) + \bpylint: # pylint word and column + \s* # Any number of whitespaces + ([^;#\n]+)) # Anything except semicolon or hash or + # newline (it is the second matched group) + # and end of the first matched group + [;#]{0,1} # From 0 to 1 repetition of semicolon or hash """ OPTION_PO = re.compile(OPTION_RGX, re.VERBOSE) diff --git a/tests/checkers/unittest_refactoring.py b/tests/checkers/unittest_refactoring.py index abb93bc7b2..760eb2fe85 100644 --- a/tests/checkers/unittest_refactoring.py +++ b/tests/checkers/unittest_refactoring.py @@ -36,6 +36,7 @@ def test_process_tokens() -> None: @pytest.mark.skipif(not hasattr(signal, "setitimer"), reason="Assumes POSIX signals") def test_issue_5724() -> None: + """Regression test for parsing of pylint disable pragma's.""" with timeout(25.0): with pytest.raises(SystemExit) as cm: Run(