From cb2836ca2c50374f6f18786e1c9fe699d584c5eb Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 30 Aug 2016 15:41:45 -0700 Subject: [PATCH 1/3] Make Mapping covariant. Fixes #510. This requires a `# type: ignore` on `__getitem__` and `get` because mypy complains about covariant parameters. FWIW typing.py needs to be changed too. (It was covariant in the value but invariant in the key -- typeshed was invariant in both.) --- stdlib/2.7/typing.pyi | 22 ++++++++++++---------- stdlib/3/typing.pyi | 16 +++++++++------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/stdlib/2.7/typing.pyi b/stdlib/2.7/typing.pyi index 5e0906e0d113..53e33a213bd5 100644 --- a/stdlib/2.7/typing.pyi +++ b/stdlib/2.7/typing.pyi @@ -176,17 +176,19 @@ class ValuesView(MappingView, Iterable[_VT_co], Generic[_VT_co]): def __contains__(self, o: object) -> bool: ... def __iter__(self) -> Iterator[_VT_co]: ... -class Mapping(Sized, Iterable[_KT], Container[_KT], Generic[_KT, _VT]): - @abstractmethod - def __getitem__(self, k: _KT) -> _VT: ... +class Mapping(Sized, Iterable[_KT_co], Container[_KT_co], Generic[_KT_co, _VT_co]): + @abstractmethod # type: ignore + def __getitem__(self, k: _KT_co) -> _VT_co: # type: ignore + ... # Mixin methods - def get(self, k: _KT, default: _VT = ...) -> _VT: ... - def keys(self) -> list[_KT]: ... - def values(self) -> list[_VT]: ... - def items(self) -> list[Tuple[_KT, _VT]]: ... - def iterkeys(self) -> Iterator[_KT]: ... - def itervalues(self) -> Iterator[_VT]: ... - def iteritems(self) -> Iterator[Tuple[_KT, _VT]]: ... + def get(self, k: _KT_co, default: _VT_co = ...) -> _VT_co: # type: ignore + ... + def keys(self) -> list[_KT_co]: ... + def values(self) -> list[_VT_co]: ... + def items(self) -> list[Tuple[_KT_co, _VT_co]]: ... + def iterkeys(self) -> Iterator[_KT_co]: ... + def itervalues(self) -> Iterator[_VT_co]: ... + def iteritems(self) -> Iterator[Tuple[_KT_co, _VT_co]]: ... def __contains__(self, o: object) -> bool: ... class MutableMapping(Mapping[_KT, _VT], Generic[_KT, _VT]): diff --git a/stdlib/3/typing.pyi b/stdlib/3/typing.pyi index 438d2648b615..0e411bfd44e4 100644 --- a/stdlib/3/typing.pyi +++ b/stdlib/3/typing.pyi @@ -226,16 +226,18 @@ class ValuesView(MappingView, Iterable[_VT_co], Generic[_VT_co]): # TODO: ContextManager (only if contextlib.AbstractContextManager exists) -class Mapping(Iterable[_KT], Container[_KT], Sized, Generic[_KT, _VT]): +class Mapping(Iterable[_KT_co], Container[_KT_co], Sized, Generic[_KT_co, _VT_co]): # TODO: Value type should be covariant, but currently we can't give a good signature for # get if this is the case. - @abstractmethod - def __getitem__(self, k: _KT) -> _VT: ... + @abstractmethod # type: ignore + def __getitem__(self, k: _KT_co) -> _VT_co: # type: ignore + ... # Mixin methods - def get(self, k: _KT, default: _VT = ...) -> _VT: ... - def items(self) -> AbstractSet[Tuple[_KT, _VT]]: ... - def keys(self) -> AbstractSet[_KT]: ... - def values(self) -> ValuesView[_VT]: ... + def get(self, k: _KT_co, default: _VT_co = ...) -> _VT_co: # type: ignore + ... + def items(self) -> AbstractSet[Tuple[_KT_co, _VT_co]]: ... + def keys(self) -> AbstractSet[_KT_co]: ... + def values(self) -> ValuesView[_VT_co]: ... def __contains__(self, o: object) -> bool: ... class MutableMapping(Mapping[_KT, _VT], Generic[_KT, _VT]): From febb476d45c0c64a7aa71bbe065913065bf9447f Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Wed, 31 Aug 2016 11:08:24 -0700 Subject: [PATCH 2/3] Delete outdated comment. --- stdlib/3/typing.pyi | 2 -- 1 file changed, 2 deletions(-) diff --git a/stdlib/3/typing.pyi b/stdlib/3/typing.pyi index 0e411bfd44e4..a06020180298 100644 --- a/stdlib/3/typing.pyi +++ b/stdlib/3/typing.pyi @@ -227,8 +227,6 @@ class ValuesView(MappingView, Iterable[_VT_co], Generic[_VT_co]): # TODO: ContextManager (only if contextlib.AbstractContextManager exists) class Mapping(Iterable[_KT_co], Container[_KT_co], Sized, Generic[_KT_co, _VT_co]): - # TODO: Value type should be covariant, but currently we can't give a good signature for - # get if this is the case. @abstractmethod # type: ignore def __getitem__(self, k: _KT_co) -> _VT_co: # type: ignore ... From 199c983c42d00387e5731acead08d6bc2627cb6e Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Fri, 2 Sep 2016 16:23:52 -0700 Subject: [PATCH 3/3] Backpeddle a bit -- Mapping key type should not be covariant. --- stdlib/2.7/typing.pyi | 18 ++++++++++-------- stdlib/3/typing.pyi | 14 ++++++++------ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/stdlib/2.7/typing.pyi b/stdlib/2.7/typing.pyi index 53e33a213bd5..e8aa48a6f1ef 100644 --- a/stdlib/2.7/typing.pyi +++ b/stdlib/2.7/typing.pyi @@ -176,19 +176,21 @@ class ValuesView(MappingView, Iterable[_VT_co], Generic[_VT_co]): def __contains__(self, o: object) -> bool: ... def __iter__(self) -> Iterator[_VT_co]: ... -class Mapping(Sized, Iterable[_KT_co], Container[_KT_co], Generic[_KT_co, _VT_co]): - @abstractmethod # type: ignore - def __getitem__(self, k: _KT_co) -> _VT_co: # type: ignore +class Mapping(Sized, Iterable[_KT], Container[_KT], Generic[_KT, _VT_co]): + # TODO: We wish the key type could also be covariant, but that doesn't work, + # see discussion in https://github.com/python/typing/pull/273. + @abstractmethod + def __getitem__(self, k: _KT) -> _VT_co: ... # Mixin methods - def get(self, k: _KT_co, default: _VT_co = ...) -> _VT_co: # type: ignore + def get(self, k: _KT, default: _VT_co = ...) -> _VT_co: # type: ignore ... - def keys(self) -> list[_KT_co]: ... + def keys(self) -> list[_KT]: ... def values(self) -> list[_VT_co]: ... - def items(self) -> list[Tuple[_KT_co, _VT_co]]: ... - def iterkeys(self) -> Iterator[_KT_co]: ... + def items(self) -> list[Tuple[_KT, _VT_co]]: ... + def iterkeys(self) -> Iterator[_KT]: ... def itervalues(self) -> Iterator[_VT_co]: ... - def iteritems(self) -> Iterator[Tuple[_KT_co, _VT_co]]: ... + def iteritems(self) -> Iterator[Tuple[_KT, _VT_co]]: ... def __contains__(self, o: object) -> bool: ... class MutableMapping(Mapping[_KT, _VT], Generic[_KT, _VT]): diff --git a/stdlib/3/typing.pyi b/stdlib/3/typing.pyi index a06020180298..d5389962aa13 100644 --- a/stdlib/3/typing.pyi +++ b/stdlib/3/typing.pyi @@ -226,15 +226,17 @@ class ValuesView(MappingView, Iterable[_VT_co], Generic[_VT_co]): # TODO: ContextManager (only if contextlib.AbstractContextManager exists) -class Mapping(Iterable[_KT_co], Container[_KT_co], Sized, Generic[_KT_co, _VT_co]): - @abstractmethod # type: ignore - def __getitem__(self, k: _KT_co) -> _VT_co: # type: ignore +class Mapping(Iterable[_KT], Container[_KT], Sized, Generic[_KT, _VT_co]): + # TODO: We wish the key type could also be covariant, but that doesn't work, + # see discussion in https://github.com/python/typing/pull/273. + @abstractmethod + def __getitem__(self, k: _KT) -> _VT_co: ... # Mixin methods - def get(self, k: _KT_co, default: _VT_co = ...) -> _VT_co: # type: ignore + def get(self, k: _KT, default: _VT_co = ...) -> _VT_co: # type: ignore ... - def items(self) -> AbstractSet[Tuple[_KT_co, _VT_co]]: ... - def keys(self) -> AbstractSet[_KT_co]: ... + def items(self) -> AbstractSet[Tuple[_KT, _VT_co]]: ... + def keys(self) -> AbstractSet[_KT]: ... def values(self) -> ValuesView[_VT_co]: ... def __contains__(self, o: object) -> bool: ...