diff --git a/crates/ruff_linter/resources/test/fixtures/flake8_type_checking/TC001_future.py b/crates/ruff_linter/resources/test/fixtures/flake8_type_checking/TC001_future.py new file mode 100644 index 0000000000..a548df3274 --- /dev/null +++ b/crates/ruff_linter/resources/test/fixtures/flake8_type_checking/TC001_future.py @@ -0,0 +1,68 @@ +def f(): + from . import first_party + + def f(x: first_party.foo): ... + + +# Type parameter bounds +def g(): + from . import foo + + class C[T: foo.Ty]: ... + + +def h(): + from . import foo + + def f[T: foo.Ty](x: T): ... + + +def i(): + from . import foo + + type Alias[T: foo.Ty] = list[T] + + +# Type parameter defaults +def j(): + from . import foo + + class C[T = foo.Ty]: ... + + +def k(): + from . import foo + + def f[T = foo.Ty](x: T): ... + + +def l(): + from . import foo + + type Alias[T = foo.Ty] = list[T] + + +# non-generic type alias +def m(): + from . import foo + + type Alias = foo.Ty + + +# unions +from typing import Union + + +def n(): + from . import foo + + def f(x: Union[foo.Ty, int]): ... + def g(x: foo.Ty | int): ... + + +# runtime and typing usage +def o(): + from . import foo + + def f(x: foo.Ty): + return foo.Ty() diff --git a/crates/ruff_linter/src/rules/flake8_type_checking/mod.rs b/crates/ruff_linter/src/rules/flake8_type_checking/mod.rs index 8722e0bd4c..5f24964268 100644 --- a/crates/ruff_linter/src/rules/flake8_type_checking/mod.rs +++ b/crates/ruff_linter/src/rules/flake8_type_checking/mod.rs @@ -75,6 +75,7 @@ mod tests { ], Path::new("TC001-3_future.py") )] + #[test_case(&[Rule::TypingOnlyFirstPartyImport], Path::new("TC001_future.py"))] #[test_case(&[Rule::TypingOnlyFirstPartyImport], Path::new("TC001_future_present.py"))] fn add_future_import(rules: &[Rule], path: &Path) -> Result<()> { let name = rules.iter().map(Rule::name).join("-"); diff --git a/crates/ruff_linter/src/rules/flake8_type_checking/snapshots/ruff_linter__rules__flake8_type_checking__tests__add_future_import__typing-only-first-party-import_TC001_future.py.snap b/crates/ruff_linter/src/rules/flake8_type_checking/snapshots/ruff_linter__rules__flake8_type_checking__tests__add_future_import__typing-only-first-party-import_TC001_future.py.snap new file mode 100644 index 0000000000..0ecb18cd62 --- /dev/null +++ b/crates/ruff_linter/src/rules/flake8_type_checking/snapshots/ruff_linter__rules__flake8_type_checking__tests__add_future_import__typing-only-first-party-import_TC001_future.py.snap @@ -0,0 +1,56 @@ +--- +source: crates/ruff_linter/src/rules/flake8_type_checking/mod.rs +--- +TC001_future.py:2:19: TC001 [*] Move application import `.first_party` into a type-checking block + | +1 | def f(): +2 | from . import first_party + | ^^^^^^^^^^^ TC001 +3 | +4 | def f(x: first_party.foo): ... + | + = help: Move into type-checking block + +ℹ Unsafe fix +1 |-def f(): + 1 |+from __future__ import annotations + 2 |+from typing import TYPE_CHECKING + 3 |+ + 4 |+if TYPE_CHECKING: +2 5 | from . import first_party + 6 |+def f(): +3 7 | +4 8 | def f(x: first_party.foo): ... +5 9 | + +TC001_future.py:57:19: TC001 [*] Move application import `.foo` into a type-checking block + | +56 | def n(): +57 | from . import foo + | ^^^ TC001 +58 | +59 | def f(x: Union[foo.Ty, int]): ... + | + = help: Move into type-checking block + +ℹ Unsafe fix + 1 |+from __future__ import annotations +1 2 | def f(): +2 3 | from . import first_party +3 4 | +-------------------------------------------------------------------------------- +50 51 | +51 52 | +52 53 | # unions +53 |-from typing import Union + 54 |+from typing import Union, TYPE_CHECKING +54 55 | + 56 |+if TYPE_CHECKING: + 57 |+ from . import foo + 58 |+ +55 59 | +56 60 | def n(): +57 |- from . import foo +58 61 | +59 62 | def f(x: Union[foo.Ty, int]): ... +60 63 | def g(x: foo.Ty | int): ...