From df397a786a7416851c5fad20988a5777046a2d98 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 8 Jan 2024 22:09:32 -0500 Subject: [PATCH] Allow Hashable = None in type annotations --- .../ruff_linter/resources/test/fixtures/ruff/RUF013_0.py | 8 +++++++- crates/ruff_linter/src/rules/ruff/typing.rs | 9 +++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/crates/ruff_linter/resources/test/fixtures/ruff/RUF013_0.py b/crates/ruff_linter/resources/test/fixtures/ruff/RUF013_0.py index e4807c9f5ac611..8a3a7b0b434090 100644 --- a/crates/ruff_linter/resources/test/fixtures/ruff/RUF013_0.py +++ b/crates/ruff_linter/resources/test/fixtures/ruff/RUF013_0.py @@ -1,5 +1,5 @@ import typing -from typing import Annotated, Any, Literal, Optional, Tuple, Union +from typing import Annotated, Any, Literal, Optional, Tuple, Union, Hashable def f(arg: int): @@ -257,3 +257,9 @@ def f(arg: "Text" = None): def f(arg: MaybeInt = None): pass + + +# Hashable + +def f(arg: Hashable = None): # OK + pass diff --git a/crates/ruff_linter/src/rules/ruff/typing.rs b/crates/ruff_linter/src/rules/ruff/typing.rs index 76f825da8f18a0..1c176ca7e4d620 100644 --- a/crates/ruff_linter/src/rules/ruff/typing.rs +++ b/crates/ruff_linter/src/rules/ruff/typing.rs @@ -57,6 +57,9 @@ enum TypingTarget<'a> { /// A `typing.Annotated` type e.g., `Annotated[int, ...]`. Annotated(&'a Expr), + /// The `typing.Hashable` type. + Hashable, + /// Special type used to represent an unknown type (and not a typing target) /// which could be a type alias. Unknown, @@ -121,6 +124,10 @@ impl<'a> TypingTarget<'a> { Some(TypingTarget::Any) } else if matches!(call_path.as_slice(), ["" | "builtins", "object"]) { Some(TypingTarget::Object) + } else if semantic.match_typing_call_path(&call_path, "Hashable") + || matches!(call_path.as_slice(), ["collections", "abc", "Hashable"]) + { + Some(TypingTarget::Hashable) } else if !is_known_type(&call_path, minor_version) { // If it's not a known type, we assume it's `Any`. Some(TypingTarget::Unknown) @@ -142,6 +149,7 @@ impl<'a> TypingTarget<'a> { match self { TypingTarget::None | TypingTarget::Optional(_) + | TypingTarget::Hashable | TypingTarget::Any | TypingTarget::Object | TypingTarget::Unknown => true, @@ -191,6 +199,7 @@ impl<'a> TypingTarget<'a> { // `Literal` cannot contain `Any` as it's a dynamic value. TypingTarget::Literal(_) | TypingTarget::None + | TypingTarget::Hashable | TypingTarget::Object | TypingTarget::Known | TypingTarget::Unknown => false,