diff --git a/crates/ruff_linter/resources/test/fixtures/flake8_pie/PIE796.py b/crates/ruff_linter/resources/test/fixtures/flake8_pie/PIE796.py index 227ae8acc27b0..585e38b4d1b0c 100644 --- a/crates/ruff_linter/resources/test/fixtures/flake8_pie/PIE796.py +++ b/crates/ruff_linter/resources/test/fixtures/flake8_pie/PIE796.py @@ -64,3 +64,9 @@ class FakeEnum10(enum.Enum): A = enum.auto() B = enum.auto() C = enum.auto() + + +class FakeEnum10(enum.Enum): + A = ... + B = ... # PIE796 + C = ... # PIE796 diff --git a/crates/ruff_linter/resources/test/fixtures/flake8_pie/PIE796.pyi b/crates/ruff_linter/resources/test/fixtures/flake8_pie/PIE796.pyi new file mode 100644 index 0000000000000..ccfb75a2846a6 --- /dev/null +++ b/crates/ruff_linter/resources/test/fixtures/flake8_pie/PIE796.pyi @@ -0,0 +1,7 @@ +import enum + + +class FakeEnum1(enum.Enum): + A = ... + B = ... + C = ... diff --git a/crates/ruff_linter/src/rules/flake8_pie/mod.rs b/crates/ruff_linter/src/rules/flake8_pie/mod.rs index 238c239add39e..046b43b097aae 100644 --- a/crates/ruff_linter/src/rules/flake8_pie/mod.rs +++ b/crates/ruff_linter/src/rules/flake8_pie/mod.rs @@ -21,6 +21,7 @@ mod tests { #[test_case(Rule::UnnecessarySpread, Path::new("PIE800.py"))] #[test_case(Rule::ReimplementedContainerBuiltin, Path::new("PIE807.py"))] #[test_case(Rule::NonUniqueEnums, Path::new("PIE796.py"))] + #[test_case(Rule::NonUniqueEnums, Path::new("PIE796.pyi"))] fn rules(rule_code: Rule, path: &Path) -> Result<()> { let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy()); let diagnostics = test_path( diff --git a/crates/ruff_linter/src/rules/flake8_pie/rules/non_unique_enums.rs b/crates/ruff_linter/src/rules/flake8_pie/rules/non_unique_enums.rs index 6a0e62b47c307..36f54f444f88d 100644 --- a/crates/ruff_linter/src/rules/flake8_pie/rules/non_unique_enums.rs +++ b/crates/ruff_linter/src/rules/flake8_pie/rules/non_unique_enums.rs @@ -4,7 +4,7 @@ use ruff_diagnostics::Diagnostic; use ruff_diagnostics::Violation; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::comparable::ComparableExpr; -use ruff_python_ast::{self as ast, Expr, Stmt}; +use ruff_python_ast::{self as ast, Expr, PySourceType, Stmt}; use ruff_text_size::Ranged; use crate::checkers::ast::Checker; @@ -84,7 +84,15 @@ pub(crate) fn non_unique_enums(checker: &mut Checker, parent: &Stmt, body: &[Stm } } - if !seen_targets.insert(ComparableExpr::from(value)) { + let comparable = ComparableExpr::from(value); + + if checker.source_type == PySourceType::Stub + && comparable == ComparableExpr::EllipsisLiteral + { + continue; + } + + if !seen_targets.insert(comparable) { let diagnostic = Diagnostic::new( NonUniqueEnums { value: checker.generator().expr(value), diff --git a/crates/ruff_linter/src/rules/flake8_pie/snapshots/ruff_linter__rules__flake8_pie__tests__PIE796_PIE796.py.snap b/crates/ruff_linter/src/rules/flake8_pie/snapshots/ruff_linter__rules__flake8_pie__tests__PIE796_PIE796.py.snap index df58500ba5ef4..e10325ed1b541 100644 --- a/crates/ruff_linter/src/rules/flake8_pie/snapshots/ruff_linter__rules__flake8_pie__tests__PIE796_PIE796.py.snap +++ b/crates/ruff_linter/src/rules/flake8_pie/snapshots/ruff_linter__rules__flake8_pie__tests__PIE796_PIE796.py.snap @@ -57,4 +57,21 @@ PIE796.py:54:5: PIE796 Enum contains duplicate value: `2` | ^^^^^ PIE796 | +PIE796.py:71:5: PIE796 Enum contains duplicate value: `...` + | +69 | class FakeEnum10(enum.Enum): +70 | A = ... +71 | B = ... # PIE796 + | ^^^^^^^ PIE796 +72 | C = ... # PIE796 + | + +PIE796.py:72:5: PIE796 Enum contains duplicate value: `...` + | +70 | A = ... +71 | B = ... # PIE796 +72 | C = ... # PIE796 + | ^^^^^^^ PIE796 + | + diff --git a/crates/ruff_linter/src/rules/flake8_pie/snapshots/ruff_linter__rules__flake8_pie__tests__PIE796_PIE796.pyi.snap b/crates/ruff_linter/src/rules/flake8_pie/snapshots/ruff_linter__rules__flake8_pie__tests__PIE796_PIE796.pyi.snap new file mode 100644 index 0000000000000..5c6e954faaa5a --- /dev/null +++ b/crates/ruff_linter/src/rules/flake8_pie/snapshots/ruff_linter__rules__flake8_pie__tests__PIE796_PIE796.pyi.snap @@ -0,0 +1,4 @@ +--- +source: crates/ruff_linter/src/rules/flake8_pie/mod.rs +--- + diff --git a/crates/ruff_python_ast/src/comparable.rs b/crates/ruff_python_ast/src/comparable.rs index 208b97d05505e..dbbe6e75a351c 100644 --- a/crates/ruff_python_ast/src/comparable.rs +++ b/crates/ruff_python_ast/src/comparable.rs @@ -766,7 +766,7 @@ pub enum ComparableExpr<'a> { NumberLiteral(ExprNumberLiteral<'a>), BoolLiteral(ExprBoolLiteral<'a>), NoneLiteral, - EllispsisLiteral, + EllipsisLiteral, Attribute(ExprAttribute<'a>), Subscript(ExprSubscript<'a>), Starred(ExprStarred<'a>), @@ -964,7 +964,7 @@ impl<'a> From<&'a ast::Expr> for ComparableExpr<'a> { Self::BoolLiteral(ExprBoolLiteral { value }) } ast::Expr::NoneLiteral(_) => Self::NoneLiteral, - ast::Expr::EllipsisLiteral(_) => Self::EllispsisLiteral, + ast::Expr::EllipsisLiteral(_) => Self::EllipsisLiteral, ast::Expr::Attribute(ast::ExprAttribute { value, attr,