aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/_abcoll.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/_abcoll.py')
-rw-r--r--Lib/_abcoll.py146
1 files changed, 84 insertions, 62 deletions
diff --git a/Lib/_abcoll.py b/Lib/_abcoll.py
index e7376e4a56a..5ddcea3a301 100644
--- a/Lib/_abcoll.py
+++ b/Lib/_abcoll.py
@@ -17,20 +17,36 @@ __all__ = ["Hashable", "Iterable", "Iterator",
"Mapping", "MutableMapping",
"MappingView", "KeysView", "ItemsView", "ValuesView",
"Sequence", "MutableSequence",
+ "ByteString",
]
-### ONE-TRICK PONIES ###
-def _hasattr(C, attr):
- try:
- return any(attr in B.__dict__ for B in C.__mro__)
- except AttributeError:
- # Old-style class
- return hasattr(C, attr)
+### collection related types which are not exposed through builtin ###
+## iterators ##
+bytes_iterator = type(iter(b''))
+bytearray_iterator = type(iter(bytearray()))
+#callable_iterator = ???
+dict_keyiterator = type(iter({}.keys()))
+dict_valueiterator = type(iter({}.values()))
+dict_itemiterator = type(iter({}.items()))
+list_iterator = type(iter([]))
+list_reverseiterator = type(iter(reversed([])))
+range_iterator = type(iter(range(0)))
+set_iterator = type(iter(set()))
+str_iterator = type(iter(""))
+tuple_iterator = type(iter(()))
+zip_iterator = type(iter(zip()))
+## views ##
+dict_keys = type({}.keys())
+dict_values = type({}.values())
+dict_items = type({}.items())
+## misc ##
+dict_proxy = type(type.__dict__)
+
+### ONE-TRICK PONIES ###
-class Hashable:
- __metaclass__ = ABCMeta
+class Hashable(metaclass=ABCMeta):
@abstractmethod
def __hash__(self):
@@ -39,21 +55,15 @@ class Hashable:
@classmethod
def __subclasshook__(cls, C):
if cls is Hashable:
- try:
- for B in C.__mro__:
- if "__hash__" in B.__dict__:
- if B.__dict__["__hash__"]:
- return True
- break
- except AttributeError:
- # Old-style class
- if getattr(C, "__hash__", None):
- return True
+ for B in C.__mro__:
+ if "__hash__" in B.__dict__:
+ if B.__dict__["__hash__"]:
+ return True
+ break
return NotImplemented
-class Iterable:
- __metaclass__ = ABCMeta
+class Iterable(metaclass=ABCMeta):
@abstractmethod
def __iter__(self):
@@ -63,17 +73,15 @@ class Iterable:
@classmethod
def __subclasshook__(cls, C):
if cls is Iterable:
- if _hasattr(C, "__iter__"):
+ if any("__iter__" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
-Iterable.register(str)
-
class Iterator(Iterable):
@abstractmethod
- def next(self):
+ def __next__(self):
raise StopIteration
def __iter__(self):
@@ -82,13 +90,26 @@ class Iterator(Iterable):
@classmethod
def __subclasshook__(cls, C):
if cls is Iterator:
- if _hasattr(C, "next") and _hasattr(C, "__iter__"):
+ if (any("__next__" in B.__dict__ for B in C.__mro__) and
+ any("__iter__" in B.__dict__ for B in C.__mro__)):
return True
return NotImplemented
-
-class Sized:
- __metaclass__ = ABCMeta
+Iterator.register(bytes_iterator)
+Iterator.register(bytearray_iterator)
+#Iterator.register(callable_iterator)
+Iterator.register(dict_keyiterator)
+Iterator.register(dict_valueiterator)
+Iterator.register(dict_itemiterator)
+Iterator.register(list_iterator)
+Iterator.register(list_reverseiterator)
+Iterator.register(range_iterator)
+Iterator.register(set_iterator)
+Iterator.register(str_iterator)
+Iterator.register(tuple_iterator)
+Iterator.register(zip_iterator)
+
+class Sized(metaclass=ABCMeta):
@abstractmethod
def __len__(self):
@@ -97,13 +118,12 @@ class Sized:
@classmethod
def __subclasshook__(cls, C):
if cls is Sized:
- if _hasattr(C, "__len__"):
+ if any("__len__" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
-class Container:
- __metaclass__ = ABCMeta
+class Container(metaclass=ABCMeta):
@abstractmethod
def __contains__(self, x):
@@ -112,13 +132,12 @@ class Container:
@classmethod
def __subclasshook__(cls, C):
if cls is Container:
- if _hasattr(C, "__contains__"):
+ if any("__contains__" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
-class Callable:
- __metaclass__ = ABCMeta
+class Callable(metaclass=ABCMeta):
@abstractmethod
def __call__(self, *args, **kwds):
@@ -127,7 +146,7 @@ class Callable:
@classmethod
def __subclasshook__(cls, C):
if cls is Callable:
- if _hasattr(C, "__call__"):
+ if any("__call__" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
@@ -136,6 +155,7 @@ class Callable:
class Set(Sized, Iterable, Container):
+
"""A set is a finite, iterable container.
This class provides concrete generic implementations of all
@@ -164,12 +184,12 @@ class Set(Sized, Iterable, Container):
def __gt__(self, other):
if not isinstance(other, Set):
return NotImplemented
- return other < self
+ return other.__lt__(self)
def __ge__(self, other):
if not isinstance(other, Set):
return NotImplemented
- return other <= self
+ return other.__le__(self)
def __eq__(self, other):
if not isinstance(other, Set):
@@ -220,9 +240,6 @@ class Set(Sized, Iterable, Container):
other = self._from_iterable(other)
return (self - other) | (other - self)
- # Sets are not hashable by default, but subclasses can change this
- __hash__ = None
-
def _hash(self):
"""Compute the hash value of a set.
@@ -238,7 +255,7 @@ class Set(Sized, Iterable, Container):
freedom for __eq__ or __hash__. We match the algorithm used
by the built-in frozenset type.
"""
- MAX = sys.maxint
+ MAX = sys.maxsize
MASK = 2 * MAX + 1
n = len(self)
h = 1927868237 * (n + 1)
@@ -351,28 +368,14 @@ class Mapping(Sized, Iterable, Container):
else:
return True
- def iterkeys(self):
- return iter(self)
-
- def itervalues(self):
- for key in self:
- yield self[key]
-
- def iteritems(self):
- for key in self:
- yield (key, self[key])
-
def keys(self):
- return list(self)
+ return KeysView(self)
def items(self):
- return [(key, self[key]) for key in self]
+ return ItemsView(self)
def values(self):
- return [self[key] for key in self]
-
- # Mappings are not hashable by default, but subclasses can change this
- __hash__ = None
+ return ValuesView(self)
def __eq__(self, other):
if not isinstance(other, Mapping):
@@ -382,6 +385,7 @@ class Mapping(Sized, Iterable, Container):
def __ne__(self, other):
return not (self == other)
+
class MappingView(Sized):
def __init__(self, mapping):
@@ -407,6 +411,8 @@ class KeysView(MappingView, Set):
for key in self._mapping:
yield key
+KeysView.register(dict_keys)
+
class ItemsView(MappingView, Set):
@@ -427,6 +433,8 @@ class ItemsView(MappingView, Set):
for key in self._mapping:
yield (key, self._mapping[key])
+ItemsView.register(dict_items)
+
class ValuesView(MappingView):
@@ -440,6 +448,8 @@ class ValuesView(MappingView):
for key in self._mapping:
yield self._mapping[key]
+ValuesView.register(dict_values)
+
class MutableMapping(Mapping):
@@ -515,6 +525,7 @@ MutableMapping.register(dict)
class Sequence(Sized, Iterable, Container):
+
"""All the operations on a read-only sequence.
Concrete subclasses must override __new__ or __init__,
@@ -555,9 +566,19 @@ class Sequence(Sized, Iterable, Container):
return sum(1 for v in self if v == value)
Sequence.register(tuple)
-Sequence.register(basestring)
-Sequence.register(buffer)
-Sequence.register(xrange)
+Sequence.register(str)
+Sequence.register(range)
+
+
+class ByteString(Sequence):
+
+ """This unifies bytes and bytearray.
+
+ XXX Should add all their methods.
+ """
+
+ByteString.register(bytes)
+ByteString.register(bytearray)
class MutableSequence(Sequence):
@@ -599,3 +620,4 @@ class MutableSequence(Sequence):
return self
MutableSequence.register(list)
+MutableSequence.register(bytearray) # Multiply inheriting, see ByteString