Skip to content

Commit cffeff0

Browse files
authored
Update comments for operator.itemgetter.__call__ generic following mypy 1.11 fix (#13489)
1 parent 751525b commit cffeff0

File tree

4 files changed

+44
-4
lines changed

4 files changed

+44
-4
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from __future__ import annotations
2+
3+
from _typeshed import SupportsDunderGT, SupportsDunderLT, SupportsGetItem
4+
from collections.abc import Callable
5+
from operator import itemgetter
6+
from typing import Any, TypeVar
7+
from typing_extensions import assert_type
8+
9+
_T = TypeVar("_T")
10+
11+
12+
# This should be equivalent to itemgetter().__call__
13+
def standalone_call(obj: SupportsGetItem[Any, _T]) -> _T: ...
14+
15+
16+
# Expected type of itemgetter(1).__call__
17+
expected_type_itemgetter_call: Callable[[SupportsGetItem[int, _T]], _T] # pyright: ignore[reportGeneralTypeIssues]
18+
19+
# Expecting itemgetter(1) to be assignable to this
20+
# based on the example below: min({"first": 1, "second": 2}.items(), key=itemgetter(1))
21+
# That example and assigning to this variable are what failed in https://github.com/python/mypy/issues/14032
22+
expected_assignable_to: Callable[[tuple[str, int]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]
23+
24+
25+
# Regression tests for https://github.com/python/mypy/issues/14032
26+
# assert_type(itemgetter("first")({"first": 1, "second": 2}), int) # See comment on itemgetter.__call__
27+
assert_type(min({"first": 1, "second": 2}, key=itemgetter(1)), str)
28+
assert_type(min({"first": 1, "second": 2}.items(), key=itemgetter(1)), tuple[str, int])
29+
assert_type(standalone_call({"first": 1, "second": 2}), int)
30+
assert_type(min({"first": 1, "second": 2}, key=standalone_call), str)
31+
assert_type(min({"first": 1, "second": 2}.items(), key=standalone_call), tuple[str, int])
32+
33+
expected_itemgetter_call_type = itemgetter(1).__call__
34+
expected_itemgetter_call_type = itemgetter(1)
35+
expected_assignable_to = itemgetter(1)
36+
37+
expected_itemgetter_call_type = standalone_call
38+
expected_assignable_to = standalone_call

stdlib/operator.pyi

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,10 @@ class itemgetter(Generic[_T_co]):
205205
# "tuple[int, int]" is incompatible with protocol "SupportsIndex"
206206
# preventing [_T_co, ...] instead of [Any, ...]
207207
#
208-
# A suspected mypy issue prevents using [..., _T] instead of [..., Any] here.
209-
# https://github.com/python/mypy/issues/14032
208+
# If we can't infer a literal key from __new__ (ie: `itemgetter[Literal[0]]` for `itemgetter(0)`),
209+
# then we can't annotate __call__'s return type or it'll break on tuples
210+
#
211+
# These issues are best demonstrated by the `itertools.check_itertools_recipes.unique_justseen` test.
210212
def __call__(self, obj: SupportsGetItem[Any, Any]) -> Any: ...
211213

212214
@final

stubs/six/@tests/stubtest_allowlist.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ six.get_method_self
1414
six.viewitems
1515
six.viewkeys
1616
six.viewvalues
17-
# Should be `operator.itemgetter[int]`. But a bug in mypy prevents using TypeVar in itemgetter__call__
17+
# Should be `byte2int: operator.itemgetter[int]`. But `itemgetter.__call__` returns `Any`
1818
six.byte2int
1919

2020
# Utils

stubs/six/six/__init__.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ unichr = chr
6161

6262
def int2byte(i: int) -> bytes: ...
6363

64-
# Should be `byte2int: operator.itemgetter[int]`. But a bug in mypy prevents using TypeVar in itemgetter.__call__
64+
# Should be `byte2int: operator.itemgetter[int]`. But `itemgetter.__call__` returns `Any`
6565
def byte2int(obj: SupportsGetItem[int, _T]) -> _T: ...
6666

6767
indexbytes = operator.getitem

0 commit comments

Comments
 (0)