mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-01 06:11:21 +00:00
[flake8-pie
] Allow cast(SomeType, ...)
(PIE796
) (#15141)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
This commit is contained in:
parent
04d538113a
commit
280ba75100
4 changed files with 64 additions and 8 deletions
|
@ -70,3 +70,11 @@ class FakeEnum10(enum.Enum):
|
||||||
A = ...
|
A = ...
|
||||||
B = ... # PIE796
|
B = ... # PIE796
|
||||||
C = ... # PIE796
|
C = ... # PIE796
|
||||||
|
|
||||||
|
|
||||||
|
from typing import cast
|
||||||
|
|
||||||
|
class FakeEnum11(enum.Enum):
|
||||||
|
A = cast(SomeType, ...)
|
||||||
|
B = cast(SomeType, ...) # PIE796
|
||||||
|
C = cast(SomeType, ...) # PIE796
|
||||||
|
|
|
@ -5,3 +5,11 @@ class FakeEnum1(enum.Enum):
|
||||||
A = ...
|
A = ...
|
||||||
B = ...
|
B = ...
|
||||||
C = ...
|
C = ...
|
||||||
|
|
||||||
|
|
||||||
|
from typing import cast
|
||||||
|
|
||||||
|
class FakeEnum2(enum.Enum):
|
||||||
|
A = cast(SomeType, ...)
|
||||||
|
B = cast(SomeType, ...)
|
||||||
|
C = cast(SomeType, ...)
|
||||||
|
|
|
@ -4,7 +4,7 @@ use ruff_diagnostics::Diagnostic;
|
||||||
use ruff_diagnostics::Violation;
|
use ruff_diagnostics::Violation;
|
||||||
use ruff_macros::{derive_message_formats, ViolationMetadata};
|
use ruff_macros::{derive_message_formats, ViolationMetadata};
|
||||||
use ruff_python_ast::comparable::ComparableExpr;
|
use ruff_python_ast::comparable::ComparableExpr;
|
||||||
use ruff_python_ast::{self as ast, Expr, PySourceType, Stmt};
|
use ruff_python_ast::{self as ast, Expr, ExprCall, Stmt};
|
||||||
use ruff_text_size::Ranged;
|
use ruff_text_size::Ranged;
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
@ -55,13 +55,14 @@ impl Violation for NonUniqueEnums {
|
||||||
|
|
||||||
/// PIE796
|
/// PIE796
|
||||||
pub(crate) fn non_unique_enums(checker: &mut Checker, parent: &Stmt, body: &[Stmt]) {
|
pub(crate) fn non_unique_enums(checker: &mut Checker, parent: &Stmt, body: &[Stmt]) {
|
||||||
|
let semantic = checker.semantic();
|
||||||
|
|
||||||
let Stmt::ClassDef(parent) = parent else {
|
let Stmt::ClassDef(parent) = parent else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if !parent.bases().iter().any(|expr| {
|
if !parent.bases().iter().any(|expr| {
|
||||||
checker
|
semantic
|
||||||
.semantic()
|
|
||||||
.resolve_qualified_name(expr)
|
.resolve_qualified_name(expr)
|
||||||
.is_some_and(|qualified_name| matches!(qualified_name.segments(), ["enum", "Enum"]))
|
.is_some_and(|qualified_name| matches!(qualified_name.segments(), ["enum", "Enum"]))
|
||||||
}) {
|
}) {
|
||||||
|
@ -84,14 +85,12 @@ pub(crate) fn non_unique_enums(checker: &mut Checker, parent: &Stmt, body: &[Stm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let comparable = ComparableExpr::from(value);
|
if checker.source_type.is_stub() && member_has_unknown_value(checker, value) {
|
||||||
|
|
||||||
if checker.source_type == PySourceType::Stub
|
|
||||||
&& comparable == ComparableExpr::EllipsisLiteral
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let comparable = ComparableExpr::from(value);
|
||||||
|
|
||||||
if !seen_targets.insert(comparable) {
|
if !seen_targets.insert(comparable) {
|
||||||
let diagnostic = Diagnostic::new(
|
let diagnostic = Diagnostic::new(
|
||||||
NonUniqueEnums {
|
NonUniqueEnums {
|
||||||
|
@ -103,3 +102,27 @@ pub(crate) fn non_unique_enums(checker: &mut Checker, parent: &Stmt, body: &[Stm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether the value is a bare ellipsis literal (`A = ...`)
|
||||||
|
/// or a casted one (`A = cast(SomeType, ...)`).
|
||||||
|
fn member_has_unknown_value(checker: &Checker, expr: &Expr) -> bool {
|
||||||
|
match expr {
|
||||||
|
Expr::EllipsisLiteral(_) => true,
|
||||||
|
|
||||||
|
Expr::Call(ExprCall {
|
||||||
|
func, arguments, ..
|
||||||
|
}) => {
|
||||||
|
if !checker.semantic().match_typing_expr(func, "cast") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !arguments.keywords.is_empty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
matches!(arguments.args.as_ref(), [_, Expr::EllipsisLiteral(_)])
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -74,3 +74,20 @@ PIE796.py:72:5: PIE796 Enum contains duplicate value: `...`
|
||||||
72 | C = ... # PIE796
|
72 | C = ... # PIE796
|
||||||
| ^^^^^^^ PIE796
|
| ^^^^^^^ PIE796
|
||||||
|
|
|
|
||||||
|
|
||||||
|
PIE796.py:79:5: PIE796 Enum contains duplicate value: `cast(SomeType, ...)`
|
||||||
|
|
|
||||||
|
77 | class FakeEnum11(enum.Enum):
|
||||||
|
78 | A = cast(SomeType, ...)
|
||||||
|
79 | B = cast(SomeType, ...) # PIE796
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^ PIE796
|
||||||
|
80 | C = cast(SomeType, ...) # PIE796
|
||||||
|
|
|
||||||
|
|
||||||
|
PIE796.py:80:5: PIE796 Enum contains duplicate value: `cast(SomeType, ...)`
|
||||||
|
|
|
||||||
|
78 | A = cast(SomeType, ...)
|
||||||
|
79 | B = cast(SomeType, ...) # PIE796
|
||||||
|
80 | C = cast(SomeType, ...) # PIE796
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^ PIE796
|
||||||
|
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue