• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
12import sys
13
14__all__ = ["Hashable", "Iterable", "Iterator",
15           "Sized", "Container", "Callable",
16           "Set", "MutableSet",
17           "Mapping", "MutableMapping",
18           "MappingView", "KeysView", "ItemsView", "ValuesView",
19           "Sequence", "MutableSequence",
20           ]
21
22### ONE-TRICK PONIES ###
23
24def _hasattr(C, attr):
25    try:
26        return any(attr in B.__dict__ for B in C.__mro__)
27    except AttributeError:
28        # Old-style class
29        return hasattr(C, attr)
30
31
32class Hashable:
33    __metaclass__ = ABCMeta
34
35    @abstractmethod
36    def __hash__(self):
37        return 0
38
39    @classmethod
40    def __subclasshook__(cls, C):
41        if cls is Hashable:
42            try:
43                for B in C.__mro__:
44                    if "__hash__" in B.__dict__:
45                        if B.__dict__["__hash__"]:
46                            return True
47                        break
48            except AttributeError:
49                # Old-style class
50                if getattr(C, "__hash__", None):
51                    return True
52        return NotImplemented
53
54
55class Iterable:
56    __metaclass__ = ABCMeta
57
58    @abstractmethod
59    def __iter__(self):
60        while False:
61            yield None
62
63    @classmethod
64    def __subclasshook__(cls, C):
65        if cls is Iterable:
66            if _hasattr(C, "__iter__"):
67                return True
68        return NotImplemented
69
70Iterable.register(str)
71
72
73class Iterator(Iterable):
74
75    @abstractmethod
76    def next(self):
77        'Return the next item from the iterator. When exhausted, raise StopIteration'
78        raise StopIteration
79
80    def __iter__(self):
81        return self
82
83    @classmethod
84    def __subclasshook__(cls, C):
85        if cls is Iterator:
86            if _hasattr(C, "next") and _hasattr(C, "__iter__"):
87                return True
88        return NotImplemented
89
90
91class Sized:
92    __metaclass__ = ABCMeta
93
94    @abstractmethod
95    def __len__(self):
96        return 0
97
98    @classmethod
99    def __subclasshook__(cls, C):
100        if cls is Sized:
101            if _hasattr(C, "__len__"):
102                return True
103        return NotImplemented
104
105
106class Container:
107    __metaclass__ = ABCMeta
108
109    @abstractmethod
110    def __contains__(self, x):
111        return False
112
113    @classmethod
114    def __subclasshook__(cls, C):
115        if cls is Container:
116            if _hasattr(C, "__contains__"):
117                return True
118        return NotImplemented
119
120
121class Callable:
122    __metaclass__ = ABCMeta
123
124    @abstractmethod
125    def __call__(self, *args, **kwds):
126        return False
127
128    @classmethod
129    def __subclasshook__(cls, C):
130        if cls is Callable:
131            if _hasattr(C, "__call__"):
132                return True
133        return NotImplemented
134
135
136### SETS ###
137
138
139class Set(Sized, Iterable, Container):
140    """A set is a finite, iterable container.
141
142    This class provides concrete generic implementations of all
143    methods except for __contains__, __iter__ and __len__.
144
145    To override the comparisons (presumably for speed, as the
146    semantics are fixed), redefine __le__ and __ge__,
147    then the other operations will automatically follow suit.
148    """
149
150    def __le__(self, other):
151        if not isinstance(other, Set):
152            return NotImplemented
153        if len(self) > len(other):
154            return False
155        for elem in self:
156            if elem not in other:
157                return False
158        return True
159
160    def __lt__(self, other):
161        if not isinstance(other, Set):
162            return NotImplemented
163        return len(self) < len(other) and self.__le__(other)
164
165    def __gt__(self, other):
166        if not isinstance(other, Set):
167            return NotImplemented
168        return len(self) > len(other) and self.__ge__(other)
169
170    def __ge__(self, other):
171        if not isinstance(other, Set):
172            return NotImplemented
173        if len(self) < len(other):
174            return False
175        for elem in other:
176            if elem not in self:
177                return False
178        return True
179
180    def __eq__(self, other):
181        if not isinstance(other, Set):
182            return NotImplemented
183        return len(self) == len(other) and self.__le__(other)
184
185    def __ne__(self, other):
186        return not (self == other)
187
188    @classmethod
189    def _from_iterable(cls, it):
190        '''Construct an instance of the class from any iterable input.
191
192        Must override this method if the class constructor signature
193        does not accept an iterable for an input.
194        '''
195        return cls(it)
196
197    def __and__(self, other):
198        if not isinstance(other, Iterable):
199            return NotImplemented
200        return self._from_iterable(value for value in other if value in self)
201
202    __rand__ = __and__
203
204    def isdisjoint(self, other):
205        'Return True if two sets have a null intersection.'
206        for value in other:
207            if value in self:
208                return False
209        return True
210
211    def __or__(self, other):
212        if not isinstance(other, Iterable):
213            return NotImplemented
214        chain = (e for s in (self, other) for e in s)
215        return self._from_iterable(chain)
216
217    __ror__ = __or__
218
219    def __sub__(self, other):
220        if not isinstance(other, Set):
221            if not isinstance(other, Iterable):
222                return NotImplemented
223            other = self._from_iterable(other)
224        return self._from_iterable(value for value in self
225                                   if value not in other)
226
227    def __rsub__(self, other):
228        if not isinstance(other, Set):
229            if not isinstance(other, Iterable):
230                return NotImplemented
231            other = self._from_iterable(other)
232        return self._from_iterable(value for value in other
233                                   if value not in self)
234
235    def __xor__(self, other):
236        if not isinstance(other, Set):
237            if not isinstance(other, Iterable):
238                return NotImplemented
239            other = self._from_iterable(other)
240        return (self - other) | (other - self)
241
242    __rxor__ = __xor__
243
244    # Sets are not hashable by default, but subclasses can change this
245    __hash__ = None
246
247    def _hash(self):
248        """Compute the hash value of a set.
249
250        Note that we don't define __hash__: not all sets are hashable.
251        But if you define a hashable set type, its __hash__ should
252        call this function.
253
254        This must be compatible __eq__.
255
256        All sets ought to compare equal if they contain the same
257        elements, regardless of how they are implemented, and
258        regardless of the order of the elements; so there's not much
259        freedom for __eq__ or __hash__.  We match the algorithm used
260        by the built-in frozenset type.
261        """
262        MAX = sys.maxint
263        MASK = 2 * MAX + 1
264        n = len(self)
265        h = 1927868237 * (n + 1)
266        h &= MASK
267        for x in self:
268            hx = hash(x)
269            h ^= (hx ^ (hx << 16) ^ 89869747)  * 3644798167
270            h &= MASK
271        h = h * 69069 + 907133923
272        h &= MASK
273        if h > MAX:
274            h -= MASK + 1
275        if h == -1:
276            h = 590923713
277        return h
278
279Set.register(frozenset)
280
281
282class MutableSet(Set):
283    """A mutable set is a finite, iterable container.
284
285    This class provides concrete generic implementations of all
286    methods except for __contains__, __iter__, __len__,
287    add(), and discard().
288
289    To override the comparisons (presumably for speed, as the
290    semantics are fixed), all you have to do is redefine __le__ and
291    then the other operations will automatically follow suit.
292    """
293
294    @abstractmethod
295    def add(self, value):
296        """Add an element."""
297        raise NotImplementedError
298
299    @abstractmethod
300    def discard(self, value):
301        """Remove an element.  Do not raise an exception if absent."""
302        raise NotImplementedError
303
304    def remove(self, value):
305        """Remove an element. If not a member, raise a KeyError."""
306        if value not in self:
307            raise KeyError(value)
308        self.discard(value)
309
310    def pop(self):
311        """Return the popped value.  Raise KeyError if empty."""
312        it = iter(self)
313        try:
314            value = next(it)
315        except StopIteration:
316            raise KeyError
317        self.discard(value)
318        return value
319
320    def clear(self):
321        """This is slow (creates N new iterators!) but effective."""
322        try:
323            while True:
324                self.pop()
325        except KeyError:
326            pass
327
328    def __ior__(self, it):
329        for value in it:
330            self.add(value)
331        return self
332
333    def __iand__(self, it):
334        for value in (self - it):
335            self.discard(value)
336        return self
337
338    def __ixor__(self, it):
339        if it is self:
340            self.clear()
341        else:
342            if not isinstance(it, Set):
343                it = self._from_iterable(it)
344            for value in it:
345                if value in self:
346                    self.discard(value)
347                else:
348                    self.add(value)
349        return self
350
351    def __isub__(self, it):
352        if it is self:
353            self.clear()
354        else:
355            for value in it:
356                self.discard(value)
357        return self
358
359MutableSet.register(set)
360
361
362### MAPPINGS ###
363
364
365class Mapping(Sized, Iterable, Container):
366
367    """A Mapping is a generic container for associating key/value
368    pairs.
369
370    This class provides concrete generic implementations of all
371    methods except for __getitem__, __iter__, and __len__.
372
373    """
374
375    @abstractmethod
376    def __getitem__(self, key):
377        raise KeyError
378
379    def get(self, key, default=None):
380        'D.get(k[,d]) -> D[k] if k in D, else d.  d defaults to None.'
381        try:
382            return self[key]
383        except KeyError:
384            return default
385
386    def __contains__(self, key):
387        try:
388            self[key]
389        except KeyError:
390            return False
391        else:
392            return True
393
394    def iterkeys(self):
395        'D.iterkeys() -> an iterator over the keys of D'
396        return iter(self)
397
398    def itervalues(self):
399        'D.itervalues() -> an iterator over the values of D'
400        for key in self:
401            yield self[key]
402
403    def iteritems(self):
404        'D.iteritems() -> an iterator over the (key, value) items of D'
405        for key in self:
406            yield (key, self[key])
407
408    def keys(self):
409        "D.keys() -> list of D's keys"
410        return list(self)
411
412    def items(self):
413        "D.items() -> list of D's (key, value) pairs, as 2-tuples"
414        return [(key, self[key]) for key in self]
415
416    def values(self):
417        "D.values() -> list of D's values"
418        return [self[key] for key in self]
419
420    # Mappings are not hashable by default, but subclasses can change this
421    __hash__ = None
422
423    def __eq__(self, other):
424        if not isinstance(other, Mapping):
425            return NotImplemented
426        return dict(self.items()) == dict(other.items())
427
428    def __ne__(self, other):
429        return not (self == other)
430
431class MappingView(Sized):
432
433    def __init__(self, mapping):
434        self._mapping = mapping
435
436    def __len__(self):
437        return len(self._mapping)
438
439    def __repr__(self):
440        return '{0.__class__.__name__}({0._mapping!r})'.format(self)
441
442
443class KeysView(MappingView, Set):
444
445    @classmethod
446    def _from_iterable(self, it):
447        return set(it)
448
449    def __contains__(self, key):
450        return key in self._mapping
451
452    def __iter__(self):
453        for key in self._mapping:
454            yield key
455
456KeysView.register(type({}.viewkeys()))
457
458class ItemsView(MappingView, Set):
459
460    @classmethod
461    def _from_iterable(self, it):
462        return set(it)
463
464    def __contains__(self, item):
465        key, value = item
466        try:
467            v = self._mapping[key]
468        except KeyError:
469            return False
470        else:
471            return v == value
472
473    def __iter__(self):
474        for key in self._mapping:
475            yield (key, self._mapping[key])
476
477ItemsView.register(type({}.viewitems()))
478
479class ValuesView(MappingView):
480
481    def __contains__(self, value):
482        for key in self._mapping:
483            if value == self._mapping[key]:
484                return True
485        return False
486
487    def __iter__(self):
488        for key in self._mapping:
489            yield self._mapping[key]
490
491ValuesView.register(type({}.viewvalues()))
492
493class MutableMapping(Mapping):
494
495    """A MutableMapping is a generic container for associating
496    key/value pairs.
497
498    This class provides concrete generic implementations of all
499    methods except for __getitem__, __setitem__, __delitem__,
500    __iter__, and __len__.
501
502    """
503
504    @abstractmethod
505    def __setitem__(self, key, value):
506        raise KeyError
507
508    @abstractmethod
509    def __delitem__(self, key):
510        raise KeyError
511
512    __marker = object()
513
514    def pop(self, key, default=__marker):
515        '''D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
516          If key is not found, d is returned if given, otherwise KeyError is raised.
517        '''
518        try:
519            value = self[key]
520        except KeyError:
521            if default is self.__marker:
522                raise
523            return default
524        else:
525            del self[key]
526            return value
527
528    def popitem(self):
529        '''D.popitem() -> (k, v), remove and return some (key, value) pair
530           as a 2-tuple; but raise KeyError if D is empty.
531        '''
532        try:
533            key = next(iter(self))
534        except StopIteration:
535            raise KeyError
536        value = self[key]
537        del self[key]
538        return key, value
539
540    def clear(self):
541        'D.clear() -> None.  Remove all items from D.'
542        try:
543            while True:
544                self.popitem()
545        except KeyError:
546            pass
547
548    def update(*args, **kwds):
549        ''' D.update([E, ]**F) -> None.  Update D from mapping/iterable E and F.
550            If E present and has a .keys() method, does:     for k in E: D[k] = E[k]
551            If E present and lacks .keys() method, does:     for (k, v) in E: D[k] = v
552            In either case, this is followed by: for k, v in F.items(): D[k] = v
553        '''
554        if not args:
555            raise TypeError("descriptor 'update' of 'MutableMapping' object "
556                            "needs an argument")
557        self = args[0]
558        args = args[1:]
559        if len(args) > 1:
560            raise TypeError('update expected at most 1 arguments, got %d' %
561                            len(args))
562        if args:
563            other = args[0]
564            if isinstance(other, Mapping):
565                for key in other:
566                    self[key] = other[key]
567            elif hasattr(other, "keys"):
568                for key in other.keys():
569                    self[key] = other[key]
570            else:
571                for key, value in other:
572                    self[key] = value
573        for key, value in kwds.items():
574            self[key] = value
575
576    def setdefault(self, key, default=None):
577        'D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D'
578        try:
579            return self[key]
580        except KeyError:
581            self[key] = default
582        return default
583
584MutableMapping.register(dict)
585
586
587### SEQUENCES ###
588
589
590class Sequence(Sized, Iterable, Container):
591    """All the operations on a read-only sequence.
592
593    Concrete subclasses must override __new__ or __init__,
594    __getitem__, and __len__.
595    """
596
597    @abstractmethod
598    def __getitem__(self, index):
599        raise IndexError
600
601    def __iter__(self):
602        i = 0
603        try:
604            while True:
605                v = self[i]
606                yield v
607                i += 1
608        except IndexError:
609            return
610
611    def __contains__(self, value):
612        for v in self:
613            if v == value:
614                return True
615        return False
616
617    def __reversed__(self):
618        for i in reversed(range(len(self))):
619            yield self[i]
620
621    def index(self, value):
622        '''S.index(value) -> integer -- return first index of value.
623           Raises ValueError if the value is not present.
624        '''
625        for i, v in enumerate(self):
626            if v == value:
627                return i
628        raise ValueError
629
630    def count(self, value):
631        'S.count(value) -> integer -- return number of occurrences of value'
632        return sum(1 for v in self if v == value)
633
634Sequence.register(tuple)
635Sequence.register(basestring)
636Sequence.register(buffer)
637Sequence.register(xrange)
638
639
640class MutableSequence(Sequence):
641
642    """All the operations on a read-only sequence.
643
644    Concrete subclasses must provide __new__ or __init__,
645    __getitem__, __setitem__, __delitem__, __len__, and insert().
646
647    """
648
649    @abstractmethod
650    def __setitem__(self, index, value):
651        raise IndexError
652
653    @abstractmethod
654    def __delitem__(self, index):
655        raise IndexError
656
657    @abstractmethod
658    def insert(self, index, value):
659        'S.insert(index, object) -- insert object before index'
660        raise IndexError
661
662    def append(self, value):
663        'S.append(object) -- append object to the end of the sequence'
664        self.insert(len(self), value)
665
666    def reverse(self):
667        'S.reverse() -- reverse *IN PLACE*'
668        n = len(self)
669        for i in range(n//2):
670            self[i], self[n-i-1] = self[n-i-1], self[i]
671
672    def extend(self, values):
673        'S.extend(iterable) -- extend sequence by appending elements from the iterable'
674        for v in values:
675            self.append(v)
676
677    def pop(self, index=-1):
678        '''S.pop([index]) -> item -- remove and return item at index (default last).
679           Raise IndexError if list is empty or index is out of range.
680        '''
681        v = self[index]
682        del self[index]
683        return v
684
685    def remove(self, value):
686        '''S.remove(value) -- remove first occurrence of value.
687           Raise ValueError if the value is not present.
688        '''
689        del self[self.index(value)]
690
691    def __iadd__(self, values):
692        self.extend(values)
693        return self
694
695MutableSequence.register(list)
696