Skip to content

Commit

Permalink
[flake8-bugbear] Do not raise error if keyword argument is present …
Browse files Browse the repository at this point in the history
…and target-python version is less or equals than 3.9 (`B903`) (#15549)
  • Loading branch information
guillaumeLepape authored Jan 17, 2025
1 parent 4328df7 commit 4fdf8af
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,10 @@ def __init__(self, foo:int, bar:list):
self.foo = foo
self.bar = bar


class KeywordOnly: # OK with python3.9 or less, not OK starting python3.10
def __init__(self, *, foo: int, bar: int):
self.foo = foo
self.bar = bar

# <-- end flake8-bugbear tests
30 changes: 30 additions & 0 deletions crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ mod tests {
use crate::settings::LinterSettings;
use crate::test::test_path;

use crate::settings::types::PythonVersion;

#[test_case(Rule::AbstractBaseClassWithoutAbstractMethod, Path::new("B024.py"))]
#[test_case(Rule::AssertFalse, Path::new("B011.py"))]
#[test_case(Rule::AssertRaisesException, Path::new("B017.py"))]
Expand Down Expand Up @@ -78,6 +80,34 @@ mod tests {
Ok(())
}

#[test_case(
Rule::ClassAsDataStructure,
Path::new("class_as_data_structure.py"),
PythonVersion::Py39
)]
fn rules_with_target_version(
rule_code: Rule,
path: &Path,
target_version: PythonVersion,
) -> Result<()> {
let snapshot = format!(
"{}_py{}{}_{}",
rule_code.noqa_code(),
target_version.major(),
target_version.minor(),
path.to_string_lossy(),
);
let diagnostics = test_path(
Path::new("flake8_bugbear").join(path).as_path(),
&LinterSettings {
target_version,
..LinterSettings::for_rule(rule_code)
},
)?;
assert_messages!(snapshot, diagnostics);
Ok(())
}

#[test]
fn zip_without_explicit_strict() -> Result<()> {
let snapshot = "B905.py";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use ruff_python_semantic::analyze::visibility::{self, Visibility::Public};
use ruff_text_size::Ranged;

use crate::checkers::ast::Checker;
use crate::settings::types::PythonVersion;

/// ## What it does
/// Checks for classes that only have a public `__init__` method,
Expand Down Expand Up @@ -77,6 +78,7 @@ pub(crate) fn class_as_data_structure(checker: &mut Checker, class_def: &ast::St
// skip `self`
.skip(1)
.all(|param| param.annotation().is_some() && !param.is_variadic())
&& (func_def.parameters.kwonlyargs.is_empty() || checker.settings.target_version >= PythonVersion::Py310)
// `__init__` should not have complicated logic in it
// only assignments
&& func_def
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ class_as_data_structure.py:91:1: B903 Class could be dataclass or namedtuple
95 | | self.foo = foo
96 | | self.bar = bar
| |______________________^ B903
97 |
98 | # <-- end flake8-bugbear tests
|

class_as_data_structure.py:99:1: B903 Class could be dataclass or namedtuple
|
99 | / class KeywordOnly: # OK with python3.9 or less, not OK starting python3.10
100 | | def __init__(self, *, foo: int, bar: int):
101 | | self.foo = foo
102 | | self.bar = bar
| |______________________^ B903
103 |
104 | # <-- end flake8-bugbear tests
|
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
---
class_as_data_structure.py:6:1: B903 Class could be dataclass or namedtuple
|
6 | / class Point: # B903
7 | | def __init__(self, x: float, y: float) -> None:
8 | | self.x = x
9 | | self.y = y
| |__________________^ B903
|

class_as_data_structure.py:40:1: B903 Class could be dataclass or namedtuple
|
38 | ...
39 |
40 | / class C: # B903
41 | | c: int
42 | | def __init__(self,d:list):
43 | | self.d = d
| |__________________^ B903
44 |
45 | class D: # B903
|

class_as_data_structure.py:45:1: B903 Class could be dataclass or namedtuple
|
43 | self.d = d
44 |
45 | / class D: # B903
46 | | """This class has a docstring."""
47 | | # this next method is an init
48 | | def __init__(self,e:dict):
49 | | self.e = e
| |__________________^ B903
50 |
51 | # <--- begin flake8-bugbear tests below
|

class_as_data_structure.py:63:1: B903 Class could be dataclass or namedtuple
|
63 | / class NoWarningsClassAttributes:
64 | | spam = "ham"
65 | |
66 | | def __init__(self, foo:int, bar:list):
67 | | self.foo = foo
68 | | self.bar = bar
| |______________________^ B903
|

class_as_data_structure.py:85:1: B903 Class could be dataclass or namedtuple
|
85 | / class Warnings:
86 | | def __init__(self, foo:int, bar:list):
87 | | self.foo = foo
88 | | self.bar = bar
| |______________________^ B903
|

class_as_data_structure.py:91:1: B903 Class could be dataclass or namedtuple
|
91 | / class WarningsWithDocstring:
92 | | """A docstring should not be an impediment to a warning"""
93 | |
94 | | def __init__(self, foo:int, bar:list):
95 | | self.foo = foo
96 | | self.bar = bar
| |______________________^ B903
|

0 comments on commit 4fdf8af

Please sign in to comment.