_collections_abc.py revision b9da9bc0a04b718e8395e2e88c3053ab944579b7
1# Copyright 2007 Google, Inc. All Rights Reserved.
2# Licensed to PSF under a Contributor Agreement.
3
4"""Abstract Base Classes (ABCs) for collections, according to PEP 3119.
5
6DON'T USE THIS MODULE DIRECTLY!  The classes here should be imported
7via collections; they are defined here only to alleviate certain
8bootstrapping issues.  Unit tests are in test_collections.
9"""
10
11from abc import ABCMeta, abstractmethod
12
13__all__ = ["Hashable", "Iterable", "Iterator",
14           "Sized", "Container", "Callable",
15           "Set", "MutableSet",
16           "Mapping", "MutableMapping",
17           "MappingView", "KeysView", "ItemsView", "ValuesView",
18           "Sequence", "MutableSequence",
19           "ByteString",
20           "bytearray_iterator", "bytes_iterator", "dict_itemiterator",
21           "dict_items", "dict_keyiterator", "dict_keys", "dict_proxy",
22           "dict_valueiterator", "dict_values", "list_iterator",
23           "list_reverseiterator", "range_iterator", "set_iterator",
24           "str_iterator", "tuple_iterator", "zip_iterator",
25           ]
26
27
28### collection related types which are not exposed through builtin ###
29## iterators ##
30bytes_iterator = type(iter(b''))
31bytearray_iterator = type(iter(bytearray()))
32#callable_iterator = ???
33dict_keyiterator = type(iter({}.keys()))
34dict_valueiterator = type(iter({}.values()))
35dict_itemiterator = type(iter({}.items()))
36list_iterator = type(iter([]))
37list_reverseiterator = type(iter(reversed([])))
38range_iterator = type(iter(range(0)))
39set_iterator = type(iter(set()))
40str_iterator = type(iter(""))
41tuple_iterator = type(iter(()))
42zip_iterator = type(iter(zip()))
43## views ##
44dict_keys = type({}.keys())
45dict_values = type({}.values())
46dict_items = type({}.items())
47## misc ##
48dict_proxy = type(type.__dict__)
49
50
51### ONE-TRICK PONIES ###
52
53class Hashable(metaclass=ABCMeta):
54
55    @abstractmethod
56    def __hash__(self):
57        return 0
58
59    @classmethod
60    def __subclasshook__(cls, C):
61        if cls is Hashable:
62            for B in C.__mro__:
63                if "__hash__" in B.__dict__:
64                    if B.__dict__["__hash__"]:
65                        return True
66                    break
67        return NotImplemented
68
69
70class Iterable(metaclass=ABCMeta):
71
72    @abstractmethod
73    def __iter__(self):
74        while False:
75            yield None
76
77    @classmethod
78    def __subclasshook__(cls, C):
79        if cls is Iterable:
80            if any("__iter__" in B.__dict__ for B in C.__mro__):
81                return True
82        return NotImplemented
83
84
85class Iterator(metaclass=ABCMeta):
86
87    @abstractmethod
88    def __next__(self):
89        raise StopIteration
90
91    def __iter__(self):
92        return self
93
94    @classmethod
95    def __subclasshook__(cls, C):
96        if cls is Iterator:
97            if any("__next__" in B.__dict__ for B in C.__mro__):
98                return True
99        return NotImplemented
100
101Iterator.register(bytes_iterator)
102Iterator.register(bytearray_iterator)
103#Iterator.register(callable_iterator)
104Iterator.register(dict_keyiterator)
105Iterator.register(dict_valueiterator)
106Iterator.register(dict_itemiterator)
107Iterator.register(list_iterator)
108Iterator.register(list_reverseiterator)
109Iterator.register(range_iterator)
110Iterator.register(set_iterator)
111Iterator.register(str_iterator)
112Iterator.register(tuple_iterator)
113Iterator.register(zip_iterator)
114
115class Sized(metaclass=ABCMeta):
116
117    @abstractmethod
118    def __len__(self):
119        return 0
120
121    @classmethod
122    def __subclasshook__(cls, C):
123        if cls is Sized:
124            if any("__len__" in B.__dict__ for B in C.__mro__):
125                return True
126        return NotImplemented
127
128
129class Container(metaclass=ABCMeta):
130
131    @abstractmethod
132    def __contains__(self, x):
133        return False
134
135    @classmethod
136    def __subclasshook__(cls, C):
137        if cls is Container:
138            if any("__contains__" in B.__dict__ for B in C.__mro__):
139                return True
140        return NotImplemented
141
142
143class Callable(metaclass=ABCMeta):
144
145    @abstractmethod
146    def __contains__(self, x):
147        return False
148
149    @classmethod
150    def __subclasshook__(cls, C):
151        if cls is Callable:
152            if any("__call__" in B.__dict__ for B in C.__mro__):
153                return True
154        return NotImplemented
155
156
157### SETS ###
158
159
160class Set(metaclass=ABCMeta):
161
162    """A set is a finite, iterable container.
163
164    This class provides concrete generic implementations of all
165    methods except for __contains__, __iter__ and __len__.
166
167    To override the comparisons (presumably for speed, as the
168    semantics are fixed), all you have to do is redefine __le__ and
169    then the other operations will automatically follow suit.
170    """
171
172    @abstractmethod
173    def __contains__(self, value):
174        return False
175
176    @abstractmethod
177    def __iter__(self):
178        while False:
179            yield None
180
181    @abstractmethod
182    def __len__(self):
183        return 0
184
185    def __le__(self, other):
186        if not isinstance(other, Set):
187            return NotImplemented
188        if len(self) > len(other):
189            return False
190        for elem in self:
191            if elem not in other:
192                return False
193        return True
194
195    def __lt__(self, other):
196        if not isinstance(other, Set):
197            return NotImplemented
198        return len(self) < len(other) and self.__le__(other)
199
200    def __eq__(self, other):
201        if not isinstance(other, Set):
202            return NotImplemented
203        return len(self) == len(other) and self.__le__(other)
204
205    @classmethod
206    def _from_iterable(cls, it):
207        return frozenset(it)
208
209    def __and__(self, other):
210        if not isinstance(other, Iterable):
211            return NotImplemented
212        return self._from_iterable(value for value in other if value in self)
213
214    def isdisjoint(self, other):
215        for value in other:
216            if value in self:
217                return False
218        return True
219
220    def __or__(self, other):
221        if not isinstance(other, Iterable):
222            return NotImplemented
223        return self._from_iterable(itertools.chain(self, other))
224
225    def __sub__(self, other):
226        if not isinstance(other, Set):
227            if not isinstance(other, Iterable):
228                return NotImplemented
229            other = self._from_iterable(other)
230        return self._from_iterable(value for value in self
231                                   if value not in other)
232
233    def __xor__(self, other):
234        if not isinstance(other, Set):
235            if not isinstance(other, Iterable):
236                return NotImplemented
237            other = self._from_iterable(other)
238        return (self - other) | (other - self)
239
240    def _hash(self):
241        """Compute the hash value of a set.
242
243        Note that we don't define __hash__: not all sets are hashable.
244        But if you define a hashable set type, its __hash__ should
245        call this function.
246
247        This must be compatible __eq__.
248
249        All sets ought to compare equal if they contain the same
250        elements, regardless of how they are implemented, and
251        regardless of the order of the elements; so there's not much
252        freedom for __eq__ or __hash__.  We match the algorithm used
253        by the built-in frozenset type.
254        """
255        MAX = sys.maxsize
256        MASK = 2 * MAX + 1
257        n = len(self)
258        h = 1927868237 * (n + 1)
259        h &= MASK
260        for x in self:
261            hx = hash(x)
262            h ^= (hx ^ (hx << 16) ^ 89869747)  * 3644798167
263            h &= MASK
264        h = h * 69069 + 907133923
265        h &= MASK
266        if h > MAX:
267            h -= MASK + 1
268        if h == -1:
269            h = 590923713
270        return h
271
272Set.register(frozenset)
273
274
275class MutableSet(Set):
276
277    @abstractmethod
278    def add(self, value):
279        """Return True if it was added, False if already there."""
280        raise NotImplementedError
281
282    @abstractmethod
283    def discard(self, value):
284        """Return True if it was deleted, False if not there."""
285        raise NotImplementedError
286
287    def remove(self, value):
288        """Remove an element. If not a member, raise a KeyError."""
289        if value not in self:
290            raise KeyError(value)
291        self.discard(value)
292
293    def pop(self):
294        """Return the popped value.  Raise KeyError if empty."""
295        it = iter(self)
296        try:
297            value = it.__next__()
298        except StopIteration:
299            raise KeyError
300        self.discard(value)
301        return value
302
303    def clear(self):
304        """This is slow (creates N new iterators!) but effective."""
305        try:
306            while True:
307                self.pop()
308        except KeyError:
309            pass
310
311    def __ior__(self, it: Iterable):
312        for value in it:
313            self.add(value)
314        return self
315
316    def __iand__(self, c: Container):
317        for value in self:
318            if value not in c:
319                self.discard(value)
320        return self
321
322    def __ixor__(self, it: Iterable):
323        if not isinstance(it, Set):
324            it = self._from_iterable(it)
325        for value in it:
326            if value in self:
327                self.discard(value)
328            else:
329                self.add(value)
330        return self
331
332    def __isub__(self, it: Iterable):
333        for value in it:
334            self.discard(value)
335        return self
336
337MutableSet.register(set)
338
339
340### MAPPINGS ###
341
342
343class Mapping(metaclass=ABCMeta):
344
345    @abstractmethod
346    def __getitem__(self, key):
347        raise KeyError
348
349    def get(self, key, default=None):
350        try:
351            return self[key]
352        except KeyError:
353            return default
354
355    def __contains__(self, key):
356        try:
357            self[key]
358        except KeyError:
359            return False
360        else:
361            return True
362
363    @abstractmethod
364    def __len__(self):
365        return 0
366
367    @abstractmethod
368    def __iter__(self):
369        while False:
370            yield None
371
372    def keys(self):
373        return KeysView(self)
374
375    def items(self):
376        return ItemsView(self)
377
378    def values(self):
379        return ValuesView(self)
380
381    def __eq__(self, other):
382        return set(self) == set(other)
383
384    def __ne__(self, other):
385        return set(self) == set(other)
386
387class MappingView(metaclass=ABCMeta):
388
389    def __init__(self, mapping):
390        self._mapping = mapping
391
392    def __len__(self):
393        return len(self._mapping)
394
395
396class KeysView(MappingView, Set):
397
398    def __contains__(self, key):
399        return key in self._mapping
400
401    def __iter__(self):
402        for key in self._mapping:
403            yield key
404
405KeysView.register(dict_keys)
406
407
408class ItemsView(MappingView, Set):
409
410    def __contains__(self, item):
411        key, value = item
412        try:
413            v = self._mapping[key]
414        except KeyError:
415            return False
416        else:
417            return v == value
418
419    def __iter__(self):
420        for key in self._mapping:
421            yield (key, self._mapping[key])
422
423ItemsView.register(dict_items)
424
425
426class ValuesView(MappingView):
427
428    def __contains__(self, value):
429        for key in self._mapping:
430            if value == self._mapping[key]:
431                return True
432        return False
433
434    def __iter__(self):
435        for key in self._mapping:
436            yield self._mapping[key]
437
438ValuesView.register(dict_values)
439
440
441class MutableMapping(Mapping):
442
443    @abstractmethod
444    def __setitem__(self, key, value):
445        raise KeyError
446
447    @abstractmethod
448    def __delitem__(self, key):
449        raise KeyError
450
451    __marker = object()
452
453    def pop(self, key, default=__marker):
454        try:
455            value = self[key]
456        except KeyError:
457            if default is self.__marker:
458                raise
459            return default
460        else:
461            del self[key]
462            return value
463
464    def popitem(self):
465        try:
466            key = next(iter(self))
467        except StopIteration:
468            raise KeyError
469        value = self[key]
470        del self[key]
471        return key, value
472
473    def clear(self):
474        try:
475            while True:
476                self.popitem()
477        except KeyError:
478            pass
479
480    def update(self, other=(), **kwds):
481        if isinstance(other, Mapping):
482            for key in other:
483                self[key] = other[key]
484        elif hasattr(other, "keys"):
485            for key in other.keys():
486                self[key] = other[key]
487        else:
488            for key, value in other:
489                self[key] = value
490        for key, value in kwds.items():
491            self[key] = value
492
493    def setdefault(self, key, default=None):
494        try:
495            return self[key]
496        except KeyError:
497            self[key] = default
498        return default
499
500MutableMapping.register(dict)
501
502
503### SEQUENCES ###
504
505
506class Sequence(metaclass=ABCMeta):
507
508    """All the operations on a read-only sequence.
509
510    Concrete subclasses must override __new__ or __init__,
511    __getitem__, and __len__.
512    """
513
514    @abstractmethod
515    def __getitem__(self, index):
516        raise IndexError
517
518    @abstractmethod
519    def __len__(self):
520        return 0
521
522    def __iter__(self):
523        i = 0
524        while True:
525            try:
526                v = self[i]
527            except IndexError:
528                break
529            yield v
530            i += 1
531
532    def __contains__(self, value):
533        for v in self:
534            if v == value:
535                return True
536        return False
537
538    def __reversed__(self):
539        for i in reversed(range(len(self))):
540            yield self[i]
541
542    def index(self, value):
543        for i, v in enumerate(self):
544            if v == value:
545                return i
546        raise ValueError
547
548    def count(self, value):
549        return sum(1 for v in self if v == value)
550
551Sequence.register(tuple)
552Sequence.register(str)
553
554
555class ByteString(Sequence):
556
557    """This unifies bytes and bytearray.
558
559    XXX Should add all their methods.
560    """
561
562ByteString.register(bytes)
563ByteString.register(bytearray)
564
565
566class MutableSequence(Sequence):
567
568    @abstractmethod
569    def __setitem__(self, index, value):
570        raise IndexError
571
572    @abstractmethod
573    def __delitem__(self, index):
574        raise IndexError
575
576    @abstractmethod
577    def insert(self, index, value):
578        raise IndexError
579
580    def append(self, value):
581        self.insert(len(self), value)
582
583    def reverse(self):
584        n = len(self)
585        for i in range(n//2):
586            self[i], self[n-i-1] = self[n-i-1], self[i]
587
588    def extend(self, values):
589        for v in values:
590            self.append(v)
591
592    def pop(self, index=-1):
593        v = self[index]
594        del self[index]
595        return v
596
597    def remove(self, value):
598        del self[self.index(value)]
599
600    def __iadd__(self, values):
601        self.extend(values)
602
603MutableSequence.register(list)
604MutableSequence.register(bytearray)  # Multiply inheriting, see ByteString
605