Skip to content

Issue with itemgetter, SupportsGetItem and min #14032

@Avasam

Description

@Avasam

Bug Report
Sorry for the vague title. I'm not sure whether this is a bug or if I'm doing something wrong. This came up in python/typeshed#9117 . Pyright reports no error with the usage of itemgetter here. And both type-checkers reveal the right type returned from min in this example.

To Reproduce

from _typeshed import SupportsDunderGT, SupportsDunderLT
from collections.abc import Callable
from typing import Any, Generic, Protocol, Tuple, TypeVar, Union
from typing_extensions import final

_T = TypeVar("_T")
_T_contra = TypeVar("_T_contra", contravariant=True)
_T_co = TypeVar("_T_co", covariant=True)
_VT_co = TypeVar("_VT_co", covariant=True)
_KT_contra = TypeVar("_KT_contra", contravariant=True)

# Simplified from typeshed
class SupportsGetItem(Protocol[_KT_contra, _VT_co]):
    def __contains__(self, __x: Any) -> bool: ...
    def __getitem__(self, __key: _KT_contra) -> _VT_co: ...

# Simplified from typeshed, with the generic typing change to __call__
@final
class itemgetter(Generic[_T_co]):
    def __new__(cls, item: _T_co) -> itemgetter[_T_co]: ...
    def __call__(self, obj: SupportsGetItem[_T_co, _T]) -> _T: ...

# This is the same as itemgetter.__call__
def standalone_call(obj: SupportsGetItem[int, _T]) -> _T: ...

reveal_type(itemgetter(1).__call__)

test_dict = min({"first": 1, "second": 2}, key=itemgetter(1))
test_items = min({"first": 1, "second": 2}.items(), key=itemgetter(1))  # mypy error
test_dict_standalone = min({"first": 1, "second": 2}, key=standalone_call)
test_items_standalone = min({"first": 1, "second": 2}.items(), key=standalone_call)  # mypy error

reveal_type(test_dict)
reveal_type(test_items)

expected_type_form_min_param_1: Callable[[Tuple[str, int]], Union[SupportsDunderLT[Any], SupportsDunderGT[Any]]]
revealed_type_itemgetter_call: Callable[[SupportsGetItem[Any, _T]], _T]  # pyright error

revealed_type_itemgetter_call = itemgetter(1)
expected_type_form_min_param_1 = itemgetter(1)  # mypy error

revealed_type_itemgetter_call = standalone_call
expected_type_form_min_param_1 = standalone_call  # mypy error

Expected Behavior

No error? Maybe?

Actual Behavior

(.venv) PS C:\Users\Avasam\Desktop> mypy .\operator_reveal_type.pyi
operator_reveal_type.pyi:26: note: Revealed type is "def [_T] (obj: operator_reveal_type.SupportsGetItem[Any, _T`3]) -> _T`3"
operator_reveal_type.pyi:29: error: Argument "key" to "min" has incompatible type "itemgetter[int]"; expected "Callable[[Tuple[str, int]], Union[SupportsDunderLT[Any], SupportsDunderGT[Any]]]"  
[arg-type]
operator_reveal_type.pyi:29: note: "itemgetter[int].__call__" has type "Callable[[Arg(SupportsGetItem[Any, _T], 'obj')], _T]"
operator_reveal_type.pyi:31: error: Argument "key" to "min" has incompatible type "Callable[[SupportsGetItem[Any, _T]], _T]"; expected "Callable[[Tuple[str, int]], Union[SupportsDunderLT[Any], SupportsDunderGT[Any]]]"  [arg-type]
operator_reveal_type.pyi:33: note: Revealed type is "builtins.str"
operator_reveal_type.pyi:34: note: Revealed type is "Tuple[builtins.str, builtins.int]"
operator_reveal_type.pyi:40: error: Incompatible types in assignment (expression has type "itemgetter[int]", variable has type "Callable[[Tuple[str, int]], Union[SupportsDunderLT[Any], SupportsDunderGT[Any]]]")  [assignment]
operator_reveal_type.pyi:40: note: "itemgetter[int].__call__" has type "Callable[[Arg(SupportsGetItem[Any, _T], 'obj')], _T]"
operator_reveal_type.pyi:43: error: Incompatible types in assignment (expression has type "Callable[[SupportsGetItem[Any, _T]], _T]", variable has type "Callable[[Tuple[str, int]], Union[SupportsDunderLT[Any], SupportsDunderGT[Any]]]")  [assignment]
Found 4 errors in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: 0.982 AND 0.990 (compiled: yes)
  • Mypy command-line flags: N/A
  • Mypy configuration options from mypy.ini (and other config files): N/A
  • Python version used: 3.9.13

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      pFad - Phonifier reborn

      Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy