Skip to content

Commit

Permalink
[flake8-pyi] Avoid rewriting invalid type expressions in `unnecessa…
Browse files Browse the repository at this point in the history
…ry-type-union` (PYI055) (#14660)
  • Loading branch information
sbrugman authored Nov 28, 2024
1 parent 224fe75 commit abb3c6e
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 68 deletions.
20 changes: 14 additions & 6 deletions crates/ruff_linter/resources/test/fixtures/flake8_pyi/PYI055.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@
t: type[int] | type[str] | type[float]
u: builtins.type[int] | type[str] | builtins.type[complex]
v: Union[type[float], type[complex]]
w: Union[type[float, int], type[complex]]
x: Union[Union[type[float, int], type[complex]]]
y: Union[Union[Union[type[float, int], type[complex]]]]
z: Union[type[complex], Union[Union[type[float, int]]]]
w: Union[type[float | int], type[complex]]
x: Union[Union[type[Union[float, int]], type[complex]]]
y: Union[Union[Union[type[float | int], type[complex]]]]
z: Union[type[complex], Union[Union[type[Union[float, int]]]]]


def func(arg: type[int] | str | type[float]) -> None:
...


# OK
x: type[int, str, float]
y: builtins.type[int, str, complex]
x: type[int | str | float]
y: builtins.type[int | str | complex]
z: Union[float, complex]


Expand Down Expand Up @@ -68,3 +68,11 @@ def convert_union(union: UnionType) -> _T | None:
Union[type[_T] | type[Converter[_T]] | str] | Converter[_T] | Callable[[str], _T], ... # PYI055
] = union.__args__
...


# `type[float, int]`` is not valid, use `type[float|int]` or `type[Union[float, int]]`
# OK for PYI055, should be covered by another check.
a: Union[type[float, int], type[complex]]
b: Union[Union[type[float, int], type[complex]]]
c: Union[Union[Union[type[float, int], type[complex]]]]
d: Union[type[complex], Union[Union[type[float, int]]]]
19 changes: 13 additions & 6 deletions crates/ruff_linter/resources/test/fixtures/flake8_pyi/PYI055.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ s: builtins.type[int] | builtins.type[str] | builtins.type[complex]
t: type[int] | type[str] | type[float]
u: builtins.type[int] | type[str] | builtins.type[complex]
v: Union[type[float], type[complex]]
w: Union[type[float, int], type[complex]]
x: Union[Union[type[float, int], type[complex]]]
y: Union[Union[Union[type[float, int], type[complex]]]]
z: Union[type[complex], Union[Union[type[float, int]]]]
w: Union[type[Union[float, int]], type[complex]]
x: Union[Union[type[Union[float, int]], type[complex]]]
y: Union[Union[Union[type[Union[float, int]], type[complex]]]]
z: Union[type[complex], Union[Union[type[Union[float, int]]]]]

def func(arg: type[int] | str | type[float]) -> None: ...

# OK
x: type[int, str, float]
y: builtins.type[int, str, complex]
x: type[int | str | float]
y: builtins.type[int | str | complex]
z: Union[float, complex]

def func(arg: type[int, float] | str) -> None: ...
Expand All @@ -29,3 +29,10 @@ def func():
item3: Union[ # comment
type[requests_mock.Mocker], # another comment
type[httpretty], type[str]] = requests_mock.Mocker


# OK
w: Union[type[float, int], type[complex]]
x: Union[Union[type[float, int], type[complex]]]
y: Union[Union[Union[type[float, int], type[complex]]]]
z: Union[type[complex], Union[Union[type[float, int]]]]
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,12 @@ pub(crate) fn unnecessary_type_union<'a>(checker: &mut Checker, union: &'a Expr)
}
match expr {
Expr::Subscript(ast::ExprSubscript { slice, value, .. }) => {
if semantic.match_builtin_expr(value, "type") {
// The annotation `type[a, b]` is not valid since `type` accepts
// a single parameter. This likely is a confusion with `type[a | b]` or
// `type[Union[a, b]]`. Do not emit a diagnostic for invalid type
// annotations.
if !matches!(**slice, Expr::Tuple(_)) && semantic.match_builtin_expr(value, "type")
{
type_exprs.push(slice);
} else {
other_exprs.push(expr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,4 @@ PYI055.py:68:9: PYI055 [*] Multiple `type` members in a union. Combine them into
68 |+ type[_T | Converter[_T]] | str | Converter[_T] | Callable[[str], _T], ... # PYI055
69 69 | ] = union.__args__
70 70 | ...
71 71 |
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ PYI055.pyi:5:4: PYI055 [*] Multiple `type` members in a union. Combine them into
5 |+t: type[int | str | float]
6 6 | u: builtins.type[int] | type[str] | builtins.type[complex]
7 7 | v: Union[type[float], type[complex]]
8 8 | w: Union[type[float, int], type[complex]]
8 8 | w: Union[type[Union[float, int]], type[complex]]

PYI055.pyi:6:4: PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[int | str | complex]`.
|
Expand All @@ -49,7 +49,7 @@ PYI055.pyi:6:4: PYI055 [*] Multiple `type` members in a union. Combine them into
6 | u: builtins.type[int] | type[str] | builtins.type[complex]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
7 | v: Union[type[float], type[complex]]
8 | w: Union[type[float, int], type[complex]]
8 | w: Union[type[Union[float, int]], type[complex]]
|
= help: Combine multiple `type` members

Expand All @@ -60,17 +60,17 @@ PYI055.pyi:6:4: PYI055 [*] Multiple `type` members in a union. Combine them into
6 |-u: builtins.type[int] | type[str] | builtins.type[complex]
6 |+u: type[int | str | complex]
7 7 | v: Union[type[float], type[complex]]
8 8 | w: Union[type[float, int], type[complex]]
9 9 | x: Union[Union[type[float, int], type[complex]]]
8 8 | w: Union[type[Union[float, int]], type[complex]]
9 9 | x: Union[Union[type[Union[float, int]], type[complex]]]

PYI055.pyi:7:4: PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[Union[float, complex]]`.
|
5 | t: type[int] | type[str] | type[float]
6 | u: builtins.type[int] | type[str] | builtins.type[complex]
7 | v: Union[type[float], type[complex]]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
8 | w: Union[type[float, int], type[complex]]
9 | x: Union[Union[type[float, int], type[complex]]]
8 | w: Union[type[Union[float, int]], type[complex]]
9 | x: Union[Union[type[Union[float, int]], type[complex]]]
|
= help: Combine multiple `type` members

Expand All @@ -80,96 +80,96 @@ PYI055.pyi:7:4: PYI055 [*] Multiple `type` members in a union. Combine them into
6 6 | u: builtins.type[int] | type[str] | builtins.type[complex]
7 |-v: Union[type[float], type[complex]]
7 |+v: type[Union[float, complex]]
8 8 | w: Union[type[float, int], type[complex]]
9 9 | x: Union[Union[type[float, int], type[complex]]]
10 10 | y: Union[Union[Union[type[float, int], type[complex]]]]
8 8 | w: Union[type[Union[float, int]], type[complex]]
9 9 | x: Union[Union[type[Union[float, int]], type[complex]]]
10 10 | y: Union[Union[Union[type[Union[float, int]], type[complex]]]]

PYI055.pyi:8:4: PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[Union[float, int, complex]]`.
PYI055.pyi:8:4: PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[Union[Union[float, int], complex]]`.
|
6 | u: builtins.type[int] | type[str] | builtins.type[complex]
7 | v: Union[type[float], type[complex]]
8 | w: Union[type[float, int], type[complex]]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
9 | x: Union[Union[type[float, int], type[complex]]]
10 | y: Union[Union[Union[type[float, int], type[complex]]]]
8 | w: Union[type[Union[float, int]], type[complex]]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
9 | x: Union[Union[type[Union[float, int]], type[complex]]]
10 | y: Union[Union[Union[type[Union[float, int]], type[complex]]]]
|
= help: Combine multiple `type` members

Safe fix
5 5 | t: type[int] | type[str] | type[float]
6 6 | u: builtins.type[int] | type[str] | builtins.type[complex]
7 7 | v: Union[type[float], type[complex]]
8 |-w: Union[type[float, int], type[complex]]
8 |+w: type[Union[float, int, complex]]
9 9 | x: Union[Union[type[float, int], type[complex]]]
10 10 | y: Union[Union[Union[type[float, int], type[complex]]]]
11 11 | z: Union[type[complex], Union[Union[type[float, int]]]]
8 |-w: Union[type[Union[float, int]], type[complex]]
8 |+w: type[Union[Union[float, int], complex]]
9 9 | x: Union[Union[type[Union[float, int]], type[complex]]]
10 10 | y: Union[Union[Union[type[Union[float, int]], type[complex]]]]
11 11 | z: Union[type[complex], Union[Union[type[Union[float, int]]]]]

PYI055.pyi:9:4: PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[Union[float, int, complex]]`.
PYI055.pyi:9:4: PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[Union[Union[float, int], complex]]`.
|
7 | v: Union[type[float], type[complex]]
8 | w: Union[type[float, int], type[complex]]
9 | x: Union[Union[type[float, int], type[complex]]]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
10 | y: Union[Union[Union[type[float, int], type[complex]]]]
11 | z: Union[type[complex], Union[Union[type[float, int]]]]
8 | w: Union[type[Union[float, int]], type[complex]]
9 | x: Union[Union[type[Union[float, int]], type[complex]]]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
10 | y: Union[Union[Union[type[Union[float, int]], type[complex]]]]
11 | z: Union[type[complex], Union[Union[type[Union[float, int]]]]]
|
= help: Combine multiple `type` members

Safe fix
6 6 | u: builtins.type[int] | type[str] | builtins.type[complex]
7 7 | v: Union[type[float], type[complex]]
8 8 | w: Union[type[float, int], type[complex]]
9 |-x: Union[Union[type[float, int], type[complex]]]
9 |+x: type[Union[float, int, complex]]
10 10 | y: Union[Union[Union[type[float, int], type[complex]]]]
11 11 | z: Union[type[complex], Union[Union[type[float, int]]]]
8 8 | w: Union[type[Union[float, int]], type[complex]]
9 |-x: Union[Union[type[Union[float, int]], type[complex]]]
9 |+x: type[Union[Union[float, int], complex]]
10 10 | y: Union[Union[Union[type[Union[float, int]], type[complex]]]]
11 11 | z: Union[type[complex], Union[Union[type[Union[float, int]]]]]
12 12 |

PYI055.pyi:10:4: PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[Union[float, int, complex]]`.
PYI055.pyi:10:4: PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[Union[Union[float, int], complex]]`.
|
8 | w: Union[type[float, int], type[complex]]
9 | x: Union[Union[type[float, int], type[complex]]]
10 | y: Union[Union[Union[type[float, int], type[complex]]]]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
11 | z: Union[type[complex], Union[Union[type[float, int]]]]
8 | w: Union[type[Union[float, int]], type[complex]]
9 | x: Union[Union[type[Union[float, int]], type[complex]]]
10 | y: Union[Union[Union[type[Union[float, int]], type[complex]]]]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
11 | z: Union[type[complex], Union[Union[type[Union[float, int]]]]]
|
= help: Combine multiple `type` members

Safe fix
7 7 | v: Union[type[float], type[complex]]
8 8 | w: Union[type[float, int], type[complex]]
9 9 | x: Union[Union[type[float, int], type[complex]]]
10 |-y: Union[Union[Union[type[float, int], type[complex]]]]
10 |+y: type[Union[float, int, complex]]
11 11 | z: Union[type[complex], Union[Union[type[float, int]]]]
8 8 | w: Union[type[Union[float, int]], type[complex]]
9 9 | x: Union[Union[type[Union[float, int]], type[complex]]]
10 |-y: Union[Union[Union[type[Union[float, int]], type[complex]]]]
10 |+y: type[Union[Union[float, int], complex]]
11 11 | z: Union[type[complex], Union[Union[type[Union[float, int]]]]]
12 12 |
13 13 | def func(arg: type[int] | str | type[float]) -> None: ...

PYI055.pyi:11:4: PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[Union[complex, float, int]]`.
PYI055.pyi:11:4: PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[Union[complex, Union[float, int]]]`.
|
9 | x: Union[Union[type[float, int], type[complex]]]
10 | y: Union[Union[Union[type[float, int], type[complex]]]]
11 | z: Union[type[complex], Union[Union[type[float, int]]]]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
9 | x: Union[Union[type[Union[float, int]], type[complex]]]
10 | y: Union[Union[Union[type[Union[float, int]], type[complex]]]]
11 | z: Union[type[complex], Union[Union[type[Union[float, int]]]]]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
12 |
13 | def func(arg: type[int] | str | type[float]) -> None: ...
|
= help: Combine multiple `type` members

Safe fix
8 8 | w: Union[type[float, int], type[complex]]
9 9 | x: Union[Union[type[float, int], type[complex]]]
10 10 | y: Union[Union[Union[type[float, int], type[complex]]]]
11 |-z: Union[type[complex], Union[Union[type[float, int]]]]
11 |+z: type[Union[complex, float, int]]
8 8 | w: Union[type[Union[float, int]], type[complex]]
9 9 | x: Union[Union[type[Union[float, int]], type[complex]]]
10 10 | y: Union[Union[Union[type[Union[float, int]], type[complex]]]]
11 |-z: Union[type[complex], Union[Union[type[Union[float, int]]]]]
11 |+z: type[Union[complex, Union[float, int]]]
12 12 |
13 13 | def func(arg: type[int] | str | type[float]) -> None: ...
14 14 |

PYI055.pyi:13:15: PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[int | float]`.
|
11 | z: Union[type[complex], Union[Union[type[float, int]]]]
11 | z: Union[type[complex], Union[Union[type[Union[float, int]]]]]
12 |
13 | def func(arg: type[int] | str | type[float]) -> None: ...
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
Expand All @@ -179,14 +179,14 @@ PYI055.pyi:13:15: PYI055 [*] Multiple `type` members in a union. Combine them in
= help: Combine multiple `type` members

Safe fix
10 10 | y: Union[Union[Union[type[float, int], type[complex]]]]
11 11 | z: Union[type[complex], Union[Union[type[float, int]]]]
10 10 | y: Union[Union[Union[type[Union[float, int]], type[complex]]]]
11 11 | z: Union[type[complex], Union[Union[type[Union[float, int]]]]]
12 12 |
13 |-def func(arg: type[int] | str | type[float]) -> None: ...
13 |+def func(arg: type[int | float] | str) -> None: ...
14 14 |
15 15 | # OK
16 16 | x: type[int, str, float]
16 16 | x: type[int | str | float]

PYI055.pyi:23:7: PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[requests_mock.Mocker | httpretty]`.
|
Expand Down Expand Up @@ -270,3 +270,6 @@ PYI055.pyi:29:12: PYI055 [*] Multiple `type` members in a union. Combine them in
30 |- type[requests_mock.Mocker], # another comment
31 |- type[httpretty], type[str]] = requests_mock.Mocker
29 |+ item3: type[Union[requests_mock.Mocker, httpretty, str]] = requests_mock.Mocker
32 30 |
33 31 |
34 32 | # OK

0 comments on commit abb3c6e

Please sign in to comment.