Don't unwrap a lambda whose callee contains a call - #572
Open
Eljees wants to merge 1 commit into
Open
Conversation
NoRedundantLambda rewrites lambda: f() into f, which is safe only while
the callee is re-evaluated on each call. When the callee itself contains
a call, unwrapping evaluates that inner call once, at definition time,
and freezes its result:
lambda: datetime.now().isoformat() -> datetime.now().isoformat
The rewritten form binds one fixed datetime instead of reading the clock
on each call, so the autofix silently changes behaviour.
Skip the report when the callee contains a call of its own, and pin the
behaviour with three valid cases covering an attribute of a call, a
method on a returned object, and a subscript of a call result.
Fixes Instagram#509
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #509.
The problem
NoRedundantLambdarewriteslambda: f()intof. That is only equivalentwhile
fis re-evaluated on every call. When the callee itself contains acall, the autofix moves that inner call out of the lambda body, so it runs
once at definition time and its result is frozen:
The rewritten version binds
isoformatto one fixeddatetimeinstancecaptured when the line was evaluated, instead of reading the clock on each
call. The lambda was not redundant, and the fix is applied automatically.
The change
Skip the report when the callee contains a call of its own:
Three valid cases pin the behaviour, covering the shapes this can take:
an attribute of a call result, a method on a returned object, and a
subscript of a call result.
Tests
mainWithout the guard the three new cases fail on the rule's own output rather
than on a count:
No test that passes on
mainfails with the change.flake8on the touchedfile is clean.
One thing this deliberately does not cover
The existing invalid case
is unsafe for a related but different reason:
t + uis evaluated onceafter unwrapping. That callee contains no call, so this change leaves it
reported exactly as before. I did not want to widen the scope without
knowing whether you consider that one intended — happy to extend the guard
to any non-trivial callee expression if you'd prefer.