diff options
Diffstat (limited to 'Lib/_abcoll.py')
-rw-r--r-- | Lib/_abcoll.py | 146 |
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 |