From 4ef315edfaf48a9818003034483cb5af0fafabca Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Mon, 9 Dec 2024 19:53:38 -0800 Subject: [PATCH 1/3] test suite characterizing dict.get() --- .../@tests/test_cases/builtins/check_dict.py | 88 ++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/stdlib/@tests/test_cases/builtins/check_dict.py b/stdlib/@tests/test_cases/builtins/check_dict.py index 96c60e779038..0106c0223c3a 100644 --- a/stdlib/@tests/test_cases/builtins/check_dict.py +++ b/stdlib/@tests/test_cases/builtins/check_dict.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Dict, Generic, Iterable, TypeVar +from typing import Any, Dict, Generic, Iterable, TypeVar, Union from typing_extensions import assert_type # These do follow `__init__` overloads order: @@ -57,3 +57,89 @@ def test_iterable_tuple_overload(x: Iterable[tuple[int, str]]) -> dict[int, str] dict(["foo", "bar", "baz"]) # type: ignore dict([b"foo", b"bar", b"baz"]) # type: ignore + +# Exploring corner cases of dict.get() +d_any: dict[str, Any] = {} +d_str: dict[str, str] = {} +any_value: Any = None +str_value = "value" +int_value = 1 + +assert_type(d_any["key"], Any) +assert_type(d_any.get("key"), Union[Any, None]) +assert_type(d_any.get("key", None), Any) +assert_type(d_any.get("key", any_value), Any) +assert_type(d_any.get("key", str_value), Any) +assert_type(d_any.get("key", int_value), Any) + +assert_type(d_str["key"], str) +assert_type(d_str.get("key"), Union[str, None]) +assert_type(d_str.get("key", None), Union[str, None]) +assert_type(d_str.get("key", any_value), Any) +assert_type(d_str.get("key", str_value), str) +assert_type(d_str.get("key", int_value), Union[str, int]) + +# Now with context! +result: str +result = d_any["key"] +result = d_any.get("key") # type: ignore[assignment] +result = d_any.get("key", None) +result = d_any.get("key", any_value) +result = d_any.get("key", str_value) +result = d_any.get("key", int_value) + +result = d_str["key"] +result = d_str.get("key") # type: ignore[assignment] +result = d_str.get("key", None) # type: ignore[arg-type] +result = d_str.get("key", any_value) +result = d_str.get("key", str_value) +result = d_str.get("key", int_value) # type: ignore[arg-type] + + +# Return values also make things weird +def test1() -> str: + return d_any["key"] # type: ignore[no-any-return] + + +def test2() -> str: + return d_any.get("key") # type: ignore[return-value] + + +def test3() -> str: + return d_any.get("key", None) # type: ignore[no-any-return] + + +def test4() -> str: + return d_any.get("key", any_value) # type: ignore[no-any-return] + + +def test5() -> str: + return d_any.get("key", str_value) # type: ignore[no-any-return] + + +def test6() -> str: + return d_any.get("key", int_value) # type: ignore[no-any-return] + + +def test7() -> str: + return d_str["key"] + + +def test8() -> str: + return d_str.get("key") # type: ignore[return-value] + + +def test9() -> str: + return d_str.get("key", None) # type: ignore[arg-type] + + +def test10() -> str: + return d_str.get("key", any_value) + + +def test11() -> str: + return d_str.get("key", str_value) + + +def test12() -> str: + return d_str.get("key", int_value) # type: ignore[arg-type] From 1a524820f29f0f1f5b6854d32f3c12757fe2a963 Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Mon, 9 Dec 2024 20:14:29 -0800 Subject: [PATCH 2/3] fixes for pyright --- .../@tests/test_cases/builtins/check_dict.py | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/stdlib/@tests/test_cases/builtins/check_dict.py b/stdlib/@tests/test_cases/builtins/check_dict.py index 0106c0223c3a..3e34a947af61 100644 --- a/stdlib/@tests/test_cases/builtins/check_dict.py +++ b/stdlib/@tests/test_cases/builtins/check_dict.py @@ -75,7 +75,8 @@ def test_iterable_tuple_overload(x: Iterable[tuple[int, str]]) -> dict[int, str] assert_type(d_str["key"], str) assert_type(d_str.get("key"), Union[str, None]) assert_type(d_str.get("key", None), Union[str, None]) -assert_type(d_str.get("key", any_value), Any) +# Pyright has str instead of Any here +assert_type(d_str.get("key", any_value), Any) # pyright: ignore[reportAssertTypeFailure] assert_type(d_str.get("key", str_value), str) assert_type(d_str.get("key", int_value), Union[str, int]) @@ -97,28 +98,31 @@ def test_iterable_tuple_overload(x: Iterable[tuple[int, str]]) -> dict[int, str] # Return values also make things weird -def test1() -> str: - return d_any["key"] # type: ignore[no-any-return] + +# Pyright doesn't have a version of no-any-return, +# and mypy doesn't have a type: ignore that pyright will ignore. +# def test1() -> str: +# return d_any["key"] # type: ignore[no-any-return] def test2() -> str: return d_any.get("key") # type: ignore[return-value] -def test3() -> str: - return d_any.get("key", None) # type: ignore[no-any-return] - - -def test4() -> str: - return d_any.get("key", any_value) # type: ignore[no-any-return] - - -def test5() -> str: - return d_any.get("key", str_value) # type: ignore[no-any-return] - - -def test6() -> str: - return d_any.get("key", int_value) # type: ignore[no-any-return] +# def test3() -> str: +# return d_any.get("key", None) # type: ignore[no-any-return] +# +# +# def test4() -> str: +# return d_any.get("key", any_value) # type: ignore[no-any-return] +# +# +# def test5() -> str: +# return d_any.get("key", str_value) # type: ignore[no-any-return] +# +# +# def test6() -> str: +# return d_any.get("key", int_value) # type: ignore[no-any-return] def test7() -> str: From 4879acb52cbc8d867823996ddb848794ae515dc2 Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Mon, 9 Dec 2024 20:17:33 -0800 Subject: [PATCH 3/3] try again --- stdlib/@tests/test_cases/builtins/check_dict.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stdlib/@tests/test_cases/builtins/check_dict.py b/stdlib/@tests/test_cases/builtins/check_dict.py index 3e34a947af61..dd4569eccbe5 100644 --- a/stdlib/@tests/test_cases/builtins/check_dict.py +++ b/stdlib/@tests/test_cases/builtins/check_dict.py @@ -102,7 +102,7 @@ def test_iterable_tuple_overload(x: Iterable[tuple[int, str]]) -> dict[int, str] # Pyright doesn't have a version of no-any-return, # and mypy doesn't have a type: ignore that pyright will ignore. # def test1() -> str: -# return d_any["key"] # type: ignore[no-any-return] +# return d_any["key"] # mypy: ignore[no-any-return] def test2() -> str: @@ -110,19 +110,19 @@ def test2() -> str: # def test3() -> str: -# return d_any.get("key", None) # type: ignore[no-any-return] +# return d_any.get("key", None) # mypy: ignore[no-any-return] # # # def test4() -> str: -# return d_any.get("key", any_value) # type: ignore[no-any-return] +# return d_any.get("key", any_value) # mypy: ignore[no-any-return] # # # def test5() -> str: -# return d_any.get("key", str_value) # type: ignore[no-any-return] +# return d_any.get("key", str_value) # mypy: ignore[no-any-return] # # # def test6() -> str: -# return d_any.get("key", int_value) # type: ignore[no-any-return] +# return d_any.get("key", int_value) # mypy: ignore[no-any-return] def test7() -> str: