blob: d25d521290ac720b4a0f8e80ae41cee7cb5709ee [file] [log] [blame]
Guido van Rossum64c06e32007-11-22 00:55:51 +00001# 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 ]
20
21### ONE-TRICK PONIES ###
22
23class Hashable:
24 __metaclass__ = ABCMeta
25
26 @abstractmethod
27 def __hash__(self):
28 return 0
29
30 @classmethod
31 def __subclasshook__(cls, C):
32 if cls is Hashable:
33 for B in C.__mro__:
34 if "__hash__" in B.__dict__:
35 if B.__dict__["__hash__"]:
36 return True
37 break
38 return NotImplemented
39
40
41class Iterable:
42 __metaclass__ = ABCMeta
43
44 @abstractmethod
45 def __iter__(self):
46 while False:
47 yield None
48
49 @classmethod
50 def __subclasshook__(cls, C):
51 if cls is Iterable:
52 if any("__iter__" in B.__dict__ for B in C.__mro__):
53 return True
54 return NotImplemented
55
56Iterable.register(str)
57
58
Raymond Hettingerc2bc0d12008-02-09 01:18:42 +000059class Iterator(Iterable):
Guido van Rossum64c06e32007-11-22 00:55:51 +000060
61 @abstractmethod
62 def __next__(self):
63 raise StopIteration
64
65 def __iter__(self):
66 return self
67
68 @classmethod
69 def __subclasshook__(cls, C):
70 if cls is Iterator:
71 if any("next" in B.__dict__ for B in C.__mro__):
72 return True
73 return NotImplemented
74
75
76class Sized:
77 __metaclass__ = ABCMeta
78
79 @abstractmethod
80 def __len__(self):
81 return 0
82
83 @classmethod
84 def __subclasshook__(cls, C):
85 if cls is Sized:
86 if any("__len__" in B.__dict__ for B in C.__mro__):
87 return True
88 return NotImplemented
89
90
91class Container:
92 __metaclass__ = ABCMeta
93
94 @abstractmethod
95 def __contains__(self, x):
96 return False
97
98 @classmethod
99 def __subclasshook__(cls, C):
100 if cls is Container:
101 if any("__contains__" in B.__dict__ for B in C.__mro__):
102 return True
103 return NotImplemented
104
105
106class Callable:
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 Callable:
116 if any("__call__" in B.__dict__ for B in C.__mro__):
117 return True
118 return NotImplemented
119
120
121### SETS ###
122
123
Raymond Hettingerc2bc0d12008-02-09 01:18:42 +0000124class Set(Sized, Iterable, Container):
Guido van Rossum64c06e32007-11-22 00:55:51 +0000125 """A set is a finite, iterable container.
126
127 This class provides concrete generic implementations of all
128 methods except for __contains__, __iter__ and __len__.
129
130 To override the comparisons (presumably for speed, as the
131 semantics are fixed), all you have to do is redefine __le__ and
132 then the other operations will automatically follow suit.
133 """
134
Guido van Rossum64c06e32007-11-22 00:55:51 +0000135 def __le__(self, other):
136 if not isinstance(other, Set):
137 return NotImplemented
138 if len(self) > len(other):
139 return False
140 for elem in self:
141 if elem not in other:
142 return False
143 return True
144
145 def __lt__(self, other):
146 if not isinstance(other, Set):
147 return NotImplemented
148 return len(self) < len(other) and self.__le__(other)
149
Raymond Hettingerd53f1c42008-02-08 23:34:21 +0000150 def __gt__(self, other):
151 if not isinstance(other, Set):
152 return NotImplemented
153 return other < self
154
155 def __ge__(self, other):
156 if not isinstance(other, Set):
157 return NotImplemented
158 return other <= self
159
Guido van Rossum64c06e32007-11-22 00:55:51 +0000160 def __eq__(self, other):
161 if not isinstance(other, Set):
162 return NotImplemented
163 return len(self) == len(other) and self.__le__(other)
164
Raymond Hettingerd53f1c42008-02-08 23:34:21 +0000165 def __ne__(self, other):
166 return not (self == other)
167
Guido van Rossum64c06e32007-11-22 00:55:51 +0000168 @classmethod
169 def _from_iterable(cls, it):
Raymond Hettinger017b6a32008-02-07 03:10:33 +0000170 '''Construct an instance of the class from any iterable input.
171
172 Must override this method if the class constructor signature
Raymond Hettinger2e827bf2008-02-09 03:34:52 +0000173 does not accept an iterable for an input.
Raymond Hettinger017b6a32008-02-07 03:10:33 +0000174 '''
Raymond Hettinger2e827bf2008-02-09 03:34:52 +0000175 return cls(it)
Guido van Rossum64c06e32007-11-22 00:55:51 +0000176
177 def __and__(self, other):
178 if not isinstance(other, Iterable):
179 return NotImplemented
180 return self._from_iterable(value for value in other if value in self)
181
Raymond Hettingerabf3fcf2008-01-30 00:01:07 +0000182 def isdisjoint(self, other):
183 for value in other:
184 if value in self:
185 return False
186 return True
187
Guido van Rossum64c06e32007-11-22 00:55:51 +0000188 def __or__(self, other):
189 if not isinstance(other, Iterable):
190 return NotImplemented
191 return self._from_iterable(itertools.chain(self, other))
192
193 def __sub__(self, other):
194 if not isinstance(other, Set):
195 if not isinstance(other, Iterable):
196 return NotImplemented
197 other = self._from_iterable(other)
198 return self._from_iterable(value for value in self
199 if value not in other)
200
201 def __xor__(self, other):
202 if not isinstance(other, Set):
203 if not isinstance(other, Iterable):
204 return NotImplemented
205 other = self._from_iterable(other)
206 return (self - other) | (other - self)
207
208 def _hash(self):
209 """Compute the hash value of a set.
210
211 Note that we don't define __hash__: not all sets are hashable.
212 But if you define a hashable set type, its __hash__ should
213 call this function.
214
215 This must be compatible __eq__.
216
217 All sets ought to compare equal if they contain the same
218 elements, regardless of how they are implemented, and
219 regardless of the order of the elements; so there's not much
220 freedom for __eq__ or __hash__. We match the algorithm used
221 by the built-in frozenset type.
222 """
223 MAX = sys.maxint
224 MASK = 2 * MAX + 1
225 n = len(self)
226 h = 1927868237 * (n + 1)
227 h &= MASK
228 for x in self:
229 hx = hash(x)
230 h ^= (hx ^ (hx << 16) ^ 89869747) * 3644798167
231 h &= MASK
232 h = h * 69069 + 907133923
233 h &= MASK
234 if h > MAX:
235 h -= MASK + 1
236 if h == -1:
237 h = 590923713
238 return h
239
240Set.register(frozenset)
241
242
243class MutableSet(Set):
244
245 @abstractmethod
246 def add(self, value):
247 """Return True if it was added, False if already there."""
248 raise NotImplementedError
249
250 @abstractmethod
251 def discard(self, value):
252 """Return True if it was deleted, False if not there."""
253 raise NotImplementedError
254
Raymond Hettinger7d518f42008-01-30 00:08:31 +0000255 def remove(self, value):
256 """Remove an element. If not a member, raise a KeyError."""
257 if value not in self:
258 raise KeyError(value)
259 self.discard(value)
260
Guido van Rossum64c06e32007-11-22 00:55:51 +0000261 def pop(self):
262 """Return the popped value. Raise KeyError if empty."""
263 it = iter(self)
264 try:
265 value = it.__next__()
266 except StopIteration:
267 raise KeyError
268 self.discard(value)
269 return value
270
Guido van Rossum64c06e32007-11-22 00:55:51 +0000271 def clear(self):
272 """This is slow (creates N new iterators!) but effective."""
273 try:
274 while True:
275 self.pop()
276 except KeyError:
277 pass
278
279 def __ior__(self, it):
280 for value in it:
281 self.add(value)
282 return self
283
284 def __iand__(self, c):
285 for value in self:
286 if value not in c:
287 self.discard(value)
288 return self
289
290 def __ixor__(self, it):
Raymond Hettingere67420d2008-01-31 01:38:15 +0000291 if not isinstance(it, Set):
292 it = self._from_iterable(it)
Guido van Rossum64c06e32007-11-22 00:55:51 +0000293 for value in it:
Raymond Hettingere67420d2008-01-31 01:38:15 +0000294 if value in self:
295 self.discard(value)
296 else:
297 self.add(value)
Raymond Hettingere973c612008-01-31 01:42:11 +0000298 return self
Guido van Rossum64c06e32007-11-22 00:55:51 +0000299
300 def __isub__(self, it):
301 for value in it:
302 self.discard(value)
303 return self
304
305MutableSet.register(set)
306
307
308### MAPPINGS ###
309
310
Raymond Hettingerc2bc0d12008-02-09 01:18:42 +0000311class Mapping(Sized, Iterable, Container):
Guido van Rossum64c06e32007-11-22 00:55:51 +0000312
313 @abstractmethod
314 def __getitem__(self, key):
315 raise KeyError
316
317 def get(self, key, default=None):
318 try:
319 return self[key]
320 except KeyError:
321 return default
322
323 def __contains__(self, key):
324 try:
325 self[key]
326 except KeyError:
327 return False
328 else:
329 return True
330
Guido van Rossum64c06e32007-11-22 00:55:51 +0000331 def keys(self):
332 return KeysView(self)
333
334 def items(self):
335 return ItemsView(self)
336
337 def values(self):
338 return ValuesView(self)
339
Raymond Hettinger45eda642008-02-06 01:49:00 +0000340 def __eq__(self, other):
341 return isinstance(other, Mapping) and \
342 dict(self.items()) == dict(other.items())
343
344 def __ne__(self, other):
345 return not (self == other)
Guido van Rossum64c06e32007-11-22 00:55:51 +0000346
Raymond Hettingerc2bc0d12008-02-09 01:18:42 +0000347class MappingView(Sized):
Guido van Rossum64c06e32007-11-22 00:55:51 +0000348
349 def __init__(self, mapping):
350 self._mapping = mapping
351
352 def __len__(self):
353 return len(self._mapping)
354
355
356class KeysView(MappingView, Set):
357
358 def __contains__(self, key):
359 return key in self._mapping
360
361 def __iter__(self):
362 for key in self._mapping:
363 yield key
364
365KeysView.register(type({}.keys()))
366
367
368class ItemsView(MappingView, Set):
369
370 def __contains__(self, item):
371 key, value = item
372 try:
373 v = self._mapping[key]
374 except KeyError:
375 return False
376 else:
377 return v == value
378
379 def __iter__(self):
380 for key in self._mapping:
381 yield (key, self._mapping[key])
382
383ItemsView.register(type({}.items()))
384
385
386class ValuesView(MappingView):
387
388 def __contains__(self, value):
389 for key in self._mapping:
390 if value == self._mapping[key]:
391 return True
392 return False
393
394 def __iter__(self):
395 for key in self._mapping:
396 yield self._mapping[key]
397
398ValuesView.register(type({}.values()))
399
400
401class MutableMapping(Mapping):
402
403 @abstractmethod
404 def __setitem__(self, key, value):
405 raise KeyError
406
407 @abstractmethod
408 def __delitem__(self, key):
409 raise KeyError
410
411 __marker = object()
412
413 def pop(self, key, default=__marker):
414 try:
415 value = self[key]
416 except KeyError:
417 if default is self.__marker:
418 raise
419 return default
420 else:
421 del self[key]
422 return value
423
424 def popitem(self):
425 try:
426 key = next(iter(self))
427 except StopIteration:
428 raise KeyError
429 value = self[key]
430 del self[key]
431 return key, value
432
433 def clear(self):
434 try:
435 while True:
436 self.popitem()
437 except KeyError:
438 pass
439
440 def update(self, other=(), **kwds):
441 if isinstance(other, Mapping):
442 for key in other:
443 self[key] = other[key]
444 elif hasattr(other, "keys"):
445 for key in other.keys():
446 self[key] = other[key]
447 else:
448 for key, value in other:
449 self[key] = value
450 for key, value in kwds.items():
451 self[key] = value
452
Raymond Hettinger45eda642008-02-06 01:49:00 +0000453 def setdefault(self, key, default=None):
454 try:
455 return self[key]
456 except KeyError:
457 self[key] = default
458 return default
459
Guido van Rossum64c06e32007-11-22 00:55:51 +0000460MutableMapping.register(dict)
461
462
463### SEQUENCES ###
464
465
Raymond Hettingerc2bc0d12008-02-09 01:18:42 +0000466class Sequence(Sized, Iterable, Container):
Guido van Rossum64c06e32007-11-22 00:55:51 +0000467 """All the operations on a read-only sequence.
468
469 Concrete subclasses must override __new__ or __init__,
470 __getitem__, and __len__.
471 """
472
473 @abstractmethod
474 def __getitem__(self, index):
475 raise IndexError
476
Guido van Rossum64c06e32007-11-22 00:55:51 +0000477 def __iter__(self):
478 i = 0
Raymond Hettinger18a1ffc2008-02-08 23:02:27 +0000479 try:
480 while True:
Guido van Rossum64c06e32007-11-22 00:55:51 +0000481 v = self[i]
Raymond Hettinger18a1ffc2008-02-08 23:02:27 +0000482 yield v
483 i += 1
484 except IndexError:
485 return
Guido van Rossum64c06e32007-11-22 00:55:51 +0000486
487 def __contains__(self, value):
488 for v in self:
489 if v == value:
490 return True
491 return False
492
493 def __reversed__(self):
494 for i in reversed(range(len(self))):
495 yield self[i]
496
497 def index(self, value):
498 for i, v in enumerate(self):
499 if v == value:
500 return i
501 raise ValueError
502
503 def count(self, value):
504 return sum(1 for v in self if v == value)
505
506Sequence.register(tuple)
507Sequence.register(basestring)
508Sequence.register(buffer)
509
510
511class MutableSequence(Sequence):
512
513 @abstractmethod
514 def __setitem__(self, index, value):
515 raise IndexError
516
517 @abstractmethod
518 def __delitem__(self, index):
519 raise IndexError
520
521 @abstractmethod
522 def insert(self, index, value):
523 raise IndexError
524
525 def append(self, value):
526 self.insert(len(self), value)
527
528 def reverse(self):
529 n = len(self)
530 for i in range(n//2):
531 self[i], self[n-i-1] = self[n-i-1], self[i]
532
533 def extend(self, values):
534 for v in values:
535 self.append(v)
536
537 def pop(self, index=-1):
538 v = self[index]
539 del self[index]
540 return v
541
542 def remove(self, value):
543 del self[self.index(value)]
544
545 def __iadd__(self, values):
546 self.extend(values)
547
548MutableSequence.register(list)