From eaa10ad2d9ee9d38f9b1cc690c3a5e0ab7d62ff0 Mon Sep 17 00:00:00 2001 From: Tom Kuson Date: Thu, 22 Jun 2023 16:34:44 +0100 Subject: [PATCH] Fix `deprecated-import` false positives (#5291) ## Summary Remove recommendations to replace `typing_extensions.dataclass_transform` and `typing_extensions.SupportsIndex` with their `typing` library counterparts. Closes #5112. ## Test Plan Added extra checks to the test fixture. `cargo test` --- .../test/fixtures/pyupgrade/UP035.py | 9 +++++++ .../pyupgrade/rules/deprecated_import.rs | 26 +++++++++++++------ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/crates/ruff/resources/test/fixtures/pyupgrade/UP035.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP035.py index aefd7064d1..a185c4867f 100644 --- a/crates/ruff/resources/test/fixtures/pyupgrade/UP035.py +++ b/crates/ruff/resources/test/fixtures/pyupgrade/UP035.py @@ -48,3 +48,12 @@ if True: from collections import ( # OK from a import b + +# Ok: `typing_extensions` contains backported improvements. +from typing_extensions import SupportsIndex + +# Ok: `typing_extensions` contains backported improvements. +from typing_extensions import NamedTuple + +# Ok: `typing_extensions` supports `frozen_default` (backported from 3.12). +from typing_extensions import dataclass_transform diff --git a/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs b/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs index 335354234c..c2813769b6 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs @@ -43,6 +43,12 @@ enum Deprecation { /// Deprecated imports may be removed in future versions of Python, and /// should be replaced with their new equivalents. /// +/// Note that, in some cases, it may be preferable to continue importing +/// members from `typing_extensions` even after they're added to the Python +/// standard library, as `typing_extensions` can backport bugfixes and +/// optimizations from later Python versions. This rule thus avoids flagging +/// imports from `typing_extensions` in such cases. +/// /// ## Example /// ```python /// from collections import Sequence @@ -139,10 +145,12 @@ const TYPING_EXTENSIONS_TO_TYPING: &[&str] = &[ "ContextManager", "Coroutine", "DefaultDict", - "NewType", "TYPE_CHECKING", "Text", "Type", + // Introduced in Python 3.5.2, but `typing_extensions` contains backported bugfixes and + // optimizations, + // "NewType", ]; // Python 3.7+ @@ -168,11 +176,13 @@ const MYPY_EXTENSIONS_TO_TYPING_38: &[&str] = &["TypedDict"]; // Members of `typing_extensions` that were moved to `typing`. const TYPING_EXTENSIONS_TO_TYPING_38: &[&str] = &[ "Final", - "Literal", "OrderedDict", - "Protocol", - "SupportsIndex", "runtime_checkable", + // Introduced in Python 3.8, but `typing_extensions` contains backported bugfixes and + // optimizations. + // "Literal", + // "Protocol", + // "SupportsIndex", ]; // Python 3.9+ @@ -243,6 +253,8 @@ const TYPING_TO_COLLECTIONS_ABC_310: &[&str] = &["Callable"]; // Members of `typing_extensions` that were moved to `typing`. const TYPING_EXTENSIONS_TO_TYPING_310: &[&str] = &[ "Concatenate", + "Literal", + "NewType", "ParamSpecArgs", "ParamSpecKwargs", "TypeAlias", @@ -258,21 +270,19 @@ const TYPING_EXTENSIONS_TO_TYPING_310: &[&str] = &[ const TYPING_EXTENSIONS_TO_TYPING_311: &[&str] = &[ "Any", "LiteralString", - "NamedTuple", "Never", "NotRequired", "Required", "Self", - "TypedDict", - "Unpack", "assert_never", "assert_type", "clear_overloads", - "dataclass_transform", "final", "get_overloads", "overload", "reveal_type", + // Introduced in Python 3.11, but `typing_extensions` backports the `frozen_default` argument. + // "dataclass_transform", ]; struct ImportReplacer<'a> {