summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>2022-11-27 13:26:57 +0100
committerGitHub <noreply@github.com>2022-11-27 13:26:57 +0100
commitff732826c5aa88854c275104283fd334a1d7aef8 (patch)
tree9d22916d60b78cd3dd93567f607e667ffc048fc7
parent86b8c649061f49c7d121843675ceefe6ff3a8113 (diff)
downloadpylint-git-ff732826c5aa88854c275104283fd334a1d7aef8.tar.gz
Fix ``logging-fstring-interpolation`` false positive (#7846) (#7854)
Co-authored-by: Mark Byrne <31762852+mbyrnepr2@users.noreply.github.com> Co-authored-by: Pierre Sassoulas <pierre.sassoulas@gmail.com> (cherry picked from commit 978d1ab95603fa337e686aac8956366556c23080) Co-authored-by: Dani Alcala <112832187+clavedeluna@users.noreply.github.com>
-rw-r--r--doc/whatsnew/fragments/4984.false_positive3
-rw-r--r--pylint/checkers/logging.py30
-rw-r--r--tests/functional/l/logging/logging_fstring_interpolation_py37.py6
-rw-r--r--tests/functional/l/logging/logging_fstring_interpolation_py37.txt3
4 files changed, 36 insertions, 6 deletions
diff --git a/doc/whatsnew/fragments/4984.false_positive b/doc/whatsnew/fragments/4984.false_positive
new file mode 100644
index 000000000..b31920564
--- /dev/null
+++ b/doc/whatsnew/fragments/4984.false_positive
@@ -0,0 +1,3 @@
+Fix ``logging-fstring-interpolation`` false positive raised when logging and f-string with ``%s`` formatting.
+
+Closes #4984
diff --git a/pylint/checkers/logging.py b/pylint/checkers/logging.py
index 53ac24f60..1cfa33c0f 100644
--- a/pylint/checkers/logging.py
+++ b/pylint/checkers/logging.py
@@ -105,6 +105,8 @@ CHECKED_CONVENIENCE_FUNCTIONS = {
"warning",
}
+MOST_COMMON_FORMATTING = frozenset(["%s", "%d", "%f", "%r"])
+
def is_method_call(
func: bases.BoundMethod, types: tuple[str, ...] = (), methods: tuple[str, ...] = ()
@@ -240,8 +242,9 @@ class LoggingChecker(checkers.BaseChecker):
else:
return
- if isinstance(node.args[format_pos], nodes.BinOp):
- binop = node.args[format_pos]
+ format_arg = node.args[format_pos]
+ if isinstance(format_arg, nodes.BinOp):
+ binop = format_arg
emit = binop.op == "%"
if binop.op == "+":
total_number_of_strings = sum(
@@ -256,11 +259,13 @@ class LoggingChecker(checkers.BaseChecker):
node=node,
args=(self._helper_string(node),),
)
- elif isinstance(node.args[format_pos], nodes.Call):
- self._check_call_func(node.args[format_pos])
- elif isinstance(node.args[format_pos], nodes.Const):
+ elif isinstance(format_arg, nodes.Call):
+ self._check_call_func(format_arg)
+ elif isinstance(format_arg, nodes.Const):
self._check_format_string(node, format_pos)
- elif isinstance(node.args[format_pos], nodes.JoinedStr):
+ elif isinstance(format_arg, nodes.JoinedStr):
+ if str_formatting_in_f_string(format_arg):
+ return
self.add_message(
"logging-fstring-interpolation",
node=node,
@@ -393,5 +398,18 @@ def _count_supplied_tokens(args: list[nodes.NodeNG]) -> int:
return sum(1 for arg in args if not isinstance(arg, nodes.Keyword))
+def str_formatting_in_f_string(node: nodes.JoinedStr) -> bool:
+ """Determine whether the node represents an f-string with string formatting.
+
+ For example: `f'Hello %s'`
+ """
+ # Check "%" presence first for performance.
+ return any(
+ "%" in val.value and any(x in val.value for x in MOST_COMMON_FORMATTING)
+ for val in node.values
+ if isinstance(val, nodes.Const)
+ )
+
+
def register(linter: PyLinter) -> None:
linter.register_checker(LoggingChecker(linter))
diff --git a/tests/functional/l/logging/logging_fstring_interpolation_py37.py b/tests/functional/l/logging/logging_fstring_interpolation_py37.py
index 963b2ce8c..d08424eb0 100644
--- a/tests/functional/l/logging/logging_fstring_interpolation_py37.py
+++ b/tests/functional/l/logging/logging_fstring_interpolation_py37.py
@@ -3,3 +3,9 @@ import logging
VAR = "string"
logging.error(f"{VAR}") # [logging-fstring-interpolation]
+
+WORLD = "world"
+logging.error(f'Hello {WORLD}') # [logging-fstring-interpolation]
+
+logging.error(f'Hello %s', 'World!') # [f-string-without-interpolation]
+logging.error(f'Hello %d', 1) # [f-string-without-interpolation]
diff --git a/tests/functional/l/logging/logging_fstring_interpolation_py37.txt b/tests/functional/l/logging/logging_fstring_interpolation_py37.txt
index a41c3e145..d8b84d674 100644
--- a/tests/functional/l/logging/logging_fstring_interpolation_py37.txt
+++ b/tests/functional/l/logging/logging_fstring_interpolation_py37.txt
@@ -1 +1,4 @@
logging-fstring-interpolation:5:0:5:23::Use lazy % formatting in logging functions:UNDEFINED
+logging-fstring-interpolation:8:0:8:31::Use lazy % formatting in logging functions:UNDEFINED
+f-string-without-interpolation:10:14:10:25::Using an f-string that does not have any interpolated variables:UNDEFINED
+f-string-without-interpolation:11:14:11:25::Using an f-string that does not have any interpolated variables:UNDEFINED