Seen in Ruff 0.5.7
In the following code, from __future__ import annotations causes the KW_ONLY to become a string.
The dataclasses module can deal with that, but only if the object isn’t in a if TYPE_CHECKING block.
Ruff supports this for things like ClassVar¹, i.e. if a ClassVar is used in a dataclass, Ruff knows the from typing import ClassVar needs to come out of the if TYPE_CHECKING block. However the same doesn’t seem to be true here.
from __future__ import annotations
from dataclasses import KW_ONLY, dataclass
@dataclass
class Test:
a: int
_: KW_ONLY
b: str
¹This is probably the place that should handle KW_ONLY
|
/// Returns `true` if an annotation will be inspected at runtime by the `dataclasses` module. |
|
/// |
|
/// Specifically, detects whether an annotation is to either `dataclasses.InitVar` or |
|
/// `typing.ClassVar` within a `@dataclass` class definition. |
|
/// |
|
/// See: <https://docs.python.org/3/library/dataclasses.html#init-only-variables> |
|
pub(crate) fn is_dataclass_meta_annotation(annotation: &Expr, semantic: &SemanticModel) -> bool { |
|
if !semantic.seen_module(Modules::DATACLASSES) { |
|
return false; |
|
} |
|
|
|
// Determine whether the assignment is in a `@dataclass` class definition. |
|
if let ScopeKind::Class(class_def) = semantic.current_scope().kind { |
|
if class_def.decorator_list.iter().any(|decorator| { |
|
semantic |
|
.resolve_qualified_name(map_callable(&decorator.expression)) |
|
.is_some_and(|qualified_name| { |
|
matches!(qualified_name.segments(), ["dataclasses", "dataclass"]) |
|
}) |
|
}) { |
|
// Determine whether the annotation is `typing.ClassVar` or `dataclasses.InitVar`. |
|
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") |
|
}); |
|
} |
|
} |
|
|
|
false |
|
} |
Seen in Ruff 0.5.7
In the following code,
from __future__ import annotationscauses theKW_ONLYto become a string.The dataclasses module can deal with that, but only if the object isn’t in a
if TYPE_CHECKINGblock.Ruff supports this for things like
ClassVar¹, i.e. if aClassVaris used in a dataclass, Ruff knows thefrom typing import ClassVarneeds to come out of theif TYPE_CHECKINGblock. However the same doesn’t seem to be true here.¹This is probably the place that should handle KW_ONLY
ruff/crates/ruff_linter/src/rules/flake8_type_checking/helpers.rs
Lines 108 to 139 in 82a3e69