Skip to content

Commit 9167471

Browse files
committed
[pylint/pep8-naming] Check __new__ argument name in bad-staticmethod-argument and not invalid-first-argument-name-for-class-method (PLW0211/N804) (#16676)
## Summary This PR stabilizes the behavior changes introduced by #13305 that were gated behind preview. The change is that `__new__` methods are now no longer flagged by `invalid-first-argument-name-for-class-method` (`N804`) but instead by `bad-staticmethod-argument` (`PLW0211`) > __new__ methods are technically static methods, with cls as their first argument. However, Ruff currently classifies them as classmethod, which causes two issues: ## Test Plan There have been no new issues or PRs related to `N804` or `PLW0211` since the behavior change was released in Ruff 0.9.7 (about 3 weeks ago). This is a somewhat recent change but I don't think it's necessary to leave this in preview for another 2 months. The main reason why it was in preview is that it is breaking, not because it is a risky change.
1 parent 348815d commit 9167471

7 files changed

+18
-80
lines changed

crates/ruff_linter/src/rules/pep8_naming/mod.rs

+1-19
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ mod tests {
1414
use crate::registry::Rule;
1515
use crate::rules::pep8_naming::settings::IgnoreNames;
1616
use crate::rules::{flake8_import_conventions, pep8_naming};
17-
use crate::settings::types::PreviewMode;
1817
use crate::test::test_path;
1918
use crate::{assert_messages, settings};
2019

2120
#[test_case(Rule::InvalidClassName, Path::new("N801.py"))]
2221
#[test_case(Rule::InvalidFunctionName, Path::new("N802.py"))]
2322
#[test_case(Rule::InvalidArgumentName, Path::new("N803.py"))]
23+
#[test_case(Rule::InvalidArgumentName, Path::new("N804.py"))]
2424
#[test_case(Rule::InvalidFirstArgumentNameForClassMethod, Path::new("N804.py"))]
2525
#[test_case(Rule::InvalidFirstArgumentNameForMethod, Path::new("N805.py"))]
2626
#[test_case(Rule::NonLowercaseVariableInFunction, Path::new("N806.py"))]
@@ -89,24 +89,6 @@ mod tests {
8989
Ok(())
9090
}
9191

92-
#[test_case(Rule::InvalidArgumentName, Path::new("N804.py"))]
93-
fn preview_rules(rule_code: Rule, path: &Path) -> Result<()> {
94-
let snapshot = format!(
95-
"preview__{}_{}",
96-
rule_code.noqa_code(),
97-
path.to_string_lossy()
98-
);
99-
let diagnostics = test_path(
100-
Path::new("pep8_naming").join(path).as_path(),
101-
&settings::LinterSettings {
102-
preview: PreviewMode::Enabled,
103-
..settings::LinterSettings::for_rule(rule_code)
104-
},
105-
)?;
106-
assert_messages!(snapshot, diagnostics);
107-
Ok(())
108-
}
109-
11092
#[test]
11193
fn camelcase_imported_as_incorrect_convention() -> Result<()> {
11294
let diagnostics = test_path(

crates/ruff_linter/src/rules/pep8_naming/rules/invalid_first_argument_name.rs

+4-14
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ impl Violation for InvalidFirstArgumentNameForMethod {
8282
/// Checks for class methods that use a name other than `cls` for their
8383
/// first argument.
8484
///
85-
/// With [`preview`] enabled, the method `__new__` is exempted from this
86-
/// check and the corresponding violation is then caught by
85+
/// The method `__new__` is exempted from this
86+
/// check and the corresponding violation is caught by
8787
/// [`bad-staticmethod-argument`][PLW0211].
8888
///
8989
/// ## Why is this bad?
@@ -164,8 +164,6 @@ enum FunctionType {
164164
Method,
165165
/// The function is a class method.
166166
ClassMethod,
167-
/// The function is the method `__new__`
168-
NewMethod,
169167
}
170168

171169
impl FunctionType {
@@ -177,27 +175,20 @@ impl FunctionType {
177175
is_new: false,
178176
}
179177
.into(),
180-
Self::NewMethod => InvalidFirstArgumentNameForClassMethod {
181-
argument_name,
182-
is_new: true,
183-
}
184-
.into(),
185178
}
186179
}
187180

188181
const fn valid_first_argument_name(self) -> &'static str {
189182
match self {
190183
Self::Method => "self",
191184
Self::ClassMethod => "cls",
192-
Self::NewMethod => "cls",
193185
}
194186
}
195187

196188
const fn rule(self) -> Rule {
197189
match self {
198190
Self::Method => Rule::InvalidFirstArgumentNameForMethod,
199191
Self::ClassMethod => Rule::InvalidFirstArgumentNameForClassMethod,
200-
Self::NewMethod => Rule::InvalidFirstArgumentNameForClassMethod,
201192
}
202193
}
203194
}
@@ -241,11 +232,10 @@ pub(crate) fn invalid_first_argument_name(checker: &Checker, scope: &Scope) {
241232
IsMetaclass::Maybe => return,
242233
},
243234
function_type::FunctionType::ClassMethod => FunctionType::ClassMethod,
244-
// In preview, this violation is caught by `PLW0211` instead
245-
function_type::FunctionType::NewMethod if checker.settings.preview.is_enabled() => {
235+
// This violation is caught by `PLW0211` instead
236+
function_type::FunctionType::NewMethod => {
246237
return;
247238
}
248-
function_type::FunctionType::NewMethod => FunctionType::NewMethod,
249239
};
250240
if !checker.enabled(function_type.rule()) {
251241
return;

crates/ruff_linter/src/rules/pylint/mod.rs

-4
Original file line numberDiff line numberDiff line change
@@ -446,10 +446,6 @@ mod tests {
446446
Path::new("repeated_equality_comparison.py")
447447
)]
448448
#[test_case(Rule::BadStrStripCall, Path::new("bad_str_strip_call.py"))]
449-
#[test_case(
450-
Rule::BadStaticmethodArgument,
451-
Path::new("bad_staticmethod_argument.py")
452-
)]
453449
fn preview_rules(rule_code: Rule, path: &Path) -> Result<()> {
454450
let snapshot = format!(
455451
"preview__{}_{}",

crates/ruff_linter/src/rules/pylint/rules/bad_staticmethod_argument.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,15 @@ use ruff_macros::{derive_message_formats, ViolationMetadata};
33
use ruff_python_ast as ast;
44
use ruff_python_ast::ParameterWithDefault;
55
use ruff_python_semantic::analyze::function_type;
6+
use ruff_python_semantic::analyze::function_type::FunctionType;
67
use ruff_python_semantic::Scope;
78
use ruff_text_size::Ranged;
89

910
use crate::checkers::ast::Checker;
1011

1112
/// ## What it does
1213
/// Checks for static methods that use `self` or `cls` as their first argument.
13-
///
14-
/// If [`preview`] mode is enabled, this rule also applies to
15-
/// `__new__` methods, which are implicitly static.
14+
/// This rule also applies to `__new__` methods, which are implicitly static.
1615
///
1716
/// ## Why is this bad?
1817
/// [PEP 8] recommends the use of `self` and `cls` as the first arguments for
@@ -77,9 +76,8 @@ pub(crate) fn bad_staticmethod_argument(checker: &Checker, scope: &Scope) {
7776
);
7877

7978
match type_ {
80-
function_type::FunctionType::StaticMethod => {}
81-
function_type::FunctionType::NewMethod if checker.settings.preview.is_enabled() => {}
82-
_ => {
79+
FunctionType::StaticMethod | FunctionType::NewMethod => {}
80+
FunctionType::Function | FunctionType::Method | FunctionType::ClassMethod => {
8381
return;
8482
}
8583
};

crates/ruff_linter/src/rules/pylint/snapshots/ruff_linter__rules__pylint__tests__PLW0211_bad_staticmethod_argument.py.snap

+9
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,12 @@ bad_staticmethod_argument.py:19:15: PLW0211 First argument of a static method sh
2626
| ^^^^ PLW0211
2727
20 | pass
2828
|
29+
30+
bad_staticmethod_argument.py:55:17: PLW0211 First argument of a static method should not be named `self`
31+
|
32+
53 | # `self` but not with `cls` as first argument - see above).
33+
54 | class Foo:
34+
55 | def __new__(self, x, y, z): # [bad-staticmethod-argument]
35+
| ^^^^ PLW0211
36+
56 | pass
37+
|

crates/ruff_linter/src/rules/pylint/snapshots/ruff_linter__rules__pylint__tests__preview__PLW0211_bad_staticmethod_argument.py.snap

-37
This file was deleted.

0 commit comments

Comments
 (0)