From a3d8b536103b1743db28a3cfebd8584a0c83437b Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 13 May 2024 13:21:52 -0400 Subject: [PATCH] Avoid flagging __future__ annotations as required for non-evaluated type annotations --- .../ok_quoted_type.py | 7 +++ .../src/checkers/ast/analyze/expression.rs | 4 ++ .../rules/flake8_future_annotations/mod.rs | 1 + ...02_no_future_import_uses_lowercase.py.snap | 17 ----- ..._fa102_no_future_import_uses_union.py.snap | 32 ---------- ..._no_future_import_uses_union_inner.py.snap | 62 ------------------- ...tions__tests__fa102_ok_quoted_type.py.snap | 4 ++ 7 files changed, 16 insertions(+), 111 deletions(-) create mode 100644 crates/ruff_linter/resources/test/fixtures/flake8_future_annotations/ok_quoted_type.py create mode 100644 crates/ruff_linter/src/rules/flake8_future_annotations/snapshots/ruff_linter__rules__flake8_future_annotations__tests__fa102_ok_quoted_type.py.snap diff --git a/crates/ruff_linter/resources/test/fixtures/flake8_future_annotations/ok_quoted_type.py b/crates/ruff_linter/resources/test/fixtures/flake8_future_annotations/ok_quoted_type.py new file mode 100644 index 0000000000000..0fb34cf55a94d --- /dev/null +++ b/crates/ruff_linter/resources/test/fixtures/flake8_future_annotations/ok_quoted_type.py @@ -0,0 +1,7 @@ +def main() -> None: + a_list: list[str] | None = [] + a_list.append("hello") + + +def hello(y: "dict[str, int] | None") -> None: + del y diff --git a/crates/ruff_linter/src/checkers/ast/analyze/expression.rs b/crates/ruff_linter/src/checkers/ast/analyze/expression.rs index 3a14cbc62b7ef..8382b766c0b08 100644 --- a/crates/ruff_linter/src/checkers/ast/analyze/expression.rs +++ b/crates/ruff_linter/src/checkers/ast/analyze/expression.rs @@ -62,6 +62,8 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { if !checker.semantic.future_annotations_or_stub() && checker.settings.target_version < PythonVersion::Py39 && checker.semantic.in_annotation() + && checker.semantic.in_runtime_evaluated_annotation() + && !checker.semantic.in_string_type_definition() && typing::is_pep585_generic(value, &checker.semantic) { flake8_future_annotations::rules::future_required_type_annotation( @@ -1195,6 +1197,8 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) { if !checker.semantic.future_annotations_or_stub() && checker.settings.target_version < PythonVersion::Py310 && checker.semantic.in_annotation() + && checker.semantic.in_runtime_evaluated_annotation() + && !checker.semantic.in_string_type_definition() { flake8_future_annotations::rules::future_required_type_annotation( checker, diff --git a/crates/ruff_linter/src/rules/flake8_future_annotations/mod.rs b/crates/ruff_linter/src/rules/flake8_future_annotations/mod.rs index d6265a78db735..d9b7c6bd60969 100644 --- a/crates/ruff_linter/src/rules/flake8_future_annotations/mod.rs +++ b/crates/ruff_linter/src/rules/flake8_future_annotations/mod.rs @@ -43,6 +43,7 @@ mod tests { #[test_case(Path::new("no_future_import_uses_union_inner.py"))] #[test_case(Path::new("ok_no_types.py"))] #[test_case(Path::new("ok_uses_future.py"))] + #[test_case(Path::new("ok_quoted_type.py"))] fn fa102(path: &Path) -> Result<()> { let snapshot = format!("fa102_{}", path.to_string_lossy()); let diagnostics = test_path( diff --git a/crates/ruff_linter/src/rules/flake8_future_annotations/snapshots/ruff_linter__rules__flake8_future_annotations__tests__fa102_no_future_import_uses_lowercase.py.snap b/crates/ruff_linter/src/rules/flake8_future_annotations/snapshots/ruff_linter__rules__flake8_future_annotations__tests__fa102_no_future_import_uses_lowercase.py.snap index 7270306f491bd..e9c8efa698a8f 100644 --- a/crates/ruff_linter/src/rules/flake8_future_annotations/snapshots/ruff_linter__rules__flake8_future_annotations__tests__fa102_no_future_import_uses_lowercase.py.snap +++ b/crates/ruff_linter/src/rules/flake8_future_annotations/snapshots/ruff_linter__rules__flake8_future_annotations__tests__fa102_no_future_import_uses_lowercase.py.snap @@ -1,21 +1,6 @@ --- source: crates/ruff_linter/src/rules/flake8_future_annotations/mod.rs --- -no_future_import_uses_lowercase.py:2:13: FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection - | -1 | def main() -> None: -2 | a_list: list[str] = [] - | ^^^^^^^^^ FA102 -3 | a_list.append("hello") - | - = help: Add `from __future__ import annotations` - -ℹ Unsafe fix - 1 |+from __future__ import annotations -1 2 | def main() -> None: -2 3 | a_list: list[str] = [] -3 4 | a_list.append("hello") - no_future_import_uses_lowercase.py:6:14: FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection | 6 | def hello(y: dict[str, int]) -> None: @@ -29,5 +14,3 @@ no_future_import_uses_lowercase.py:6:14: FA102 [*] Missing `from __future__ impo 1 2 | def main() -> None: 2 3 | a_list: list[str] = [] 3 4 | a_list.append("hello") - - diff --git a/crates/ruff_linter/src/rules/flake8_future_annotations/snapshots/ruff_linter__rules__flake8_future_annotations__tests__fa102_no_future_import_uses_union.py.snap b/crates/ruff_linter/src/rules/flake8_future_annotations/snapshots/ruff_linter__rules__flake8_future_annotations__tests__fa102_no_future_import_uses_union.py.snap index c2bfd9832c82e..3631ff04335a3 100644 --- a/crates/ruff_linter/src/rules/flake8_future_annotations/snapshots/ruff_linter__rules__flake8_future_annotations__tests__fa102_no_future_import_uses_union.py.snap +++ b/crates/ruff_linter/src/rules/flake8_future_annotations/snapshots/ruff_linter__rules__flake8_future_annotations__tests__fa102_no_future_import_uses_union.py.snap @@ -1,36 +1,6 @@ --- source: crates/ruff_linter/src/rules/flake8_future_annotations/mod.rs --- -no_future_import_uses_union.py:2:13: FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection - | -1 | def main() -> None: -2 | a_list: list[str] | None = [] - | ^^^^^^^^^ FA102 -3 | a_list.append("hello") - | - = help: Add `from __future__ import annotations` - -ℹ Unsafe fix - 1 |+from __future__ import annotations -1 2 | def main() -> None: -2 3 | a_list: list[str] | None = [] -3 4 | a_list.append("hello") - -no_future_import_uses_union.py:2:13: FA102 [*] Missing `from __future__ import annotations`, but uses PEP 604 union - | -1 | def main() -> None: -2 | a_list: list[str] | None = [] - | ^^^^^^^^^^^^^^^^ FA102 -3 | a_list.append("hello") - | - = help: Add `from __future__ import annotations` - -ℹ Unsafe fix - 1 |+from __future__ import annotations -1 2 | def main() -> None: -2 3 | a_list: list[str] | None = [] -3 4 | a_list.append("hello") - no_future_import_uses_union.py:6:14: FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection | 6 | def hello(y: dict[str, int] | None) -> None: @@ -58,5 +28,3 @@ no_future_import_uses_union.py:6:14: FA102 [*] Missing `from __future__ import a 1 2 | def main() -> None: 2 3 | a_list: list[str] | None = [] 3 4 | a_list.append("hello") - - diff --git a/crates/ruff_linter/src/rules/flake8_future_annotations/snapshots/ruff_linter__rules__flake8_future_annotations__tests__fa102_no_future_import_uses_union_inner.py.snap b/crates/ruff_linter/src/rules/flake8_future_annotations/snapshots/ruff_linter__rules__flake8_future_annotations__tests__fa102_no_future_import_uses_union_inner.py.snap index 3e76aee3575d4..2f2e6dbb0375a 100644 --- a/crates/ruff_linter/src/rules/flake8_future_annotations/snapshots/ruff_linter__rules__flake8_future_annotations__tests__fa102_no_future_import_uses_union_inner.py.snap +++ b/crates/ruff_linter/src/rules/flake8_future_annotations/snapshots/ruff_linter__rules__flake8_future_annotations__tests__fa102_no_future_import_uses_union_inner.py.snap @@ -1,36 +1,6 @@ --- source: crates/ruff_linter/src/rules/flake8_future_annotations/mod.rs --- -no_future_import_uses_union_inner.py:2:13: FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection - | -1 | def main() -> None: -2 | a_list: list[str | None] = [] - | ^^^^^^^^^^^^^^^^ FA102 -3 | a_list.append("hello") - | - = help: Add `from __future__ import annotations` - -ℹ Unsafe fix - 1 |+from __future__ import annotations -1 2 | def main() -> None: -2 3 | a_list: list[str | None] = [] -3 4 | a_list.append("hello") - -no_future_import_uses_union_inner.py:2:18: FA102 [*] Missing `from __future__ import annotations`, but uses PEP 604 union - | -1 | def main() -> None: -2 | a_list: list[str | None] = [] - | ^^^^^^^^^^ FA102 -3 | a_list.append("hello") - | - = help: Add `from __future__ import annotations` - -ℹ Unsafe fix - 1 |+from __future__ import annotations -1 2 | def main() -> None: -2 3 | a_list: list[str | None] = [] -3 4 | a_list.append("hello") - no_future_import_uses_union_inner.py:6:14: FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection | 6 | def hello(y: dict[str | None, int]) -> None: @@ -60,35 +30,3 @@ no_future_import_uses_union_inner.py:6:19: FA102 [*] Missing `from __future__ im 1 2 | def main() -> None: 2 3 | a_list: list[str | None] = [] 3 4 | a_list.append("hello") - -no_future_import_uses_union_inner.py:7:8: FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection - | -6 | def hello(y: dict[str | None, int]) -> None: -7 | z: tuple[str, str | None, str] = tuple(y) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ FA102 -8 | del z - | - = help: Add `from __future__ import annotations` - -ℹ Unsafe fix - 1 |+from __future__ import annotations -1 2 | def main() -> None: -2 3 | a_list: list[str | None] = [] -3 4 | a_list.append("hello") - -no_future_import_uses_union_inner.py:7:19: FA102 [*] Missing `from __future__ import annotations`, but uses PEP 604 union - | -6 | def hello(y: dict[str | None, int]) -> None: -7 | z: tuple[str, str | None, str] = tuple(y) - | ^^^^^^^^^^ FA102 -8 | del z - | - = help: Add `from __future__ import annotations` - -ℹ Unsafe fix - 1 |+from __future__ import annotations -1 2 | def main() -> None: -2 3 | a_list: list[str | None] = [] -3 4 | a_list.append("hello") - - diff --git a/crates/ruff_linter/src/rules/flake8_future_annotations/snapshots/ruff_linter__rules__flake8_future_annotations__tests__fa102_ok_quoted_type.py.snap b/crates/ruff_linter/src/rules/flake8_future_annotations/snapshots/ruff_linter__rules__flake8_future_annotations__tests__fa102_ok_quoted_type.py.snap new file mode 100644 index 0000000000000..0e51cf4a6fa77 --- /dev/null +++ b/crates/ruff_linter/src/rules/flake8_future_annotations/snapshots/ruff_linter__rules__flake8_future_annotations__tests__fa102_ok_quoted_type.py.snap @@ -0,0 +1,4 @@ +--- +source: crates/ruff_linter/src/rules/flake8_future_annotations/mod.rs +--- +