diff --git a/crates/ruff/resources/test/fixtures/pandas_vet/PD002.py b/crates/ruff/resources/test/fixtures/pandas_vet/PD002.py index 094fd0e5b0..d237ef0662 100644 --- a/crates/ruff/resources/test/fixtures/pandas_vet/PD002.py +++ b/crates/ruff/resources/test/fixtures/pandas_vet/PD002.py @@ -22,3 +22,5 @@ if True: x.drop(["a"], axis=1, **kwargs, inplace=True) x.drop(["a"], axis=1, inplace=True, **kwargs) f(x.drop(["a"], axis=1, inplace=True)) + +x.apply(lambda x: x.sort_values('a', inplace=True)) diff --git a/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs b/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs index 94590f6dee..5aae6a40df 100644 --- a/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs +++ b/crates/ruff/src/rules/flake8_pytest_style/rules/assertion.rs @@ -191,8 +191,9 @@ pub fn unittest_assertion( if let Ok(unittest_assert) = UnittestAssert::try_from(attr.as_str()) { // We're converting an expression to a statement, so avoid applying the fix if // the assertion is part of a larger expression. - let fixable = checker.ctx.current_expr_parent().is_none() - && matches!(checker.ctx.current_stmt().node, StmtKind::Expr { .. }) + let fixable = matches!(checker.ctx.current_stmt().node, StmtKind::Expr { .. }) + && checker.ctx.current_expr_parent().is_none() + && !checker.ctx.scope().kind.is_lambda() && !has_comments_in(expr.range(), checker.locator); let mut diagnostic = Diagnostic::new( PytestUnittestAssertion { diff --git a/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs b/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs index bac28367e7..d40d9299aa 100644 --- a/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs +++ b/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs @@ -77,9 +77,14 @@ pub fn inplace_argument( // the star argument _doesn't_ contain an override). // 2. The call is part of a larger expression (we're converting an expression to a // statement, and expressions can't contain statements). + // 3. The call is in a lambda (we can't assign to a variable in a lambda). This + // should be unnecessary, as lambdas are expressions, and so (2) should apply, + // but we don't currently restore expression stacks when parsing deferred nodes, + // and so the parent is lost. let fixable = !seen_star && matches!(checker.ctx.current_stmt().node, StmtKind::Expr { .. }) - && checker.ctx.current_expr_parent().is_none(); + && checker.ctx.current_expr_parent().is_none() + && !checker.ctx.scope().kind.is_lambda(); let mut diagnostic = Diagnostic::new(PandasUseOfInplaceArgument { fixable }, keyword.range()); if fixable && checker.patch(diagnostic.kind.rule()) { diff --git a/crates/ruff/src/rules/pandas_vet/snapshots/ruff__rules__pandas_vet__tests__PD002_PD002.py.snap b/crates/ruff/src/rules/pandas_vet/snapshots/ruff__rules__pandas_vet__tests__PD002_PD002.py.snap index 25851f81dc..9ce53ebcb7 100644 --- a/crates/ruff/src/rules/pandas_vet/snapshots/ruff__rules__pandas_vet__tests__PD002_PD002.py.snap +++ b/crates/ruff/src/rules/pandas_vet/snapshots/ruff__rules__pandas_vet__tests__PD002_PD002.py.snap @@ -105,6 +105,7 @@ PD002.py:22:33: PD002 [*] `inplace=True` should be avoided; it has inconsistent 22 |+x = x.drop(["a"], axis=1, **kwargs) 23 23 | x.drop(["a"], axis=1, inplace=True, **kwargs) 24 24 | f(x.drop(["a"], axis=1, inplace=True)) +25 25 | PD002.py:23:23: PD002 `inplace=True` should be avoided; it has inconsistent behavior | @@ -120,6 +121,16 @@ PD002.py:24:25: PD002 `inplace=True` should be avoided; it has inconsistent beha 25 | x.drop(["a"], axis=1, inplace=True, **kwargs) 26 | f(x.drop(["a"], axis=1, inplace=True)) | ^^^^^^^^^^^^ PD002 +27 | +28 | x.apply(lambda x: x.sort_values('a', inplace=True)) + | + +PD002.py:26:38: PD002 `inplace=True` should be avoided; it has inconsistent behavior + | +26 | f(x.drop(["a"], axis=1, inplace=True)) +27 | +28 | x.apply(lambda x: x.sort_values('a', inplace=True)) + | ^^^^^^^^^^^^ PD002 |