diff options
-rw-r--r-- | doc/whatsnew/fragments/8496.false_positive | 5 | ||||
-rw-r--r-- | pylint/checkers/base/basic_checker.py | 8 | ||||
-rw-r--r-- | tests/functional/u/unnecessary/unnecessary_lambda.py | 11 | ||||
-rw-r--r-- | tests/functional/u/unnecessary/unnecessary_lambda.txt | 2 |
4 files changed, 26 insertions, 0 deletions
diff --git a/doc/whatsnew/fragments/8496.false_positive b/doc/whatsnew/fragments/8496.false_positive new file mode 100644 index 000000000..3ea0fca6c --- /dev/null +++ b/doc/whatsnew/fragments/8496.false_positive @@ -0,0 +1,5 @@ +``unnecessary-lambda`` no longer warns on lambdas which use its parameters in +their body (other than the final arguments), e.g. +``lambda foo: (bar if foo else baz)(foo)``. + +Closes #8496 diff --git a/pylint/checkers/base/basic_checker.py b/pylint/checkers/base/basic_checker.py index 08d582b7f..062e67a97 100644 --- a/pylint/checkers/base/basic_checker.py +++ b/pylint/checkers/base/basic_checker.py @@ -519,6 +519,7 @@ class BasicChecker(_BasicChecker): ) @utils.only_required_for_messages("unnecessary-lambda") + # pylint: disable-next=too-many-return-statements def visit_lambda(self, node: nodes.Lambda) -> None: """Check whether the lambda is suspicious.""" # if the body of the lambda is a call expression with the same @@ -576,6 +577,13 @@ class BasicChecker(_BasicChecker): if arg.name != passed_arg.name: return + # The lambda is necessary if it uses its parameter in the function it is + # calling in the lambda's body + # e.g. lambda foo: (func1 if foo else func2)(foo) + for name in call.func.nodes_of_class(nodes.Name): + if name.lookup(name.name)[0] is node: + return + self.add_message("unnecessary-lambda", line=node.fromlineno, node=node) @utils.only_required_for_messages("dangerous-default-value") diff --git a/tests/functional/u/unnecessary/unnecessary_lambda.py b/tests/functional/u/unnecessary/unnecessary_lambda.py index 3e5ece2b1..82571a444 100644 --- a/tests/functional/u/unnecessary/unnecessary_lambda.py +++ b/tests/functional/u/unnecessary/unnecessary_lambda.py @@ -24,6 +24,12 @@ _ = lambda *args, **kwargs: _ANYARGS(*args, **kwargs) # +1: [unnecessary-lambda]
_ = lambda x, y, z, *args, **kwargs: _ANYARGS(x, y, z, *args, **kwargs)
+# These don't use their parameters in their body
+# +1: [unnecessary-lambda]
+_ = lambda x: z(lambda x: x)(x)
+# +1: [unnecessary-lambda]
+_ = lambda x, y: z(lambda x, y: x + y)(x, y)
+
# Lambdas that are *not* unnecessary and should *not* trigger warnings.
_ = lambda x: x
_ = lambda x: x()
@@ -50,3 +56,8 @@ _ = lambda: _ANYARGS(func=42) _ = lambda: code().analysis()
_ = lambda **kwargs: dict(bar=42, **kwargs)
+
+# These use the lambda parameters in their body
+_ = lambda x: x(x)
+_ = lambda x, y: x(x, y)
+_ = lambda x: z(lambda y: x + y)(x)
diff --git a/tests/functional/u/unnecessary/unnecessary_lambda.txt b/tests/functional/u/unnecessary/unnecessary_lambda.txt index 1cfb149df..87f80872c 100644 --- a/tests/functional/u/unnecessary/unnecessary_lambda.txt +++ b/tests/functional/u/unnecessary/unnecessary_lambda.txt @@ -5,3 +5,5 @@ unnecessary-lambda:19:4:19:33:<lambda>:Lambda may not be necessary:UNDEFINED unnecessary-lambda:21:4:21:39:<lambda>:Lambda may not be necessary:UNDEFINED unnecessary-lambda:23:4:23:53:<lambda>:Lambda may not be necessary:UNDEFINED unnecessary-lambda:25:4:25:71:<lambda>:Lambda may not be necessary:UNDEFINED +unnecessary-lambda:29:4:29:31:<lambda>:Lambda may not be necessary:UNDEFINED +unnecessary-lambda:31:4:31:44:<lambda>:Lambda may not be necessary:UNDEFINED |