Skip to content

Inconsistent behaviour of keys-like types from inspect.signature(...).parameters.keys() method and collections.OrderedDict().keys() #5808

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
bzoracler opened this issue Jul 25, 2021 · 2 comments · Fixed by #6013

Comments

@bzoracler
Copy link
Contributor

Bug Report

Possibly related to #3473.

  1. mypy indicates that the type of inspect.signature(some_method).parameters.keys() is typing.AbstractSet[_KT], while the type of collections.OrderedDict().keys() is collections._OrderedDictKeysView[typing.Any]. However, their runtime types match exactly.
  2. As a result of (1), inspect.signature(some_method).parameters.keys() doesn't like being hinted with typing.KeysView.

Actual behaviour: to reproduce

import typing
from inspect import signature
from collections import OrderedDict

# OK
dictKeys: typing.KeysView = {}.keys()
# OK
dictValues: typing.ValuesView = {}.values()
# mypy: Incompatible types in assignment (expression has type "AbstractSet[str]", variable has type "KeysView[Any]")
mappingproxyKeys: typing.KeysView = signature(object.__init__).parameters.keys()
# OK
mappingProxyValues: typing.ValuesView = signature(object.__init__).parameters.values()
# OK
orderedDictKeys = OrderedDict({1: 3}).keys()

# mypy: Revealed type is "collections._OrderedDictKeysView[Any]"
reveal_type(orderedDictKeys)

# runtime: No `AssertionError`; types match exactly
assert type(orderedDictKeys) is type(mappingproxyKeys)

Expected Behavior

# No `mypy` errors here expected
mappingproxyKeys: typing.KeysView = signature(object.__init__).parameters.keys()

Your Environment

  • Mypy version used: 0.910
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: 3.8
  • Operating system and version: Ubuntu 20.04 LTS
@JelleZijlstra JelleZijlstra transferred this issue from python/mypy Jul 25, 2021
@JelleZijlstra
Copy link
Member

This is presumably because inspect.Signature.parameters is typed as Mapping: https://github.com/python/typeshed/blob/master/stdlib/inspect.pyi#L126.

Perhaps it should be changed to dict.

@posita
Copy link
Contributor

posita commented Aug 14, 2021

This is presumably because inspect.Signature.parameters is typed as Mapping: https://github.com/python/typeshed/blob/master/stdlib/inspect.pyi#L126.

Perhaps it should be changed to dict.

Pardon my ignorance, but why should the return types of Dict (and other Mappings) not be changed (akin to #3473)? Alternatively, why have ItemsView or KeysView at all if "implementors" of Mapping aren't going to use them? I've probably missed something important, but ItemsView and KeysView seem like the more permissive of the two. Why not converge on those everywhere?

I guess another way to ask all those questions is, would your suggestion address this?

# test_case.py
from typing import AbstractSet, Dict, ItemsView, Mapping, Tuple, TypedDict

class OneTwo(TypedDict):
    one: int
    two: int

ot: OneTwo = {"one": 1, "two": 2}
d: Dict[str, object] = dict(ot)

ot_map: Mapping[str, object] = ot  # No error. A lie of omission?
d_map: Mapping[str, object] = d  # Another?

ot_items: AbstractSet[Tuple[str, object]] = ot.items()  # This works
d_items: AbstractSet[Tuple[str, object]] = d.items()  # So does this
ot_items2: ItemsView[str, object] = ot.items()  # And this
d_items2: ItemsView[str, object] = d.items()  # This too
ot_items = ot_map.items()  # All good
d_items = d_map.items()  # So is this

# These both generate errors: Incompatible types in assignment (expression has type
# "AbstractSet[Tuple[str, object]]", variable has type "ItemsView[str, object]"
ot_items2 = ot_map.items()
d_items2 = d_map.items()

This is probably a stupid question, but why shouldn't an ItemView[str, object] be assignable to something of type AbstractSet[Tuple[str, object]] if AbstractSet[Tuple[str, object]] is narrower?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants