mirror of https://github.com/astral-sh/ruff
Avoid treating `dataclasses.KW_ONLY` as typing-only (#12863)
## Summary Closes https://github.com/astral-sh/ruff/issues/12859.
This commit is contained in:
parent
d0ac38f9d3
commit
e05953a991
|
|
@ -0,0 +1,18 @@
|
|||
"""Test: avoid marking a `KW_ONLY` annotation as typing-only."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import KW_ONLY, dataclass, Field
|
||||
|
||||
|
||||
@dataclass
|
||||
class Test1:
|
||||
a: int
|
||||
_: KW_ONLY
|
||||
b: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class Test2:
|
||||
a: int
|
||||
b: Field
|
||||
|
|
@ -125,12 +125,14 @@ pub(crate) fn is_dataclass_meta_annotation(annotation: &Expr, semantic: &Semanti
|
|||
matches!(qualified_name.segments(), ["dataclasses", "dataclass"])
|
||||
})
|
||||
}) {
|
||||
// Determine whether the annotation is `typing.ClassVar` or `dataclasses.InitVar`.
|
||||
// Determine whether the annotation is `typing.ClassVar`, `dataclasses.InitVar`, or `dataclasses.KW_ONLY`.
|
||||
return semantic
|
||||
.resolve_qualified_name(map_subscript(annotation))
|
||||
.is_some_and(|qualified_name| {
|
||||
matches!(qualified_name.segments(), ["dataclasses", "InitVar"])
|
||||
|| semantic.match_typing_qualified_name(&qualified_name, "ClassVar")
|
||||
matches!(
|
||||
qualified_name.segments(),
|
||||
["dataclasses", "InitVar" | "KW_ONLY"]
|
||||
) || semantic.match_typing_qualified_name(&qualified_name, "ClassVar")
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ mod tests {
|
|||
#[test_case(Rule::TypingOnlyFirstPartyImport, Path::new("TCH001.py"))]
|
||||
#[test_case(Rule::TypingOnlyStandardLibraryImport, Path::new("TCH003.py"))]
|
||||
#[test_case(Rule::TypingOnlyStandardLibraryImport, Path::new("init_var.py"))]
|
||||
#[test_case(Rule::TypingOnlyStandardLibraryImport, Path::new("kw_only.py"))]
|
||||
#[test_case(Rule::TypingOnlyStandardLibraryImport, Path::new("snapshot.py"))]
|
||||
#[test_case(Rule::TypingOnlyThirdPartyImport, Path::new("TCH002.py"))]
|
||||
#[test_case(Rule::TypingOnlyThirdPartyImport, Path::new("quote.py"))]
|
||||
|
|
@ -77,6 +78,7 @@ mod tests {
|
|||
|
||||
#[test_case(Rule::TypingOnlyThirdPartyImport, Path::new("strict.py"))]
|
||||
#[test_case(Rule::TypingOnlyStandardLibraryImport, Path::new("init_var.py"))]
|
||||
#[test_case(Rule::TypingOnlyStandardLibraryImport, Path::new("kw_only.py"))]
|
||||
fn strict(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("strict_{}_{}", rule_code.as_ref(), path.to_string_lossy());
|
||||
let diagnostics = test_path(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_type_checking/mod.rs
|
||||
---
|
||||
kw_only.py:5:45: TCH003 [*] Move standard library import `dataclasses.Field` into a type-checking block
|
||||
|
|
||||
3 | from __future__ import annotations
|
||||
4 |
|
||||
5 | from dataclasses import KW_ONLY, dataclass, Field
|
||||
| ^^^^^ TCH003
|
||||
|
|
||||
= help: Move into type-checking block
|
||||
|
||||
ℹ Unsafe fix
|
||||
2 2 |
|
||||
3 3 | from __future__ import annotations
|
||||
4 4 |
|
||||
5 |-from dataclasses import KW_ONLY, dataclass, Field
|
||||
5 |+from dataclasses import KW_ONLY, dataclass
|
||||
6 |+from typing import TYPE_CHECKING
|
||||
7 |+
|
||||
8 |+if TYPE_CHECKING:
|
||||
9 |+ from dataclasses import Field
|
||||
6 10 |
|
||||
7 11 |
|
||||
8 12 | @dataclass
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_type_checking/mod.rs
|
||||
---
|
||||
|
||||
Loading…
Reference in New Issue