Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport maintenance/2.17.x] Fix unnecessary-lambda false positive for lambdas using its parameters in their body #8506

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions doc/whatsnew/fragments/8496.false_positive
Original file line number Diff line number Diff line change
@@ -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
8 changes: 8 additions & 0 deletions pylint/checkers/base/basic_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,7 @@ def _has_variadic_argument(
)

@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
Expand Down Expand Up @@ -576,6 +577,13 @@ def visit_lambda(self, node: nodes.Lambda) -> None:
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")
Expand Down
11 changes: 11 additions & 0 deletions tests/functional/u/unnecessary/unnecessary_lambda.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
# +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()
Expand All @@ -50,3 +56,8 @@
_ = 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)
2 changes: 2 additions & 0 deletions tests/functional/u/unnecessary/unnecessary_lambda.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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