From ad1ca72a358800958981856e8938c88570672f27 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Tue, 9 Jan 2024 12:52:01 -0500 Subject: [PATCH] Add some additional Python 3.12 typing members to `deprecated-import` (#9445) Closes https://github.com/astral-sh/ruff/issues/9443. --- .../test/fixtures/pyupgrade/UP035.py | 9 +++ .../pyupgrade/rules/deprecated_import.rs | 38 ++++++++- ...er__rules__pyupgrade__tests__UP035.py.snap | 80 ++++++++++++++----- 3 files changed, 105 insertions(+), 22 deletions(-) diff --git a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP035.py b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP035.py index 48d6929653..bd30ac03e3 100644 --- a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP035.py +++ b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP035.py @@ -91,3 +91,12 @@ from typing_extensions import dataclass_transform # UP035 from backports.strenum import StrEnum + +# UP035 +from typing_extensions import override + +# UP035 +from typing_extensions import Buffer + +# UP035 +from typing_extensions import get_original_bases diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_import.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_import.rs index 01e7e35f67..daee5a884f 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_import.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/deprecated_import.rs @@ -332,7 +332,12 @@ const BACKPORTS_STR_ENUM_TO_ENUM_311: &[&str] = &["StrEnum"]; // Members of `typing_extensions` that were moved to `typing`. const TYPING_EXTENSIONS_TO_TYPING_312: &[&str] = &[ - "NamedTuple", + // Introduced in Python 3.12, but `typing_extensions` backports some bug fixes. + // "NamedTuple", + + // Introduced in Python 3.12, but `typing_extensions` backports support for PEP 705. + // "TypedDict", + // Introduced in Python 3.8, but `typing_extensions` backports a ton of optimizations that were // added in Python 3.12. "Protocol", @@ -342,13 +347,20 @@ const TYPING_EXTENSIONS_TO_TYPING_312: &[&str] = &[ "SupportsFloat", "SupportsInt", "SupportsRound", - "TypedDict", + "TypeAliasType", "Unpack", // Introduced in Python 3.11, but `typing_extensions` backports the `frozen_default` argument, // which was introduced in Python 3.12. "dataclass_transform", + "override", ]; +// Members of `typing_extensions` that were moved to `collections.abc`. +const TYPING_EXTENSIONS_TO_COLLECTIONS_ABC_312: &[&str] = &["Buffer"]; + +// Members of `typing_extensions` that were moved to `types`. +const TYPING_EXTENSIONS_TO_TYPES_312: &[&str] = &["get_original_bases"]; + struct ImportReplacer<'a> { stmt: &'a Stmt, module: &'a str, @@ -417,6 +429,28 @@ impl<'a> ImportReplacer<'a> { } } "typing_extensions" => { + // `typing_extensions` to `collections.abc` + let mut typing_extensions_to_collections_abc = vec![]; + if self.version >= PythonVersion::Py312 { + typing_extensions_to_collections_abc + .extend(TYPING_EXTENSIONS_TO_COLLECTIONS_ABC_312); + } + if let Some(operation) = + self.try_replace(&typing_extensions_to_collections_abc, "collections.abc") + { + operations.push(operation); + } + + // `typing_extensions` to `types` + let mut typing_extensions_to_types = vec![]; + if self.version >= PythonVersion::Py312 { + typing_extensions_to_types.extend(TYPING_EXTENSIONS_TO_TYPES_312); + } + if let Some(operation) = self.try_replace(&typing_extensions_to_types, "types") { + operations.push(operation); + } + + // `typing_extensions` to `typing` let mut typing_extensions_to_typing = TYPING_EXTENSIONS_TO_TYPING.to_vec(); if self.version >= PythonVersion::Py37 { typing_extensions_to_typing.extend(TYPING_EXTENSIONS_TO_TYPING_37); diff --git a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP035.py.snap b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP035.py.snap index 654b5df7c8..ddc6941a2c 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP035.py.snap +++ b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP035.py.snap @@ -995,26 +995,6 @@ UP035.py:77:1: UP035 [*] Import from `collections.abc` instead: `Callable` 79 79 | 80 80 | # OK -UP035.py:87:1: UP035 [*] Import from `typing` instead: `NamedTuple` - | -86 | # OK: `typing_extensions` contains backported improvements. -87 | from typing_extensions import NamedTuple - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 -88 | -89 | # OK: `typing_extensions` supports `frozen_default` (backported from 3.12). - | - = help: Import from `typing` - -ℹ Safe fix -84 84 | from typing_extensions import SupportsIndex -85 85 | -86 86 | # OK: `typing_extensions` contains backported improvements. -87 |-from typing_extensions import NamedTuple - 87 |+from typing import NamedTuple -88 88 | -89 89 | # OK: `typing_extensions` supports `frozen_default` (backported from 3.12). -90 90 | from typing_extensions import dataclass_transform - UP035.py:90:1: UP035 [*] Import from `typing` instead: `dataclass_transform` | 89 | # OK: `typing_extensions` supports `frozen_default` (backported from 3.12). @@ -1040,6 +1020,8 @@ UP035.py:93:1: UP035 [*] Import from `enum` instead: `StrEnum` 92 | # UP035 93 | from backports.strenum import StrEnum | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +94 | +95 | # UP035 | = help: Import from `enum` @@ -1049,5 +1031,63 @@ UP035.py:93:1: UP035 [*] Import from `enum` instead: `StrEnum` 92 92 | # UP035 93 |-from backports.strenum import StrEnum 93 |+from enum import StrEnum +94 94 | +95 95 | # UP035 +96 96 | from typing_extensions import override + +UP035.py:96:1: UP035 [*] Import from `typing` instead: `override` + | +95 | # UP035 +96 | from typing_extensions import override + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +97 | +98 | # UP035 + | + = help: Import from `typing` + +ℹ Safe fix +93 93 | from backports.strenum import StrEnum +94 94 | +95 95 | # UP035 +96 |-from typing_extensions import override + 96 |+from typing import override +97 97 | +98 98 | # UP035 +99 99 | from typing_extensions import Buffer + +UP035.py:99:1: UP035 [*] Import from `collections.abc` instead: `Buffer` + | + 98 | # UP035 + 99 | from typing_extensions import Buffer + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 +100 | +101 | # UP035 + | + = help: Import from `collections.abc` + +ℹ Safe fix +96 96 | from typing_extensions import override +97 97 | +98 98 | # UP035 +99 |-from typing_extensions import Buffer + 99 |+from collections.abc import Buffer +100 100 | +101 101 | # UP035 +102 102 | from typing_extensions import get_original_bases + +UP035.py:102:1: UP035 [*] Import from `types` instead: `get_original_bases` + | +101 | # UP035 +102 | from typing_extensions import get_original_bases + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ UP035 + | + = help: Import from `types` + +ℹ Safe fix +99 99 | from typing_extensions import Buffer +100 100 | +101 101 | # UP035 +102 |-from typing_extensions import get_original_bases + 102 |+from types import get_original_bases