From 0e0e7382d863373c835d30fb639a1926f0239233 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Thu, 9 Nov 2023 09:32:06 -0500 Subject: [PATCH] Revert extensions change --- ...__flake8_pyi__tests__PYI050_PYI050.py.snap | 9 --- ..._flake8_pyi__tests__PYI050_PYI050.pyi.snap | 10 ---- crates/ruff_python_semantic/src/model.rs | 13 +++- crates/ruff_python_stdlib/src/typing.rs | 60 +++++++++++++++++++ 4 files changed, 71 insertions(+), 21 deletions(-) diff --git a/crates/ruff_linter/src/rules/flake8_pyi/snapshots/ruff_linter__rules__flake8_pyi__tests__PYI050_PYI050.py.snap b/crates/ruff_linter/src/rules/flake8_pyi/snapshots/ruff_linter__rules__flake8_pyi__tests__PYI050_PYI050.py.snap index 1f70291a11d98..11b5d19b5ebd7 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/snapshots/ruff_linter__rules__flake8_pyi__tests__PYI050_PYI050.py.snap +++ b/crates/ruff_linter/src/rules/flake8_pyi/snapshots/ruff_linter__rules__flake8_pyi__tests__PYI050_PYI050.py.snap @@ -8,15 +8,6 @@ PYI050.py:13:24: PYI050 Prefer `typing.Never` over `NoReturn` for argument annot 14 | ... | -PYI050.py:18:10: PYI050 Prefer `typing.Never` over `NoReturn` for argument annotations - | -17 | def foo_no_return_typing_extensions( -18 | arg: typing_extensions.NoReturn, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI050 -19 | ): -20 | ... - | - PYI050.py:23:44: PYI050 Prefer `typing.Never` over `NoReturn` for argument annotations | 23 | def foo_no_return_kwarg(arg: int, *, arg2: NoReturn): diff --git a/crates/ruff_linter/src/rules/flake8_pyi/snapshots/ruff_linter__rules__flake8_pyi__tests__PYI050_PYI050.pyi.snap b/crates/ruff_linter/src/rules/flake8_pyi/snapshots/ruff_linter__rules__flake8_pyi__tests__PYI050_PYI050.pyi.snap index ee4be9d9f38bb..a0cb503548fca 100644 --- a/crates/ruff_linter/src/rules/flake8_pyi/snapshots/ruff_linter__rules__flake8_pyi__tests__PYI050_PYI050.pyi.snap +++ b/crates/ruff_linter/src/rules/flake8_pyi/snapshots/ruff_linter__rules__flake8_pyi__tests__PYI050_PYI050.pyi.snap @@ -11,16 +11,6 @@ PYI050.pyi:6:24: PYI050 Prefer `typing.Never` over `NoReturn` for argument annot 8 | arg: typing_extensions.NoReturn, | -PYI050.pyi:8:10: PYI050 Prefer `typing.Never` over `NoReturn` for argument annotations - | - 6 | def foo_no_return(arg: NoReturn): ... # Error: PYI050 - 7 | def foo_no_return_typing_extensions( - 8 | arg: typing_extensions.NoReturn, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI050 - 9 | ): ... # Error: PYI050 -10 | def foo_no_return_kwarg(arg: int, *, arg2: NoReturn): ... # Error: PYI050 - | - PYI050.pyi:10:44: PYI050 Prefer `typing.Never` over `NoReturn` for argument annotations | 8 | arg: typing_extensions.NoReturn, diff --git a/crates/ruff_python_semantic/src/model.rs b/crates/ruff_python_semantic/src/model.rs index 332cda194eb45..42617ddaf7396 100644 --- a/crates/ruff_python_semantic/src/model.rs +++ b/crates/ruff_python_semantic/src/model.rs @@ -8,6 +8,7 @@ use ruff_python_ast::call_path::{collect_call_path, from_unqualified_name, CallP use ruff_python_ast::helpers::from_relative_import; use ruff_python_ast::{self as ast, Expr, Operator, Stmt}; use ruff_python_stdlib::path::is_python_stub_file; +use ruff_python_stdlib::typing::is_typing_extension; use ruff_text_size::{Ranged, TextRange, TextSize}; use crate::binding::{ @@ -174,8 +175,16 @@ impl<'a> SemanticModel<'a> { /// Return `true` if the call path is a reference to `typing.${target}`. pub fn match_typing_call_path(&self, call_path: &CallPath, target: &str) -> bool { - if let ["typing" | "_typeshed" | "typing_extensions", name] = call_path.as_slice() { - if *name == target { + if call_path.as_slice() == ["typing", target] { + return true; + } + + if call_path.as_slice() == ["_typeshed", target] { + return true; + } + + if is_typing_extension(target) { + if call_path.as_slice() == ["typing_extensions", target] { return true; } } diff --git a/crates/ruff_python_stdlib/src/typing.rs b/crates/ruff_python_stdlib/src/typing.rs index 45b472ce707d6..d210964efbebc 100644 --- a/crates/ruff_python_stdlib/src/typing.rs +++ b/crates/ruff_python_stdlib/src/typing.rs @@ -1,3 +1,63 @@ +/// Returns `true` if a name is a member of Python's `typing_extensions` module. +/// +/// See: +pub fn is_typing_extension(member: &str) -> bool { + matches!( + member, + "Annotated" + | "Any" + | "AsyncContextManager" + | "AsyncGenerator" + | "AsyncIterable" + | "AsyncIterator" + | "Awaitable" + | "ChainMap" + | "ClassVar" + | "Concatenate" + | "ContextManager" + | "Coroutine" + | "Counter" + | "DefaultDict" + | "Deque" + | "Final" + | "Literal" + | "LiteralString" + | "NamedTuple" + | "Never" + | "NewType" + | "NotRequired" + | "OrderedDict" + | "ParamSpec" + | "ParamSpecArgs" + | "ParamSpecKwargs" + | "Protocol" + | "Required" + | "Self" + | "TYPE_CHECKING" + | "Text" + | "Type" + | "TypeAlias" + | "TypeGuard" + | "TypeVar" + | "TypeVarTuple" + | "TypedDict" + | "Unpack" + | "assert_never" + | "assert_type" + | "clear_overloads" + | "final" + | "get_type_hints" + | "get_args" + | "get_origin" + | "get_overloads" + | "is_typeddict" + | "overload" + | "override" + | "reveal_type" + | "runtime_checkable" + ) +} + /// Returns `true` if a call path is a generic from the Python standard library (e.g. `list`, which /// can be used as `list[int]`). ///