From a77f0c14197542dc74ff1f2b521e8508bebd5f88 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 16 Oct 2023 14:29:00 +0000 Subject: [PATCH] Respect py-version for ``inconsistent-quotes`` inside f-strings (#9152) (#9155) * [inconsistent-quotes] Emit for f-strings for 3.12 only * Add docs for inconsistent-quotes with f-strings Despite ``sys.version`` check, pylint raises the warning with Python 3.11 (cherry picked from commit 1c0bc709488af3ad00068e70f5f6b05c9a3868d7) Co-authored-by: theirix --- doc/whatsnew/fragments/9113.bugfix | 3 +++ pylint/checkers/strings.py | 15 +++++++++++++++ .../i/inconsistent/inconsistent_quotes_fstring.py | 4 ++++ .../i/inconsistent/inconsistent_quotes_fstring.rc | 5 +++++ .../inconsistent_quotes_fstring_py312.py | 5 +++++ .../inconsistent_quotes_fstring_py312.rc | 8 ++++++++ .../inconsistent_quotes_fstring_py312.txt | 1 + .../inconsistent_quotes_fstring_py312_311.py | 5 +++++ .../inconsistent_quotes_fstring_py312_311.rc | 8 ++++++++ 9 files changed, 54 insertions(+) create mode 100644 doc/whatsnew/fragments/9113.bugfix create mode 100644 tests/functional/i/inconsistent/inconsistent_quotes_fstring.py create mode 100644 tests/functional/i/inconsistent/inconsistent_quotes_fstring.rc create mode 100644 tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312.py create mode 100644 tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312.rc create mode 100644 tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312.txt create mode 100644 tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312_311.py create mode 100644 tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312_311.rc diff --git a/doc/whatsnew/fragments/9113.bugfix b/doc/whatsnew/fragments/9113.bugfix new file mode 100644 index 0000000000..4b4b9b6dc0 --- /dev/null +++ b/doc/whatsnew/fragments/9113.bugfix @@ -0,0 +1,3 @@ +Emit ``inconsistent-quotes`` for f-strings with 3.12 interpreter only if targeting pre-3.12 versions. + +Closes #9113 diff --git a/pylint/checkers/strings.py b/pylint/checkers/strings.py index 7002a551dd..3c5bced5f7 100644 --- a/pylint/checkers/strings.py +++ b/pylint/checkers/strings.py @@ -8,6 +8,7 @@ import collections import re +import sys import tokenize from collections import Counter from collections.abc import Iterable, Sequence @@ -834,8 +835,22 @@ def check_for_consistent_string_delimiters( """ string_delimiters: Counter[str] = collections.Counter() + inside_fstring = False # whether token is inside f-string (since 3.12) + target_py312 = self.linter.config.py_version >= (3, 12) + # First, figure out which quote character predominates in the module for tok_type, token, _, _, _ in tokens: + if sys.version_info[:2] >= (3, 12): + # pylint: disable=no-member,useless-suppression + if tok_type == tokenize.FSTRING_START: + inside_fstring = True + elif tok_type == tokenize.FSTRING_END: + inside_fstring = False + + if inside_fstring and not target_py312: + # skip analysis of f-string contents + continue + if tok_type == tokenize.STRING and _is_quote_delimiter_chosen_freely(token): string_delimiters[_get_quote_delimiter(token)] += 1 diff --git a/tests/functional/i/inconsistent/inconsistent_quotes_fstring.py b/tests/functional/i/inconsistent/inconsistent_quotes_fstring.py new file mode 100644 index 0000000000..dd6f9fbe12 --- /dev/null +++ b/tests/functional/i/inconsistent/inconsistent_quotes_fstring.py @@ -0,0 +1,4 @@ +# pylint: disable=missing-module-docstring + +dictionary = {'0': 0} +f_string = f'{dictionary["0"]}' diff --git a/tests/functional/i/inconsistent/inconsistent_quotes_fstring.rc b/tests/functional/i/inconsistent/inconsistent_quotes_fstring.rc new file mode 100644 index 0000000000..ffd31cd2b1 --- /dev/null +++ b/tests/functional/i/inconsistent/inconsistent_quotes_fstring.rc @@ -0,0 +1,5 @@ +[STRING] +check-quote-consistency=yes + +[testoptions] +max_pyver=3.12 diff --git a/tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312.py b/tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312.py new file mode 100644 index 0000000000..5e952af196 --- /dev/null +++ b/tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312.py @@ -0,0 +1,5 @@ +# pylint: disable=missing-module-docstring + +dictionary = {'0': 0} +# quotes are inconsistent when targetting Python 3.12 (use single quotes) +f_string = f'{dictionary["0"]}' # [inconsistent-quotes] diff --git a/tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312.rc b/tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312.rc new file mode 100644 index 0000000000..3675741473 --- /dev/null +++ b/tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312.rc @@ -0,0 +1,8 @@ +[STRING] +check-quote-consistency=yes + +[main] +py-version=3.12 + +[testoptions] +min_pyver=3.12 diff --git a/tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312.txt b/tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312.txt new file mode 100644 index 0000000000..bf87ba6cb1 --- /dev/null +++ b/tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312.txt @@ -0,0 +1 @@ +inconsistent-quotes:5:0:None:None::"Quote delimiter "" is inconsistent with the rest of the file":UNDEFINED diff --git a/tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312_311.py b/tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312_311.py new file mode 100644 index 0000000000..5b53a19bb5 --- /dev/null +++ b/tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312_311.py @@ -0,0 +1,5 @@ +# pylint: disable=missing-module-docstring + +dictionary = {'0': 0} +# quotes are consistent when targetting 3.11 and earlier (cannot use single quotes here) +f_string = f'{dictionary["0"]}' diff --git a/tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312_311.rc b/tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312_311.rc new file mode 100644 index 0000000000..f60d7a71f7 --- /dev/null +++ b/tests/functional/i/inconsistent/inconsistent_quotes_fstring_py312_311.rc @@ -0,0 +1,8 @@ +[STRING] +check-quote-consistency=yes + +[main] +py-version=3.11 + +[testoptions] +min_pyver=3.12