mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 18:28:24 +00:00
Avoid applying PYI055
to runtime-evaluated annotations (#6457)
## Summary The use of `|` as a union operator is not always safe, if a type annotation is evaluated in a runtime context. For example, this code errors at runtime: ```python import httpretty import requests_mock item: type[requests_mock.Mocker | httpretty] = requests_mock.Mocker ``` However, it's fine in a `.pyi` file, with `__future__` annotations`, or if the annotation is in a non-evaluated context, like: ```python def func(): item: type[requests_mock.Mocker | httpretty] = requests_mock.Mocker ``` This PR modifies the rule to avoid enforcing in those invalid, runtime-evaluated contexts. Closes https://github.com/astral-sh/ruff/issues/6455.
This commit is contained in:
parent
395bb31247
commit
627f475b91
5 changed files with 86 additions and 87 deletions
|
@ -1,7 +1,6 @@
|
|||
import builtins
|
||||
from typing import Union
|
||||
|
||||
|
||||
w: builtins.type[int] | builtins.type[str] | builtins.type[complex]
|
||||
x: type[int] | type[str] | type[float]
|
||||
y: builtins.type[int] | type[str] | builtins.type[complex]
|
||||
|
@ -9,7 +8,9 @@ z: Union[type[float], type[complex]]
|
|||
z: Union[type[float, int], type[complex]]
|
||||
|
||||
|
||||
def func(arg: type[int] | str | type[float]) -> None: ...
|
||||
def func(arg: type[int] | str | type[float]) -> None:
|
||||
...
|
||||
|
||||
|
||||
# OK
|
||||
x: type[int, str, float]
|
||||
|
@ -17,4 +18,14 @@ y: builtins.type[int, str, complex]
|
|||
z: Union[float, complex]
|
||||
|
||||
|
||||
def func(arg: type[int, float] | str) -> None: ...
|
||||
def func(arg: type[int, float] | str) -> None:
|
||||
...
|
||||
|
||||
|
||||
# OK
|
||||
item: type[requests_mock.Mocker] | type[httpretty] = requests_mock.Mocker
|
||||
|
||||
|
||||
def func():
|
||||
# PYI055
|
||||
item: type[requests_mock.Mocker] | type[httpretty] = requests_mock.Mocker
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
import builtins
|
||||
from typing import Union
|
||||
|
||||
|
||||
w: builtins.type[int] | builtins.type[str] | builtins.type[complex]
|
||||
x: type[int] | type[str] | type[float]
|
||||
y: builtins.type[int] | type[str] | builtins.type[complex]
|
||||
z: Union[type[float], type[complex]]
|
||||
z: Union[type[float, int], type[complex]]
|
||||
|
||||
|
||||
def func(arg: type[int] | str | type[float]) -> None: ...
|
||||
|
||||
# OK
|
||||
|
@ -16,5 +14,11 @@ x: type[int, str, float]
|
|||
y: builtins.type[int, str, complex]
|
||||
z: Union[float, complex]
|
||||
|
||||
|
||||
def func(arg: type[int, float] | str) -> None: ...
|
||||
|
||||
# OK
|
||||
item: type[requests_mock.Mocker] | type[httpretty] = requests_mock.Mocker
|
||||
|
||||
def func():
|
||||
# PYI055
|
||||
item: type[requests_mock.Mocker] | type[httpretty] = requests_mock.Mocker
|
||||
|
|
|
@ -43,6 +43,11 @@ impl Violation for UnnecessaryTypeUnion {
|
|||
|
||||
/// PYI055
|
||||
pub(crate) fn unnecessary_type_union<'a>(checker: &mut Checker, union: &'a Expr) {
|
||||
// The `|` operator isn't always safe to allow to runtime-evaluated annotations.
|
||||
if checker.semantic().execution_context().is_runtime() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut type_exprs = Vec::new();
|
||||
|
||||
// Check if `union` is a PEP604 union (e.g. `float | int`) or a `typing.Union[float, int]`
|
||||
|
|
|
@ -1,56 +1,12 @@
|
|||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI055.py:5:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[int | str | complex]`.
|
||||
|
|
||||
5 | w: builtins.type[int] | builtins.type[str] | builtins.type[complex]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
|
||||
6 | x: type[int] | type[str] | type[float]
|
||||
7 | y: builtins.type[int] | type[str] | builtins.type[complex]
|
||||
|
|
||||
|
||||
PYI055.py:6:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[int | str | float]`.
|
||||
|
|
||||
5 | w: builtins.type[int] | builtins.type[str] | builtins.type[complex]
|
||||
6 | x: type[int] | type[str] | type[float]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
|
||||
7 | y: builtins.type[int] | type[str] | builtins.type[complex]
|
||||
8 | z: Union[type[float], type[complex]]
|
||||
|
|
||||
|
||||
PYI055.py:7:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[int | str | complex]`.
|
||||
|
|
||||
5 | w: builtins.type[int] | builtins.type[str] | builtins.type[complex]
|
||||
6 | x: type[int] | type[str] | type[float]
|
||||
7 | y: builtins.type[int] | type[str] | builtins.type[complex]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
|
||||
8 | z: Union[type[float], type[complex]]
|
||||
9 | z: Union[type[float, int], type[complex]]
|
||||
|
|
||||
|
||||
PYI055.py:8:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[Union[float, complex]]`.
|
||||
|
|
||||
6 | x: type[int] | type[str] | type[float]
|
||||
7 | y: builtins.type[int] | type[str] | builtins.type[complex]
|
||||
8 | z: Union[type[float], type[complex]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
|
||||
9 | z: Union[type[float, int], type[complex]]
|
||||
|
|
||||
|
||||
PYI055.py:9:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[Union[float, int, complex]]`.
|
||||
|
|
||||
7 | y: builtins.type[int] | type[str] | builtins.type[complex]
|
||||
8 | z: Union[type[float], type[complex]]
|
||||
9 | z: Union[type[float, int], type[complex]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
|
||||
|
|
||||
|
||||
PYI055.py:12:15: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[int | float]`.
|
||||
PYI055.py:31:11: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[requests_mock.Mocker | httpretty]`.
|
||||
|
|
||||
12 | def func(arg: type[int] | str | type[float]) -> None: ...
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
|
||||
13 |
|
||||
14 | # OK
|
||||
29 | def func():
|
||||
30 | # PYI055
|
||||
31 | item: type[requests_mock.Mocker] | type[httpretty] = requests_mock.Mocker
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
|
||||
|
|
||||
|
||||
|
||||
|
|
|
@ -1,56 +1,79 @@
|
|||
---
|
||||
source: crates/ruff/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI055.pyi:5:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[int | str | complex]`.
|
||||
PYI055.pyi:4:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[int | str | complex]`.
|
||||
|
|
||||
5 | w: builtins.type[int] | builtins.type[str] | builtins.type[complex]
|
||||
2 | from typing import Union
|
||||
3 |
|
||||
4 | w: builtins.type[int] | builtins.type[str] | builtins.type[complex]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
|
||||
6 | x: type[int] | type[str] | type[float]
|
||||
7 | y: builtins.type[int] | type[str] | builtins.type[complex]
|
||||
5 | x: type[int] | type[str] | type[float]
|
||||
6 | y: builtins.type[int] | type[str] | builtins.type[complex]
|
||||
|
|
||||
|
||||
PYI055.pyi:6:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[int | str | float]`.
|
||||
PYI055.pyi:5:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[int | str | float]`.
|
||||
|
|
||||
5 | w: builtins.type[int] | builtins.type[str] | builtins.type[complex]
|
||||
6 | x: type[int] | type[str] | type[float]
|
||||
4 | w: builtins.type[int] | builtins.type[str] | builtins.type[complex]
|
||||
5 | x: type[int] | type[str] | type[float]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
|
||||
7 | y: builtins.type[int] | type[str] | builtins.type[complex]
|
||||
8 | z: Union[type[float], type[complex]]
|
||||
6 | y: builtins.type[int] | type[str] | builtins.type[complex]
|
||||
7 | z: Union[type[float], type[complex]]
|
||||
|
|
||||
|
||||
PYI055.pyi:7:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[int | str | complex]`.
|
||||
PYI055.pyi:6:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[int | str | complex]`.
|
||||
|
|
||||
5 | w: builtins.type[int] | builtins.type[str] | builtins.type[complex]
|
||||
6 | x: type[int] | type[str] | type[float]
|
||||
7 | y: builtins.type[int] | type[str] | builtins.type[complex]
|
||||
4 | w: builtins.type[int] | builtins.type[str] | builtins.type[complex]
|
||||
5 | x: type[int] | type[str] | type[float]
|
||||
6 | y: builtins.type[int] | type[str] | builtins.type[complex]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
|
||||
8 | z: Union[type[float], type[complex]]
|
||||
9 | z: Union[type[float, int], type[complex]]
|
||||
7 | z: Union[type[float], type[complex]]
|
||||
8 | z: Union[type[float, int], type[complex]]
|
||||
|
|
||||
|
||||
PYI055.pyi:8:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[Union[float, complex]]`.
|
||||
PYI055.pyi:7:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[Union[float, complex]]`.
|
||||
|
|
||||
6 | x: type[int] | type[str] | type[float]
|
||||
7 | y: builtins.type[int] | type[str] | builtins.type[complex]
|
||||
8 | z: Union[type[float], type[complex]]
|
||||
5 | x: type[int] | type[str] | type[float]
|
||||
6 | y: builtins.type[int] | type[str] | builtins.type[complex]
|
||||
7 | z: Union[type[float], type[complex]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
|
||||
9 | z: Union[type[float, int], type[complex]]
|
||||
8 | z: Union[type[float, int], type[complex]]
|
||||
|
|
||||
|
||||
PYI055.pyi:9:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[Union[float, int, complex]]`.
|
||||
|
|
||||
7 | y: builtins.type[int] | type[str] | builtins.type[complex]
|
||||
8 | z: Union[type[float], type[complex]]
|
||||
9 | z: Union[type[float, int], type[complex]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
|
||||
|
|
||||
|
||||
PYI055.pyi:12:15: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[int | float]`.
|
||||
PYI055.pyi:8:4: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[Union[float, int, complex]]`.
|
||||
|
|
||||
12 | def func(arg: type[int] | str | type[float]) -> None: ...
|
||||
6 | y: builtins.type[int] | type[str] | builtins.type[complex]
|
||||
7 | z: Union[type[float], type[complex]]
|
||||
8 | z: Union[type[float, int], type[complex]]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
|
||||
9 |
|
||||
10 | def func(arg: type[int] | str | type[float]) -> None: ...
|
||||
|
|
||||
|
||||
PYI055.pyi:10:15: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[int | float]`.
|
||||
|
|
||||
8 | z: Union[type[float, int], type[complex]]
|
||||
9 |
|
||||
10 | def func(arg: type[int] | str | type[float]) -> None: ...
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
|
||||
13 |
|
||||
14 | # OK
|
||||
11 |
|
||||
12 | # OK
|
||||
|
|
||||
|
||||
PYI055.pyi:20:7: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[requests_mock.Mocker | httpretty]`.
|
||||
|
|
||||
19 | # OK
|
||||
20 | item: type[requests_mock.Mocker] | type[httpretty] = requests_mock.Mocker
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
|
||||
21 |
|
||||
22 | def func():
|
||||
|
|
||||
|
||||
PYI055.pyi:24:11: PYI055 Multiple `type` members in a union. Combine them into one, e.g., `type[requests_mock.Mocker | httpretty]`.
|
||||
|
|
||||
22 | def func():
|
||||
23 | # PYI055
|
||||
24 | item: type[requests_mock.Mocker] | type[httpretty] = requests_mock.Mocker
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI055
|
||||
|
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue