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