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