cpython: acd9a465b373 (original) (raw)
Mercurial > cpython
changeset 102866:acd9a465b373
Issue 27598: Add Collections to collections.abc. Patch by Ivan Levkivskyi, docs by Neil Girdhar.
Guido van Rossum guido@dropbox.com | |
---|---|
date | Tue, 23 Aug 2016 10:47:07 -0700 |
parents | d43a77b6f865 |
children | 013bb690c24a |
files | Doc/library/collections.abc.rst Lib/_collections_abc.py Lib/test/test_collections.py Lib/test/test_functools.py Misc/NEWS |
diffstat | 5 files changed, 132 insertions(+), 21 deletions(-)[+] [-] Doc/library/collections.abc.rst 26 Lib/_collections_abc.py 17 Lib/test/test_collections.py 90 Lib/test/test_functools.py 17 Misc/NEWS 3 |
line wrap: on
line diff
--- a/Doc/library/collections.abc.rst
+++ b/Doc/library/collections.abc.rst
@@ -45,10 +45,12 @@ ABC Inherits from
:class:Generator
:class:Iterator
send
, throw
close
, __iter__
, __next__
:class:Sized
__len__
:class:Callable
__call__
+:class:Collection
:class:Sized
, __contains__
,
:class:`Iterable`, ``__iter__``,[](#l1.8)
:class:`Container` ``__len__``[](#l1.9)
-:class:Sequence
:class:Sized
, __getitem__
, __contains__
, __iter__
, __reversed__
,
:class:`Reversible`, ``__len__`` ``index``, and ``count``[](#l1.12)
:class:`Container`[](#l1.13)
+:class:Sequence
:class:Reversible
, __getitem__
, __contains__
, __iter__
, __reversed__
,
:class:`Collection` ``__len__`` ``index``, and ``count``[](#l1.15)
:class:MutableSequence
:class:Sequence
__getitem__
, Inherited :class:Sequence
methods and
__setitem__
, append
, reverse
, extend
, pop
,
@@ -59,9 +61,9 @@ ABC Inherits from
:class:ByteString
:class:Sequence
__getitem__
, Inherited :class:Sequence
methods
__len__
-:class:Set
:class:Sized
, __contains__
, __le__
, __lt__
, __eq__
, __ne__
,
:class:`Iterable`, ``__iter__``, ``__gt__``, ``__ge__``, ``__and__``, ``__or__``,[](#l1.24)
:class:`Container` ``__len__`` ``__sub__``, ``__xor__``, and ``isdisjoint``[](#l1.25)
+:class:Set
:class:Collection
__contains__
, __le__
, __lt__
, __eq__
, __ne__
,
``__iter__``, ``__gt__``, ``__ge__``, ``__and__``, ``__or__``,[](#l1.27)
``__len__`` ``__sub__``, ``__xor__``, and ``isdisjoint``[](#l1.28)
:class:MutableSet
:class:Set
__contains__
, Inherited :class:Set
methods and
__iter__
, clear
, pop
, remove
, __ior__
,
@@ -69,9 +71,9 @@ ABC Inherits from
add
,
discard
-:class:Mapping
:class:Sized
, __getitem__
, __contains__
, keys
, items
, values
,
:class:`Iterable`, ``__iter__``, ``get``, ``__eq__``, and ``__ne__``[](#l1.37)
:class:`Container` ``__len__``[](#l1.38)
+:class:Mapping
:class:Collection
__getitem__
, __contains__
, keys
, items
, values
,
``__iter__``, ``get``, ``__eq__``, and ``__ne__``[](#l1.40)
``__len__``[](#l1.41)
:class:MutableMapping
:class:Mapping
__getitem__
, Inherited :class:Mapping
methods and
__setitem__
, pop
, popitem
, clear
, update
,
@@ -106,6 +108,12 @@ ABC Inherits from
ABC for classes that provide the :meth:__iter__
method.
See also the definition of :term:iterable
.
+.. class:: Collection
+
.. class:: Iterator
ABC for classes that provide the :meth:~iterator.__iter__
and
--- a/Lib/_collections_abc.py +++ b/Lib/_collections_abc.py @@ -11,7 +11,7 @@ import sys all = ["Awaitable", "Coroutine", "AsyncIterable", "AsyncIterator", "Hashable", "Iterable", "Iterator", "Generator", "Reversible",
"Sized", "Container", "Callable",[](#l2.7)
"Sized", "Container", "Callable", "Collection",[](#l2.8) "Set", "MutableSet",[](#l2.9) "Mapping", "MutableMapping",[](#l2.10) "MappingView", "KeysView", "ItemsView", "ValuesView",[](#l2.11)
@@ -326,6 +326,15 @@ class Container(metaclass=ABCMeta): return _check_methods(C, "contains") return NotImplemented +class Collection(Sized, Iterable, Container): +
- @classmethod
- def subclasshook(cls, C):
if cls is Collection:[](#l2.22)
return _check_methods(C, "__len__", "__iter__", "__contains__")[](#l2.23)
return NotImplemented[](#l2.24)
class Callable(metaclass=ABCMeta): @@ -345,7 +354,7 @@ class Callable(metaclass=ABCMeta):
SETS ###
-class Set(Sized, Iterable, Container): +class Set(Collection): """A set is a finite, iterable container. @@ -570,7 +579,7 @@ MutableSet.register(set)
MAPPINGS ###
-class Mapping(Sized, Iterable, Container): +class Mapping(Collection): slots = () @@ -794,7 +803,7 @@ MutableMapping.register(dict)
SEQUENCES ###
-class Sequence(Sized, Reversible, Container): +class Sequence(Reversible, Collection): """All the operations on a read-only sequence.
--- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -21,7 +21,7 @@ from collections import ChainMap from collections import deque from collections.abc import Awaitable, Coroutine, AsyncIterator, AsyncIterable from collections.abc import Hashable, Iterable, Iterator, Generator, Reversible -from collections.abc import Sized, Container, Callable +from collections.abc import Sized, Container, Callable, Collection from collections.abc import Set, MutableSet from collections.abc import Mapping, MutableMapping, KeysView, ItemsView, ValuesView from collections.abc import Sequence, MutableSequence @@ -771,6 +771,94 @@ class TestOneTrickPonyABCs(ABCTestCase): self.assertFalse(issubclass(RevRevBlocked, Reversible)) self.assertFalse(isinstance(RevRevBlocked(), Reversible))
- def test_Collection(self):
# Check some non-collections[](#l3.17)
non_collections = [None, 42, 3.14, 1j, lambda x: 2*x][](#l3.18)
for x in non_collections:[](#l3.19)
self.assertNotIsInstance(x, Collection)[](#l3.20)
self.assertFalse(issubclass(type(x), Collection), repr(type(x)))[](#l3.21)
# Check some non-collection iterables[](#l3.22)
non_col_iterables = [_test_gen(), iter(b''), iter(bytearray()),[](#l3.23)
(x for x in []), dict().values()][](#l3.24)
for x in non_col_iterables:[](#l3.25)
self.assertNotIsInstance(x, Collection)[](#l3.26)
self.assertFalse(issubclass(type(x), Collection), repr(type(x)))[](#l3.27)
# Check some collections[](#l3.28)
samples = [set(), frozenset(), dict(), bytes(), str(), tuple(),[](#l3.29)
list(), dict().keys(), dict().items()][](#l3.30)
for x in samples:[](#l3.31)
self.assertIsInstance(x, Collection)[](#l3.32)
self.assertTrue(issubclass(type(x), Collection), repr(type(x)))[](#l3.33)
# Check also Mapping, MutableMapping, etc.[](#l3.34)
self.assertTrue(issubclass(Sequence, Collection), repr(Sequence))[](#l3.35)
self.assertTrue(issubclass(Mapping, Collection), repr(Mapping))[](#l3.36)
self.assertTrue(issubclass(MutableMapping, Collection),[](#l3.37)
repr(MutableMapping))[](#l3.38)
self.assertTrue(issubclass(Set, Collection), repr(Set))[](#l3.39)
self.assertTrue(issubclass(MutableSet, Collection), repr(MutableSet))[](#l3.40)
self.assertTrue(issubclass(Sequence, Collection), repr(MutableSet))[](#l3.41)
# Check direct subclassing[](#l3.42)
class Col(Collection):[](#l3.43)
def __iter__(self):[](#l3.44)
return iter(list())[](#l3.45)
def __len__(self):[](#l3.46)
return 0[](#l3.47)
def __contains__(self, item):[](#l3.48)
return False[](#l3.49)
class DerCol(Col): pass[](#l3.50)
self.assertEqual(list(iter(Col())), [])[](#l3.51)
self.assertFalse(issubclass(list, Col))[](#l3.52)
self.assertFalse(issubclass(set, Col))[](#l3.53)
self.assertFalse(issubclass(float, Col))[](#l3.54)
self.assertEqual(list(iter(DerCol())), [])[](#l3.55)
self.assertFalse(issubclass(list, DerCol))[](#l3.56)
self.assertFalse(issubclass(set, DerCol))[](#l3.57)
self.assertFalse(issubclass(float, DerCol))[](#l3.58)
self.validate_abstract_methods(Collection, '__len__', '__iter__',[](#l3.59)
'__contains__')[](#l3.60)
# Check sized container non-iterable (which is not Collection) etc.[](#l3.61)
class ColNoIter:[](#l3.62)
def __len__(self): return 0[](#l3.63)
def __contains__(self, item): return False[](#l3.64)
class ColNoSize:[](#l3.65)
def __iter__(self): return iter([])[](#l3.66)
def __contains__(self, item): return False[](#l3.67)
class ColNoCont:[](#l3.68)
def __iter__(self): return iter([])[](#l3.69)
def __len__(self): return 0[](#l3.70)
self.assertFalse(issubclass(ColNoIter, Collection))[](#l3.71)
self.assertFalse(isinstance(ColNoIter(), Collection))[](#l3.72)
self.assertFalse(issubclass(ColNoSize, Collection))[](#l3.73)
self.assertFalse(isinstance(ColNoSize(), Collection))[](#l3.74)
self.assertFalse(issubclass(ColNoCont, Collection))[](#l3.75)
self.assertFalse(isinstance(ColNoCont(), Collection))[](#l3.76)
# Check None blocking[](#l3.77)
class SizeBlock:[](#l3.78)
def __iter__(self): return iter([])[](#l3.79)
def __contains__(self): return False[](#l3.80)
__len__ = None[](#l3.81)
class IterBlock:[](#l3.82)
def __len__(self): return 0[](#l3.83)
def __contains__(self): return True[](#l3.84)
__iter__ = None[](#l3.85)
self.assertFalse(issubclass(SizeBlock, Collection))[](#l3.86)
self.assertFalse(isinstance(SizeBlock(), Collection))[](#l3.87)
self.assertFalse(issubclass(IterBlock, Collection))[](#l3.88)
self.assertFalse(isinstance(IterBlock(), Collection))[](#l3.89)
# Check None blocking in subclass[](#l3.90)
class ColImpl:[](#l3.91)
def __iter__(self):[](#l3.92)
return iter(list())[](#l3.93)
def __len__(self):[](#l3.94)
return 0[](#l3.95)
def __contains__(self, item):[](#l3.96)
return False[](#l3.97)
class NonCol(ColImpl):[](#l3.98)
__contains__ = None[](#l3.99)
self.assertFalse(issubclass(NonCol, Collection))[](#l3.100)
self.assertFalse(isinstance(NonCol(), Collection))[](#l3.101)
+ + def test_Iterator(self): non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()] for x in non_samples:
--- a/Lib/test/test_functools.py +++ b/Lib/test/test_functools.py @@ -1548,13 +1548,15 @@ class TestSingleDispatch(unittest.TestCa bases = [c.Sequence, c.MutableMapping, c.Mapping, c.Set] for haystack in permutations(bases): m = mro(dict, haystack)
self.assertEqual(m, [dict, c.MutableMapping, c.Mapping, c.Sized,[](#l4.7)
c.Iterable, c.Container, object])[](#l4.8)
self.assertEqual(m, [dict, c.MutableMapping, c.Mapping,[](#l4.9)
c.Collection, c.Sized, c.Iterable,[](#l4.10)
c.Container, object])[](#l4.11) bases = [c.Container, c.Mapping, c.MutableMapping, c.OrderedDict][](#l4.12) for haystack in permutations(bases):[](#l4.13) m = mro(c.ChainMap, haystack)[](#l4.14) self.assertEqual(m, [c.ChainMap, c.MutableMapping, c.Mapping,[](#l4.15)
c.Sized, c.Iterable, c.Container, object])[](#l4.16)
c.Collection, c.Sized, c.Iterable,[](#l4.17)
c.Container, object])[](#l4.18)
# If there's a generic function with implementations registered for # both Sized and Container, passing a defaultdict to it results in an @@ -1575,9 +1577,9 @@ class TestSingleDispatch(unittest.TestCa bases = [c.MutableSequence, c.MutableMapping] for haystack in permutations(bases): m = mro(D, bases)
self.assertEqual(m, [D, c.MutableSequence, c.Sequence,[](#l4.26)
c.defaultdict, dict, c.MutableMapping,[](#l4.27)
c.Mapping, c.Sized, c.Reversible, c.Iterable, c.Container,[](#l4.28)
self.assertEqual(m, [D, c.MutableSequence, c.Sequence, c.Reversible,[](#l4.29)
c.defaultdict, dict, c.MutableMapping, c.Mapping,[](#l4.30)
c.Collection, c.Sized, c.Iterable, c.Container,[](#l4.31) object])[](#l4.32)
# Container and Callable are registered on different base classes and @@ -1590,7 +1592,8 @@ class TestSingleDispatch(unittest.TestCa for haystack in permutations(bases): m = mro(C, haystack) self.assertEqual(m, [C, c.Callable, c.defaultdict, dict, c.Mapping,
c.Sized, c.Iterable, c.Container, object])[](#l4.39)
c.Collection, c.Sized, c.Iterable,[](#l4.40)
c.Container, object])[](#l4.41)
def test_register_abc(self): c = collections
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -126,6 +126,9 @@ Core and Builtins Library ------- +- Issue 27598: Add Collections to collections.abc.