diff --git a/doc/whatsnew/fragments/8410.false_positive b/doc/whatsnew/fragments/8410.false_positive new file mode 100644 index 0000000000..264542a7de --- /dev/null +++ b/doc/whatsnew/fragments/8410.false_positive @@ -0,0 +1,3 @@ +`logging-not-lazy` is not longer emitted for explicitly concatenated string arguments. + +Closes #8410 diff --git a/pylint/checkers/logging.py b/pylint/checkers/logging.py index f7568a3a44..3064dc9268 100644 --- a/pylint/checkers/logging.py +++ b/pylint/checkers/logging.py @@ -246,7 +246,7 @@ def _check_log_method(self, node: nodes.Call, name: str) -> None: if isinstance(format_arg, nodes.BinOp): binop = format_arg emit = binop.op == "%" - if binop.op == "+": + if binop.op == "+" and not self._is_node_explicit_str_concatenation(binop): total_number_of_strings = sum( 1 for operand in (binop.left, binop.right) @@ -294,6 +294,19 @@ def _is_operand_literal_str(operand: InferenceResult | None) -> bool: """Return True if the operand in argument is a literal string.""" return isinstance(operand, nodes.Const) and operand.name == "str" + @staticmethod + def _is_node_explicit_str_concatenation(node: nodes.NodeNG) -> bool: + """Return True if the node represents an explicitly concatenated string.""" + if not isinstance(node, nodes.BinOp): + return False + return ( + LoggingChecker._is_operand_literal_str(node.left) + or LoggingChecker._is_node_explicit_str_concatenation(node.left) + ) and ( + LoggingChecker._is_operand_literal_str(node.right) + or LoggingChecker._is_node_explicit_str_concatenation(node.right) + ) + def _check_call_func(self, node: nodes.Call) -> None: """Checks that function call is not format_string.format().""" func = utils.safe_infer(node.func) diff --git a/tests/functional/l/logging/logging_not_lazy.py b/tests/functional/l/logging/logging_not_lazy.py index ab1ce008c7..aa2401dbc6 100644 --- a/tests/functional/l/logging/logging_not_lazy.py +++ b/tests/functional/l/logging/logging_not_lazy.py @@ -9,10 +9,10 @@ var_name = "Var:" # Statements that should be flagged: renamed_logging.warn("%s, %s" % (4, 5)) # [logging-not-lazy] +renamed_logging.warn("Var: " + var) # [logging-not-lazy] renamed_logging.exception("%s" % "Exceptional!") # [logging-not-lazy] renamed_logging.log(renamed_logging.INFO, "msg: %s" % "Run!") # [logging-not-lazy] renamed_logging.log(renamed_logging.INFO, "Var: " + var) # [logging-not-lazy] -renamed_logging.warn("%s" + " the rest of a single string") # [logging-not-lazy] renamed_logging.log(renamed_logging.INFO, var_name + var) # [logging-not-lazy] # Statements that should not be flagged: @@ -21,6 +21,11 @@ logging.warn("%s, %s" % (4, 5)) logging.log(logging.INFO, "msg: %s" % "Run!") logging.log("Var: " + var) +# Explicit string concatenations are fine: +renamed_logging.warn("%s" + " the rest of a single string") +renamed_logging.warn("Msg: " + "%s", "first piece " + "second piece") +renamed_logging.warn("first" + "second" + "third %s", "parameter") +renamed_logging.warn(("first" + "second" + "third %s")) # Regression crash test for incorrect format call renamed_logging.error( diff --git a/tests/functional/l/logging/logging_not_lazy.txt b/tests/functional/l/logging/logging_not_lazy.txt index 564fa65c3b..774082eb77 100644 --- a/tests/functional/l/logging/logging_not_lazy.txt +++ b/tests/functional/l/logging/logging_not_lazy.txt @@ -1,8 +1,8 @@ logging-not-lazy:11:0:11:39::Use lazy % formatting in logging functions:UNDEFINED -logging-not-lazy:12:0:12:48::Use lazy % formatting in logging functions:UNDEFINED -logging-not-lazy:13:0:13:61::Use lazy % formatting in logging functions:UNDEFINED -logging-not-lazy:14:0:14:56::Use lazy % formatting in logging functions:UNDEFINED -logging-not-lazy:15:0:15:59::Use lazy % formatting in logging functions:UNDEFINED +logging-not-lazy:12:0:12:35::Use lazy % formatting in logging functions:UNDEFINED +logging-not-lazy:13:0:13:48::Use lazy % formatting in logging functions:UNDEFINED +logging-not-lazy:14:0:14:61::Use lazy % formatting in logging functions:UNDEFINED +logging-not-lazy:15:0:15:56::Use lazy % formatting in logging functions:UNDEFINED logging-not-lazy:16:0:16:57::Use lazy % formatting in logging functions:UNDEFINED -bad-format-string:27:4:27:27::Invalid format string:UNDEFINED -logging-format-interpolation:27:4:27:27::Use lazy % formatting in logging functions:UNDEFINED +bad-format-string:32:4:32:27::Invalid format string:UNDEFINED +logging-format-interpolation:32:4:32:27::Use lazy % formatting in logging functions:UNDEFINED