diff --git a/stdlib/@tests/test_cases/check_SupportsGetItem.py b/stdlib/@tests/test_cases/check_SupportsGetItem.py new file mode 100644 index 000000000000..5319665a6be3 --- /dev/null +++ b/stdlib/@tests/test_cases/check_SupportsGetItem.py @@ -0,0 +1,37 @@ +from __future__ import annotations + +from _typeshed import SupportsDunderGT, SupportsDunderLT, SupportsGetItem +from collections.abc import Callable +from operator import itemgetter +from typing import Any, TypeVar, assert_type + +_T = TypeVar("_T") + + +# This should be equivalent to itemgetter().__call__ +def standalone_call(obj: SupportsGetItem[Any, _T]) -> _T: ... + + +# Expected type of itemgetter(1).__call__ +expected_type_itemgetter_call: Callable[[SupportsGetItem[int, _T]], _T] # pyright: ignore[reportGeneralTypeIssues] + +# Expecting itemgetter(1) to be assignable to this +# based on the example below: min({"first": 1, "second": 2}.items(), key=itemgetter(1)) +# That example and assigning to this variable are what failed in https://github.com/python/mypy/issues/14032 +expected_assignable_to: Callable[[tuple[str, int]], SupportsDunderLT[Any] | SupportsDunderGT[Any]] + + +# Regression tests for https://github.com/python/mypy/issues/14032 +assert_type(itemgetter("")({"first": 1, "second": 2}), int) +assert_type(min({"first": 1, "second": 2}, key=itemgetter(1)), str) +assert_type(min({"first": 1, "second": 2}.items(), key=itemgetter(1)), tuple[str, int]) +assert_type(standalone_call({"first": 1, "second": 2}), int) +assert_type(min({"first": 1, "second": 2}, key=standalone_call), str) +assert_type(min({"first": 1, "second": 2}.items(), key=standalone_call), tuple[str, int]) + +expected_itemgetter_call_type = itemgetter(1).__call__ +expected_itemgetter_call_type = itemgetter(1) +expected_assignable_to = itemgetter(1) + +expected_itemgetter_call_type = standalone_call +expected_assignable_to = standalone_call diff --git a/stdlib/operator.pyi b/stdlib/operator.pyi index bc2b5e026617..33268b3b504d 100644 --- a/stdlib/operator.pyi +++ b/stdlib/operator.pyi @@ -203,11 +203,8 @@ class itemgetter(Generic[_T_co]): # __key: _KT_contra in SupportsGetItem seems to be causing variance issues, ie: # TypeVar "_KT_contra@SupportsGetItem" is contravariant # "tuple[int, int]" is incompatible with protocol "SupportsIndex" - # preventing [_T_co, ...] instead of [Any, ...] - # - # A suspected mypy issue prevents using [..., _T] instead of [..., Any] here. - # https://github.com/python/mypy/issues/14032 - def __call__(self, obj: SupportsGetItem[Any, Any]) -> Any: ... + # preventing [_T_co, _T] instead of [Any, _T] + def __call__(self, obj: SupportsGetItem[Any, _T]) -> _T: ... @final class methodcaller: diff --git a/stubs/six/@tests/stubtest_allowlist.txt b/stubs/six/@tests/stubtest_allowlist.txt index b00e2bf52be9..5c638491dd63 100644 --- a/stubs/six/@tests/stubtest_allowlist.txt +++ b/stubs/six/@tests/stubtest_allowlist.txt @@ -14,8 +14,6 @@ six.get_method_self six.viewitems six.viewkeys six.viewvalues -# Should be `operator.itemgetter[int]`. But a bug in mypy prevents using TypeVar in itemgetter__call__ -six.byte2int # Utils six.Module_six_moves_urllib diff --git a/stubs/six/six/__init__.pyi b/stubs/six/six/__init__.pyi index e5a8fdbaa3c6..b2a140f403b4 100644 --- a/stubs/six/six/__init__.pyi +++ b/stubs/six/six/__init__.pyi @@ -2,7 +2,7 @@ import builtins import operator import types import unittest -from _typeshed import IdentityFunction, SupportsGetItem, Unused +from _typeshed import IdentityFunction, Unused from builtins import next as next from collections.abc import Callable, ItemsView, Iterable, Iterator as _Iterator, KeysView, Mapping, ValuesView from functools import wraps as wraps @@ -61,9 +61,7 @@ unichr = chr def int2byte(i: int) -> bytes: ... -# Should be `byte2int: operator.itemgetter[int]`. But a bug in mypy prevents using TypeVar in itemgetter.__call__ -def byte2int(obj: SupportsGetItem[int, _T]) -> _T: ... - +byte2int: operator.itemgetter[int] indexbytes = operator.getitem iterbytes = iter