From 0e3750e14c7a016124bf0d78aec066af43c1342f Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Fri, 30 Nov 2018 09:10:59 -0800 Subject: [PATCH 1/4] Stop inheriting Sized in collection ABCs Instead define abstract __len__ in affected classes. Fixes #2655 without breaking https://github.com/rominf/ordered-set-stubs/issues/1 --- stdlib/2/typing.pyi | 21 +++++++++++++++++---- stdlib/3/typing.pyi | 24 ++++++++++++++++++++---- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/stdlib/2/typing.pyi b/stdlib/2/typing.pyi index 81daad7745ea..1c738abe5ea2 100644 --- a/stdlib/2/typing.pyi +++ b/stdlib/2/typing.pyi @@ -144,7 +144,7 @@ class Container(Protocol[_T_co]): @abstractmethod def __contains__(self, x: object) -> bool: ... -class Sequence(Iterable[_T_co], Container[_T_co], Sized, Reversible[_T_co], Generic[_T_co]): +class Sequence(Iterable[_T_co], Container[_T_co], Reversible[_T_co], Generic[_T_co]): @overload @abstractmethod def __getitem__(self, i: int) -> _T_co: ... @@ -157,6 +157,9 @@ class Sequence(Iterable[_T_co], Container[_T_co], Sized, Reversible[_T_co], Gene def __contains__(self, x: object) -> bool: ... def __iter__(self) -> Iterator[_T_co]: ... def __reversed__(self) -> Iterator[_T_co]: ... + # Implement Sized (but don't have it as a base class). + @abstractmethod + def __len__(self) -> int: ... class MutableSequence(Sequence[_T], Generic[_T]): @abstractmethod @@ -187,7 +190,7 @@ class MutableSequence(Sequence[_T], Generic[_T]): def remove(self, object: _T) -> None: ... def __iadd__(self, x: Iterable[_T]) -> MutableSequence[_T]: ... -class AbstractSet(Sized, Iterable[_T_co], Container[_T_co], Generic[_T_co]): +class AbstractSet(Iterable[_T_co], Container[_T_co], Generic[_T_co]): @abstractmethod def __contains__(self, x: object) -> bool: ... # Mixin methods @@ -201,6 +204,10 @@ class AbstractSet(Sized, Iterable[_T_co], Container[_T_co], Generic[_T_co]): def __xor__(self, s: AbstractSet[_T]) -> AbstractSet[Union[_T_co, _T]]: ... # TODO: argument can be any container? def isdisjoint(self, s: AbstractSet[Any]) -> bool: ... + # Implement Sized (but don't have it as a base class). + @abstractmethod + def __len__(self) -> int: ... + class MutableSet(AbstractSet[_T], Generic[_T]): @abstractmethod @@ -216,7 +223,10 @@ class MutableSet(AbstractSet[_T], Generic[_T]): def __ixor__(self, s: AbstractSet[_S]) -> MutableSet[Union[_T, _S]]: ... def __isub__(self, s: AbstractSet[Any]) -> MutableSet[_T]: ... -class MappingView(Sized): +class MappingView: + def __len__(self) -> int: ... + # Implement Sized (but don't have it as a base class). + @abstractmethod def __len__(self) -> int: ... class ItemsView(AbstractSet[Tuple[_KT_co, _VT_co]], MappingView, Generic[_KT_co, _VT_co]): @@ -238,7 +248,7 @@ class ContextManager(Protocol[_T_co]): exc_value: Optional[BaseException], traceback: Optional[TracebackType]) -> Optional[bool]: ... -class Mapping(Iterable[_KT], Container[_KT], Sized, Generic[_KT, _VT_co]): +class Mapping(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 @@ -256,6 +266,9 @@ class Mapping(Iterable[_KT], Container[_KT], Sized, Generic[_KT, _VT_co]): def itervalues(self) -> Iterator[_VT_co]: ... def iteritems(self) -> Iterator[Tuple[_KT, _VT_co]]: ... def __contains__(self, o: object) -> bool: ... + # Implement Sized (but don't have it as a base class). + @abstractmethod + def __len__(self) -> int: ... class MutableMapping(Mapping[_KT, _VT], Generic[_KT, _VT]): @abstractmethod diff --git a/stdlib/3/typing.pyi b/stdlib/3/typing.pyi index dfc64c67e48c..ed7724be7d05 100644 --- a/stdlib/3/typing.pyi +++ b/stdlib/3/typing.pyi @@ -235,13 +235,20 @@ class Container(Protocol[_T_co]): if sys.version_info >= (3, 6): @runtime - class Collection(Sized, Iterable[_T_co], Container[_T_co], Protocol[_T_co]): ... + class Collection(Iterable[_T_co], Container[_T_co], Protocol[_T_co]): + # Implement Sized (but don't have it as a base class). + @abstractmethod + def __len__(self) -> int: ... + _Collection = Collection else: @runtime - class _Collection(Sized, Iterable[_T_co], Container[_T_co], Protocol[_T_co]): ... + class _Collection(Iterable[_T_co], Container[_T_co], Protocol[_T_co]): + # Implement Sized (but don't have it as a base class). + @abstractmethod + def __len__(self) -> int: ... -class Sequence(_Collection[_T_co], Reversible[_T_co], Generic[_T_co]): +class Sequence(Iterable[_T_co], Container[_T_co], Reversible[_T_co], Generic[_T_co]): @overload @abstractmethod def __getitem__(self, i: int) -> _T_co: ... @@ -257,6 +264,9 @@ class Sequence(_Collection[_T_co], Reversible[_T_co], Generic[_T_co]): def __contains__(self, x: object) -> bool: ... def __iter__(self) -> Iterator[_T_co]: ... def __reversed__(self) -> Iterator[_T_co]: ... + # Implement Sized (but don't have it as a base class). + @abstractmethod + def __len__(self) -> int: ... class MutableSequence(Sequence[_T], Generic[_T]): @abstractmethod @@ -302,6 +312,9 @@ class AbstractSet(_Collection[_T_co], Generic[_T_co]): def __xor__(self, s: AbstractSet[_T]) -> AbstractSet[Union[_T_co, _T]]: ... # TODO: Argument can be a more general ABC? def isdisjoint(self, s: AbstractSet[Any]) -> bool: ... + # Implement Sized (but don't have it as a base class). + @abstractmethod + def __len__(self) -> int: ... class MutableSet(AbstractSet[_T], Generic[_T]): @abstractmethod @@ -317,7 +330,10 @@ class MutableSet(AbstractSet[_T], Generic[_T]): def __ixor__(self, s: AbstractSet[_S]) -> MutableSet[Union[_T, _S]]: ... def __isub__(self, s: AbstractSet[Any]) -> MutableSet[_T]: ... -class MappingView(Sized): +class MappingView: + def __len__(self) -> int: ... + # Implement Sized (but don't have it as a base class). + @abstractmethod def __len__(self) -> int: ... class ItemsView(AbstractSet[Tuple[_KT_co, _VT_co]], MappingView, Generic[_KT_co, _VT_co]): From 8739644eb32e585298aabe0d7053d45d533c468a Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Fri, 30 Nov 2018 10:37:48 -0800 Subject: [PATCH 2/4] Fix tests -- MappingView has a *concrete* __len__ implementation --- stdlib/2/typing.pyi | 5 +---- stdlib/3/typing.pyi | 3 --- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/stdlib/2/typing.pyi b/stdlib/2/typing.pyi index 1c738abe5ea2..73eadc332b6a 100644 --- a/stdlib/2/typing.pyi +++ b/stdlib/2/typing.pyi @@ -223,10 +223,7 @@ class MutableSet(AbstractSet[_T], Generic[_T]): def __ixor__(self, s: AbstractSet[_S]) -> MutableSet[Union[_T, _S]]: ... def __isub__(self, s: AbstractSet[Any]) -> MutableSet[_T]: ... -class MappingView: - def __len__(self) -> int: ... - # Implement Sized (but don't have it as a base class). - @abstractmethod +class MappingView(object): def __len__(self) -> int: ... class ItemsView(AbstractSet[Tuple[_KT_co, _VT_co]], MappingView, Generic[_KT_co, _VT_co]): diff --git a/stdlib/3/typing.pyi b/stdlib/3/typing.pyi index ed7724be7d05..91112c76dcdf 100644 --- a/stdlib/3/typing.pyi +++ b/stdlib/3/typing.pyi @@ -332,9 +332,6 @@ class MutableSet(AbstractSet[_T], Generic[_T]): class MappingView: def __len__(self) -> int: ... - # Implement Sized (but don't have it as a base class). - @abstractmethod - def __len__(self) -> int: ... class ItemsView(AbstractSet[Tuple[_KT_co, _VT_co]], MappingView, Generic[_KT_co, _VT_co]): def __contains__(self, o: object) -> bool: ... From 5ccb8bdbb43a23aaada83014a9c79a8ce418496c Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Fri, 30 Nov 2018 10:41:55 -0800 Subject: [PATCH 3/4] Put _Collection back in Sequence, remove unneeded __len__ from it and AbstractSet --- stdlib/3/typing.pyi | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/stdlib/3/typing.pyi b/stdlib/3/typing.pyi index 91112c76dcdf..974e88eb6b29 100644 --- a/stdlib/3/typing.pyi +++ b/stdlib/3/typing.pyi @@ -248,7 +248,7 @@ else: @abstractmethod def __len__(self) -> int: ... -class Sequence(Iterable[_T_co], Container[_T_co], Reversible[_T_co], Generic[_T_co]): +class Sequence(_Collection[_T_co], Reversible[_T_co], Generic[_T_co]): @overload @abstractmethod def __getitem__(self, i: int) -> _T_co: ... @@ -264,9 +264,6 @@ class Sequence(Iterable[_T_co], Container[_T_co], Reversible[_T_co], Generic[_T_ def __contains__(self, x: object) -> bool: ... def __iter__(self) -> Iterator[_T_co]: ... def __reversed__(self) -> Iterator[_T_co]: ... - # Implement Sized (but don't have it as a base class). - @abstractmethod - def __len__(self) -> int: ... class MutableSequence(Sequence[_T], Generic[_T]): @abstractmethod @@ -312,9 +309,6 @@ class AbstractSet(_Collection[_T_co], Generic[_T_co]): def __xor__(self, s: AbstractSet[_T]) -> AbstractSet[Union[_T_co, _T]]: ... # TODO: Argument can be a more general ABC? def isdisjoint(self, s: AbstractSet[Any]) -> bool: ... - # Implement Sized (but don't have it as a base class). - @abstractmethod - def __len__(self) -> int: ... class MutableSet(AbstractSet[_T], Generic[_T]): @abstractmethod From 4f78791f80f80c7cac94cf50d2ec327397925841 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Fri, 30 Nov 2018 10:53:56 -0800 Subject: [PATCH 4/4] Put MappingView first in ItemsView and KeysView --- stdlib/2/typing.pyi | 4 ++-- stdlib/3/typing.pyi | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/2/typing.pyi b/stdlib/2/typing.pyi index 73eadc332b6a..b028769a7e70 100644 --- a/stdlib/2/typing.pyi +++ b/stdlib/2/typing.pyi @@ -226,11 +226,11 @@ class MutableSet(AbstractSet[_T], Generic[_T]): class MappingView(object): def __len__(self) -> int: ... -class ItemsView(AbstractSet[Tuple[_KT_co, _VT_co]], MappingView, Generic[_KT_co, _VT_co]): +class ItemsView(MappingView, AbstractSet[Tuple[_KT_co, _VT_co]], Generic[_KT_co, _VT_co]): def __contains__(self, o: object) -> bool: ... def __iter__(self) -> Iterator[Tuple[_KT_co, _VT_co]]: ... -class KeysView(AbstractSet[_KT_co], MappingView, Generic[_KT_co]): +class KeysView(MappingView, AbstractSet[_KT_co], Generic[_KT_co]): def __contains__(self, o: object) -> bool: ... def __iter__(self) -> Iterator[_KT_co]: ... diff --git a/stdlib/3/typing.pyi b/stdlib/3/typing.pyi index 974e88eb6b29..8a2b1000e74b 100644 --- a/stdlib/3/typing.pyi +++ b/stdlib/3/typing.pyi @@ -327,11 +327,11 @@ class MutableSet(AbstractSet[_T], Generic[_T]): class MappingView: def __len__(self) -> int: ... -class ItemsView(AbstractSet[Tuple[_KT_co, _VT_co]], MappingView, Generic[_KT_co, _VT_co]): +class ItemsView(MappingView, AbstractSet[Tuple[_KT_co, _VT_co]], Generic[_KT_co, _VT_co]): def __contains__(self, o: object) -> bool: ... def __iter__(self) -> Iterator[Tuple[_KT_co, _VT_co]]: ... -class KeysView(AbstractSet[_KT_co], MappingView, Generic[_KT_co]): +class KeysView(MappingView, AbstractSet[_KT_co], Generic[_KT_co]): def __contains__(self, o: object) -> bool: ... def __iter__(self) -> Iterator[_KT_co]: ...