mirror of https://github.com/astral-sh/ruff
Merge bb61ed58cc into b0bc990cbf
This commit is contained in:
commit
e3d8efcd0a
|
|
@ -139,3 +139,27 @@ b_string_te_1: "UnionTE[NamedTupleTE]" = None
|
|||
b_string_te_2: "UnionTE[NamedTupleTE, None]" = None
|
||||
b_string_typing_1: "typing.Union[typing.NamedTuple]" = None
|
||||
b_string_typing_2: "typing.Union[typing.NamedTuple, None]" = None
|
||||
|
||||
|
||||
# Regression test for https://github.com/astral-sh/ruff/issues/21347
|
||||
# Don't emit lint for dynamic Union creation (e.g., Union[types] where types is a variable)
|
||||
def f(types: tuple[type, ...]):
|
||||
return Union[types]
|
||||
|
||||
|
||||
# Don't emit lint for dynamic Union creation with function calls (e.g., Union[foo()])
|
||||
def get_types():
|
||||
return (int, str, float)
|
||||
|
||||
|
||||
def g():
|
||||
return Union[get_types()]
|
||||
|
||||
|
||||
# Implicit type alias at module level - should be flagged
|
||||
IntOrStr = Union[int, str]
|
||||
|
||||
if __name__ == "__main__":
|
||||
u = f((int, str, float))
|
||||
print(u) # typing.Union[int, str, float]
|
||||
print(type(u)) # <class 'types.UnionType'>
|
||||
|
|
|
|||
|
|
@ -205,6 +205,18 @@ pub(crate) fn non_pep604_annotation(
|
|||
return;
|
||||
}
|
||||
|
||||
// Only apply this rule in type annotation/definition positions, including implicit
|
||||
// type aliases (e.g., `X = Union[int, str]` at module or class level).
|
||||
// Skip dynamic Union creation (e.g., `Union[types]` or `Union[foo()]`) when not in
|
||||
// type annotations, as these cannot be converted to PEP 604 syntax since the types
|
||||
// are determined at runtime.
|
||||
let in_type_definition = checker.semantic().in_type_definition();
|
||||
let in_implicit_type_alias = is_implicit_type_alias(checker, expr);
|
||||
|
||||
if !in_type_definition && !in_implicit_type_alias {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut diagnostic = checker.report_diagnostic(NonPEP604AnnotationUnion, expr.range());
|
||||
if fixable {
|
||||
match slice {
|
||||
|
|
@ -321,3 +333,24 @@ fn is_named_tuple(checker: &Checker, expr: &Expr) -> bool {
|
|||
fn is_optional_none(operator: Pep604Operator, slice: &Expr) -> bool {
|
||||
matches!(operator, Pep604Operator::Optional) && matches!(slice, Expr::NoneLiteral(_))
|
||||
}
|
||||
|
||||
/// Return `true` if the expression is part of an implicit type alias (e.g., `X = Union[int, str]`
|
||||
/// at module or class level).
|
||||
fn is_implicit_type_alias(checker: &Checker, expr: &Expr) -> bool {
|
||||
let semantic = checker.semantic();
|
||||
let scope = semantic.current_scope();
|
||||
|
||||
// Only consider module-level or class-level assignments as potential type aliases
|
||||
if scope.kind.is_function() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the current statement is a simple assignment
|
||||
if let ast::Stmt::Assign(ast::StmtAssign { value, .. }) = semantic.current_statement() {
|
||||
// Check if the Union expression is part of the assignment value
|
||||
// We check if the expression's range is within the value's range
|
||||
expr.range().start() >= value.range().start() && expr.range().end() <= value.range().end()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,17 +205,6 @@ help: Convert to `X | Y`
|
|||
43 |
|
||||
44 |
|
||||
|
||||
UP007 Use `X | Y` for type annotations
|
||||
--> UP007.py:46:9
|
||||
|
|
||||
45 | def f() -> None:
|
||||
46 | x = Union[str, int]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
47 | x = Union["str", "int"]
|
||||
48 | x: Union[str, int]
|
||||
|
|
||||
help: Convert to `X | Y`
|
||||
|
||||
UP007 [*] Use `X | Y` for type annotations
|
||||
--> UP007.py:48:8
|
||||
|
|
||||
|
|
@ -343,3 +332,14 @@ help: Convert to `X | Y`
|
|||
92 | print(param)
|
||||
93 |
|
||||
94 |
|
||||
|
||||
UP007 Use `X | Y` for type annotations
|
||||
--> UP007.py:160:12
|
||||
|
|
||||
159 | # Implicit type alias at module level - should be flagged
|
||||
160 | IntOrStr = Union[int, str]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
161 |
|
||||
162 | if __name__ == "__main__":
|
||||
|
|
||||
help: Convert to `X | Y`
|
||||
|
|
|
|||
Loading…
Reference in New Issue