From 5605a0265f8aa256198ceec6106e8ea7ee60705d Mon Sep 17 00:00:00 2001 From: wookie184 Date: Fri, 30 Jun 2023 13:09:20 +0000 Subject: [PATCH 1/3] Add all PEP-585 names to UP006 rule --- .../test/fixtures/pyupgrade/UP006_0.py | 12 +++ .../test/fixtures/pyupgrade/UP006_1.py | 16 ++++ ...__rules__pyupgrade__tests__UP006_0.py.snap | 78 +++++++++++++++++++ ...__rules__pyupgrade__tests__UP006_1.py.snap | 28 +++++++ crates/ruff_python_semantic/src/model.rs | 3 +- crates/ruff_python_stdlib/src/typing.rs | 65 +++++++++++++--- 6 files changed, 189 insertions(+), 13 deletions(-) diff --git a/crates/ruff/resources/test/fixtures/pyupgrade/UP006_0.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP006_0.py index 106366ec2cc2b..4def08264ee9c 100644 --- a/crates/ruff/resources/test/fixtures/pyupgrade/UP006_0.py +++ b/crates/ruff/resources/test/fixtures/pyupgrade/UP006_0.py @@ -64,3 +64,15 @@ def f(x: typing.Deque[str]) -> None: def f(x: typing.DefaultDict[str, str]) -> None: ... + + +def f(x: typing.AbstractSet[str]) -> None: + ... + + +def f(x: typing.Pattern[str]) -> None: + ... + + +def f(x: typing.Sequence[str]) -> None: + ... diff --git a/crates/ruff/resources/test/fixtures/pyupgrade/UP006_1.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP006_1.py index 1f56c64011a15..95b8581cb1b8c 100644 --- a/crates/ruff/resources/test/fixtures/pyupgrade/UP006_1.py +++ b/crates/ruff/resources/test/fixtures/pyupgrade/UP006_1.py @@ -8,3 +8,19 @@ def f(x: typing.DefaultDict[str, str]) -> None: ... + + +from collections.abc import Set +from typing_extensions import Awaitable + + +def f(x: typing.AbstractSet[str]) -> None: + ... + + +def f(x: Set) -> None: + ... + + +def f(x: Awaitable) -> None: + ... diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP006_0.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP006_0.py.snap index 2e0f6ee588794..7c52aa72cb779 100644 --- a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP006_0.py.snap +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP006_0.py.snap @@ -280,5 +280,83 @@ UP006_0.py:65:10: UP006 [*] Use `collections.defaultdict` instead of `typing.Def 65 |-def f(x: typing.DefaultDict[str, str]) -> None: 66 |+def f(x: defaultdict[str, str]) -> None: 66 67 | ... +67 68 | +68 69 | + +UP006_0.py:69:10: UP006 [*] Use `collections.abc.Set` instead of `typing.AbstractSet` for type annotation + | +69 | def f(x: typing.AbstractSet[str]) -> None: + | ^^^^^^^^^^^^^^^^^^ UP006 +70 | ... + | + = help: Replace with `collections.abc.Set` + +ℹ Suggested fix +20 20 | +21 21 | +22 22 | from typing import List as IList + 23 |+from collections.abc import Set +23 24 | +24 25 | +25 26 | def f(x: IList[str]) -> None: +-------------------------------------------------------------------------------- +66 67 | ... +67 68 | +68 69 | +69 |-def f(x: typing.AbstractSet[str]) -> None: + 70 |+def f(x: Set[str]) -> None: +70 71 | ... +71 72 | +72 73 | + +UP006_0.py:73:10: UP006 [*] Use `re.Pattern` instead of `typing.Pattern` for type annotation + | +73 | def f(x: typing.Pattern[str]) -> None: + | ^^^^^^^^^^^^^^ UP006 +74 | ... + | + = help: Replace with `re.Pattern` + +ℹ Suggested fix +20 20 | +21 21 | +22 22 | from typing import List as IList + 23 |+from re import Pattern +23 24 | +24 25 | +25 26 | def f(x: IList[str]) -> None: +-------------------------------------------------------------------------------- +70 71 | ... +71 72 | +72 73 | +73 |-def f(x: typing.Pattern[str]) -> None: + 74 |+def f(x: Pattern[str]) -> None: +74 75 | ... +75 76 | +76 77 | + +UP006_0.py:77:10: UP006 [*] Use `collections.abc.Sequence` instead of `typing.Sequence` for type annotation + | +77 | def f(x: typing.Sequence[str]) -> None: + | ^^^^^^^^^^^^^^^ UP006 +78 | ... + | + = help: Replace with `collections.abc.Sequence` + +ℹ Suggested fix +20 20 | +21 21 | +22 22 | from typing import List as IList + 23 |+from collections.abc import Sequence +23 24 | +24 25 | +25 26 | def f(x: IList[str]) -> None: +-------------------------------------------------------------------------------- +74 75 | ... +75 76 | +76 77 | +77 |-def f(x: typing.Sequence[str]) -> None: + 78 |+def f(x: Sequence[str]) -> None: +78 79 | ... diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP006_1.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP006_1.py.snap index d0b32a6494443..d8520c6a98843 100644 --- a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP006_1.py.snap +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP006_1.py.snap @@ -16,5 +16,33 @@ UP006_1.py:9:10: UP006 [*] Use `collections.defaultdict` instead of `typing.Defa 9 |-def f(x: typing.DefaultDict[str, str]) -> None: 9 |+def f(x: defaultdict[str, str]) -> None: 10 10 | ... +11 11 | +12 12 | + +UP006_1.py:17:10: UP006 [*] Use `collections.abc.Set` instead of `typing.AbstractSet` for type annotation + | +17 | def f(x: typing.AbstractSet[str]) -> None: + | ^^^^^^^^^^^^^^^^^^ UP006 +18 | ... + | + = help: Replace with `collections.abc.Set` + +ℹ Suggested fix +14 14 | from typing_extensions import Awaitable +15 15 | +16 16 | +17 |-def f(x: typing.AbstractSet[str]) -> None: + 17 |+def f(x: Set[str]) -> None: +18 18 | ... +19 19 | +20 20 | + +UP006_1.py:25:10: UP006 Use `collections.abc.Awaitable` instead of `Awaitable` for type annotation + | +25 | def f(x: Awaitable) -> None: + | ^^^^^^^^^ UP006 +26 | ... + | + = help: Replace with `collections.abc.Awaitable` diff --git a/crates/ruff_python_semantic/src/model.rs b/crates/ruff_python_semantic/src/model.rs index 619020ac12bbb..20aa419452767 100644 --- a/crates/ruff_python_semantic/src/model.rs +++ b/crates/ruff_python_semantic/src/model.rs @@ -601,7 +601,8 @@ impl<'a> SemanticModel<'a> { // `from os.path import join` -> `join` // `from os.path import join as join2` -> `join2` BindingKind::FromImport(FromImport { qualified_name }) => { - if let Some((target_module, target_member)) = qualified_name.split_once('.') + if let Some((target_module, target_member)) = + qualified_name.rsplit_once('.') { if target_module == module && target_member == member { if let Some(source) = binding.source { diff --git a/crates/ruff_python_stdlib/src/typing.rs b/crates/ruff_python_stdlib/src/typing.rs index 796f7c3a07c6b..a2c1691581d35 100644 --- a/crates/ruff_python_stdlib/src/typing.rs +++ b/crates/ruff_python_stdlib/src/typing.rs @@ -366,18 +366,59 @@ type ModuleMember = (&'static str, &'static str); /// /// [PEP 585]: https://peps.python.org/pep-0585/ pub fn as_pep_585_generic(module: &str, member: &str) -> Option { - match (module, member) { - ("typing", "Dict") => Some(("", "dict")), - ("typing", "FrozenSet") => Some(("", "frozenset")), - ("typing", "List") => Some(("", "list")), - ("typing", "Set") => Some(("", "set")), - ("typing", "Tuple") => Some(("", "tuple")), - ("typing", "Type") => Some(("", "type")), - ("typing_extensions", "Type") => Some(("", "type")), - ("typing", "Deque") => Some(("collections", "deque")), - ("typing_extensions", "Deque") => Some(("collections", "deque")), - ("typing", "DefaultDict") => Some(("collections", "defaultdict")), - ("typing_extensions", "DefaultDict") => Some(("collections", "defaultdict")), + // typing_extensions mirrors all the relevant types defined in typing. + if module != "typing" && module != "typing_extensions" { + return None; + }; + + match member { + // Builtins + "Tuple" => Some(("", "tuple")), + "List" => Some(("", "list")), + "Dict" => Some(("", "dict")), + "Set" => Some(("", "set")), + "FrozenSet" => Some(("", "frozenset")), + "Type" => Some(("", "type")), + + // collections + "Deque" => Some(("collections", "deque")), + "DefaultDict" => Some(("collections", "defaultdict")), + "OrderedDict" => Some(("collections", "OrderedDict")), + "Counter" => Some(("collections", "Counter")), + "ChainMap" => Some(("collections", "ChainMap")), + + // collections.abc + "Awaitable" => Some(("collections.abc", "Awaitable")), + "Coroutine" => Some(("collections.abc", "Coroutine")), + "AsyncIterable" => Some(("collections.abc", "AsyncIterable")), + "AsyncGenerator" => Some(("collections.abc", "AsyncGenerator")), + "Iterable" => Some(("collections.abc", "Iterable")), + "Iterator" => Some(("collections.abc", "Iterator")), + "Generator" => Some(("collections.abc", "Generator")), + "Reversible" => Some(("collections.abc", "Reversible")), + "Container" => Some(("collections.abc", "Container")), + "Collection" => Some(("collections.abc", "Collection")), + "Callable" => Some(("collections.abc", "Callable")), + "AbstractSet" => Some(("collections.abc", "Set")), + "MutableSet" => Some(("collections.abc", "MutableSet")), + "Mapping" => Some(("collections.abc", "Mapping")), + "MutableMapping" => Some(("collections.abc", "MutableMapping")), + "Sequence" => Some(("collections.abc", "Sequence")), + "MutableSequence" => Some(("collections.abc", "MutableSequence")), + "ByteString" => Some(("collections.abc", "ByteString")), + "MappingView" => Some(("collections.abc", "MappingView")), + "KeysView" => Some(("collections.abc", "KeysView")), + "ItemsView" => Some(("collections.abc", "ItemsView")), + "ValuesView" => Some(("collections.abc", "ValuesView")), + + // contextlib + "ContextManager" => Some(("contextlib", "AbstractContextManager")), + "AsyncContextManager" => Some(("contextlib", "AbstractAsyncContextManager")), + + // re + "Pattern" => Some(("re", "Pattern")), + "Match" => Some(("re", "Match")), + _ => None, } } From 80907f8a31331f90faf772f64bcb3731c863ff5d Mon Sep 17 00:00:00 2001 From: wookie184 Date: Fri, 7 Jul 2023 17:52:34 +0000 Subject: [PATCH 2/3] Don't fix UP006 if there is a name conflict --- .../test/fixtures/pyupgrade/UP006_0.py | 6 ++++ .../pyupgrade/rules/use_pep585_annotation.rs | 28 ++++++++++++------- ...__rules__pyupgrade__tests__UP006_0.py.snap | 12 ++++++++ 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/crates/ruff/resources/test/fixtures/pyupgrade/UP006_0.py b/crates/ruff/resources/test/fixtures/pyupgrade/UP006_0.py index 4def08264ee9c..d5970d2145922 100644 --- a/crates/ruff/resources/test/fixtures/pyupgrade/UP006_0.py +++ b/crates/ruff/resources/test/fixtures/pyupgrade/UP006_0.py @@ -76,3 +76,9 @@ def f(x: typing.Pattern[str]) -> None: def f(x: typing.Sequence[str]) -> None: ... + + +from typing import Collection + +def f(x: typing.Collection[str]) -> None: + ... \ No newline at end of file diff --git a/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs b/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs index b5ceee9e8ad1f..b2cbaf3013ea0 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/use_pep585_annotation.rs @@ -1,12 +1,13 @@ use rustpython_parser::ast::{Expr, Ranged}; +use log::error; use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation}; use ruff_macros::{derive_message_formats, violation}; use ruff_python_ast::call_path::compose_call_path; use ruff_python_semantic::analyze::typing::ModuleMember; use crate::checkers::ast::Checker; -use crate::importer::ImportRequest; +use crate::importer::{ImportRequest, ResolutionError}; use crate::registry::AsRule; /// ## What it does @@ -90,15 +91,22 @@ pub(crate) fn use_pep585_annotation( } ModuleMember::Member(module, member) => { // Imported type, like `collections.deque`. - diagnostic.try_set_fix(|| { - let (import_edit, binding) = checker.importer.get_or_import_symbol( - &ImportRequest::import_from(module, member), - expr.start(), - checker.semantic(), - )?; - let reference_edit = Edit::range_replacement(binding, expr.range()); - Ok(Fix::suggested_edits(import_edit, [reference_edit])) - }); + let result = checker.importer.get_or_import_symbol( + &ImportRequest::import_from(module, member), + expr.start(), + checker.semantic(), + ); + + match result { + Ok((import_edit, binding)) => { + let reference_edit = Edit::range_replacement(binding, expr.range()); + diagnostic.set_fix(Fix::suggested_edits(import_edit, [reference_edit])); + } + Err(ResolutionError::ConflictingName(_)) => {} + Err(err) => { + error!("Failed to create fix for {}: {}", diagnostic.kind.name, err); + } + } } } } diff --git a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP006_0.py.snap b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP006_0.py.snap index 7c52aa72cb779..c595119edd92b 100644 --- a/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP006_0.py.snap +++ b/crates/ruff/src/rules/pyupgrade/snapshots/ruff__rules__pyupgrade__tests__UP006_0.py.snap @@ -358,5 +358,17 @@ UP006_0.py:77:10: UP006 [*] Use `collections.abc.Sequence` instead of `typing.Se 77 |-def f(x: typing.Sequence[str]) -> None: 78 |+def f(x: Sequence[str]) -> None: 78 79 | ... +79 80 | +80 81 | + +UP006_0.py:83:10: UP006 Use `collections.abc.Collection` instead of `typing.Collection` for type annotation + | +81 | from typing import Collection +82 | +83 | def f(x: typing.Collection[str]) -> None: + | ^^^^^^^^^^^^^^^^^ UP006 +84 | ... + | + = help: Replace with `collections.abc.Collection` From 3a46aeb3666188712ad5c9d6544ce6b9576efa39 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Thu, 30 Nov 2023 20:54:09 -0500 Subject: [PATCH 3/3] Update reverse list --- .../test/fixtures/pyupgrade/UP006_0.py | 3 +- ...__rules__pyupgrade__tests__UP006_0.py.snap | 14 +- ...__rules__pyupgrade__tests__UP006_1.py.snap | 2 +- .../src/analyze/typing.rs | 5 +- crates/ruff_python_stdlib/src/typing.rs | 132 ++++++++++++------ 5 files changed, 96 insertions(+), 60 deletions(-) diff --git a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP006_0.py b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP006_0.py index d5970d2145922..22db1027ad826 100644 --- a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP006_0.py +++ b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP006_0.py @@ -80,5 +80,6 @@ def f(x: typing.Sequence[str]) -> None: from typing import Collection + def f(x: typing.Collection[str]) -> None: - ... \ No newline at end of file + ... diff --git a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP006_0.py.snap b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP006_0.py.snap index 9333c6354f827..945161cae9fad 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP006_0.py.snap +++ b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP006_0.py.snap @@ -291,7 +291,7 @@ UP006_0.py:69:10: UP006 [*] Use `collections.abc.Set` instead of `typing.Abstrac | = help: Replace with `collections.abc.Set` -ℹ Suggested fix +ℹ Unsafe fix 20 20 | 21 21 | 22 22 | from typing import List as IList @@ -317,7 +317,7 @@ UP006_0.py:73:10: UP006 [*] Use `re.Pattern` instead of `typing.Pattern` for typ | = help: Replace with `re.Pattern` -ℹ Suggested fix +ℹ Unsafe fix 20 20 | 21 21 | 22 22 | from typing import List as IList @@ -343,7 +343,7 @@ UP006_0.py:77:10: UP006 [*] Use `collections.abc.Sequence` instead of `typing.Se | = help: Replace with `collections.abc.Sequence` -ℹ Suggested fix +ℹ Unsafe fix 20 20 | 21 21 | 22 22 | from typing import List as IList @@ -361,13 +361,11 @@ UP006_0.py:77:10: UP006 [*] Use `collections.abc.Sequence` instead of `typing.Se 79 80 | 80 81 | -UP006_0.py:83:10: UP006 Use `collections.abc.Collection` instead of `typing.Collection` for type annotation +UP006_0.py:84:10: UP006 Use `collections.abc.Collection` instead of `typing.Collection` for type annotation | -81 | from typing import Collection -82 | -83 | def f(x: typing.Collection[str]) -> None: +84 | def f(x: typing.Collection[str]) -> None: | ^^^^^^^^^^^^^^^^^ UP006 -84 | ... +85 | ... | = help: Replace with `collections.abc.Collection` diff --git a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP006_1.py.snap b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP006_1.py.snap index dd55f35397fea..fbf7906cd92a3 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP006_1.py.snap +++ b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP006_1.py.snap @@ -27,7 +27,7 @@ UP006_1.py:17:10: UP006 [*] Use `collections.abc.Set` instead of `typing.Abstrac | = help: Replace with `collections.abc.Set` -ℹ Suggested fix +ℹ Unsafe fix 14 14 | from typing_extensions import Awaitable 15 15 | 16 16 | diff --git a/crates/ruff_python_semantic/src/analyze/typing.rs b/crates/ruff_python_semantic/src/analyze/typing.rs index bd18f70ba8aae..0619c7c07bc35 100644 --- a/crates/ruff_python_semantic/src/analyze/typing.rs +++ b/crates/ruff_python_semantic/src/analyze/typing.rs @@ -102,10 +102,7 @@ impl std::fmt::Display for ModuleMember { /// a variant exists. pub fn to_pep585_generic(expr: &Expr, semantic: &SemanticModel) -> Option { semantic.resolve_call_path(expr).and_then(|call_path| { - let [module, member] = call_path.as_slice() else { - return None; - }; - as_pep_585_generic(module, member).map(|(module, member)| { + as_pep_585_generic(call_path.as_slice()).map(|(module, member)| { if module.is_empty() { ModuleMember::BuiltIn(member) } else { diff --git a/crates/ruff_python_stdlib/src/typing.rs b/crates/ruff_python_stdlib/src/typing.rs index 32fa765d95adb..7899fb637998d 100644 --- a/crates/ruff_python_stdlib/src/typing.rs +++ b/crates/ruff_python_stdlib/src/typing.rs @@ -375,59 +375,68 @@ type ModuleMember = (&'static str, &'static str); /// library (e.g., `list` for `typing.List`), if such a generic was introduced by [PEP 585]. /// /// [PEP 585]: https://peps.python.org/pep-0585/ -pub fn as_pep_585_generic(module: &str, member: &str) -> Option { - // typing_extensions mirrors all the relevant types defined in typing. - if module != "typing" && module != "typing_extensions" { - return None; - }; - - match member { +pub fn as_pep_585_generic(call_path: &[&str]) -> Option { + match call_path { // Builtins - "Tuple" => Some(("", "tuple")), - "List" => Some(("", "list")), - "Dict" => Some(("", "dict")), - "Set" => Some(("", "set")), - "FrozenSet" => Some(("", "frozenset")), - "Type" => Some(("", "type")), + ["typing" | "typing_extensions", "Tuple"] => Some(("", "tuple")), + ["typing" | "typing_extensions", "List"] => Some(("", "list")), + ["typing" | "typing_extensions", "Dict"] => Some(("", "dict")), + ["typing" | "typing_extensions", "Set"] => Some(("", "set")), + ["typing" | "typing_extensions", "FrozenSet"] => Some(("", "frozenset")), + ["typing" | "typing_extensions", "Type"] => Some(("", "type")), // collections - "Deque" => Some(("collections", "deque")), - "DefaultDict" => Some(("collections", "defaultdict")), - "OrderedDict" => Some(("collections", "OrderedDict")), - "Counter" => Some(("collections", "Counter")), - "ChainMap" => Some(("collections", "ChainMap")), + ["typing" | "typing_extensions", "Deque"] => Some(("collections", "deque")), + ["typing" | "typing_extensions", "DefaultDict"] => Some(("collections", "defaultdict")), + ["typing" | "typing_extensions", "OrderedDict"] => Some(("collections", "OrderedDict")), + ["typing" | "typing_extensions", "Counter"] => Some(("collections", "Counter")), + ["typing" | "typing_extensions", "ChainMap"] => Some(("collections", "ChainMap")), // collections.abc - "Awaitable" => Some(("collections.abc", "Awaitable")), - "Coroutine" => Some(("collections.abc", "Coroutine")), - "AsyncIterable" => Some(("collections.abc", "AsyncIterable")), - "AsyncGenerator" => Some(("collections.abc", "AsyncGenerator")), - "Iterable" => Some(("collections.abc", "Iterable")), - "Iterator" => Some(("collections.abc", "Iterator")), - "Generator" => Some(("collections.abc", "Generator")), - "Reversible" => Some(("collections.abc", "Reversible")), - "Container" => Some(("collections.abc", "Container")), - "Collection" => Some(("collections.abc", "Collection")), - "Callable" => Some(("collections.abc", "Callable")), - "AbstractSet" => Some(("collections.abc", "Set")), - "MutableSet" => Some(("collections.abc", "MutableSet")), - "Mapping" => Some(("collections.abc", "Mapping")), - "MutableMapping" => Some(("collections.abc", "MutableMapping")), - "Sequence" => Some(("collections.abc", "Sequence")), - "MutableSequence" => Some(("collections.abc", "MutableSequence")), - "ByteString" => Some(("collections.abc", "ByteString")), - "MappingView" => Some(("collections.abc", "MappingView")), - "KeysView" => Some(("collections.abc", "KeysView")), - "ItemsView" => Some(("collections.abc", "ItemsView")), - "ValuesView" => Some(("collections.abc", "ValuesView")), + ["typing" | "typing_extensions", "Awaitable"] => Some(("collections.abc", "Awaitable")), + ["typing" | "typing_extensions", "Coroutine"] => Some(("collections.abc", "Coroutine")), + ["typing" | "typing_extensions", "AsyncIterable"] => { + Some(("collections.abc", "AsyncIterable")) + } + ["typing" | "typing_extensions", "AsyncGenerator"] => { + Some(("collections.abc", "AsyncGenerator")) + } + ["typing" | "typing_extensions", "Iterable"] => Some(("collections.abc", "Iterable")), + ["typing" | "typing_extensions", "Iterator"] => Some(("collections.abc", "Iterator")), + ["typing" | "typing_extensions", "Generator"] => Some(("collections.abc", "Generator")), + ["typing" | "typing_extensions", "Reversible"] => Some(("collections.abc", "Reversible")), + ["typing" | "typing_extensions", "Container"] => Some(("collections.abc", "Container")), + ["typing" | "typing_extensions", "Collection"] => Some(("collections.abc", "Collection")), + ["typing" | "typing_extensions", "Callable"] => Some(("collections.abc", "Callable")), + ["typing" | "typing_extensions", "AbstractSet"] => Some(("collections.abc", "Set")), + ["typing" | "typing_extensions", "MutableSet"] => Some(("collections.abc", "MutableSet")), + ["typing" | "typing_extensions", "Mapping"] => Some(("collections.abc", "Mapping")), + ["typing" | "typing_extensions", "MutableMapping"] => { + Some(("collections.abc", "MutableMapping")) + } + ["typing" | "typing_extensions", "Sequence"] => Some(("collections.abc", "Sequence")), + ["typing" | "typing_extensions", "MutableSequence"] => { + Some(("collections.abc", "MutableSequence")) + } + ["typing" | "typing_extensions", "ByteString"] => Some(("collections.abc", "ByteString")), + ["typing" | "typing_extensions", "MappingView"] => Some(("collections.abc", "MappingView")), + ["typing" | "typing_extensions", "KeysView"] => Some(("collections.abc", "KeysView")), + ["typing" | "typing_extensions", "ItemsView"] => Some(("collections.abc", "ItemsView")), + ["typing" | "typing_extensions", "ValuesView"] => Some(("collections.abc", "ValuesView")), // contextlib - "ContextManager" => Some(("contextlib", "AbstractContextManager")), - "AsyncContextManager" => Some(("contextlib", "AbstractAsyncContextManager")), + ["typing" | "typing_extensions", "ContextManager"] => { + Some(("contextlib", "AbstractContextManager")) + } + ["typing" | "typing_extensions", "AsyncContextManager"] => { + Some(("contextlib", "AbstractAsyncContextManager")) + } // re - "Pattern" => Some(("re", "Pattern")), - "Match" => Some(("re", "Match")), + ["typing" | "typing_extensions", "Pattern"] => Some(("re", "Pattern")), + ["typing" | "typing_extensions", "Match"] => Some(("re", "Match")), + ["typing" | "typing_extensions", "re", "Pattern"] => Some(("re", "Pattern")), + ["typing" | "typing_extensions", "re", "Match"] => Some(("re", "Match")), _ => None, } @@ -442,8 +451,39 @@ pub fn has_pep_585_generic(module: &str, member: &str) -> bool { // the last element in each pattern, and de-duplicating the values. matches!( (module, member), - ("", "dict" | "frozenset" | "list" | "set" | "tuple" | "type") - | ("collections", "deque" | "defaultdict") + ("", "tuple" | "list" | "dict" | "set" | "frozenset" | "type") + | ( + "collections", + "deque" | "defaultdict" | "OrderedDict" | "Counter" | "ChainMap" + ) + | ( + "collections.abc", + "Awaitable" + | "Coroutine" + | "Iterable" + | "Iterator" + | "Generator" + | "Reversible" + | "Container" + | "Collection" + | "Callable" + | "Set" + | "MutableSet" + | "Mapping" + | "MutableMapping" + | "Sequence" + | "MutableSequence" + | "ByteString" + | "MappingView" + | "KeysView" + | "ItemsView" + | "ValuesView" + ) + | ( + "contextlib", + "AbstractContextManager" | "AbstractAsyncContextManager" + ) + | ("re", "Pattern" | "Match") ) }