blob: 0519d42335bf11468e3470eba78211607871770c [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
59class Iterator:
60 __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
125class Set:
126 __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
138 @abstractmethod
139 def __contains__(self, value):
140 return False
141
142 @abstractmethod
143 def __iter__(self):
144 while False:
145 yield None
146
147 @abstractmethod
148 def __len__(self):
149 return 0
150
151 def __le__(self, other):
152 if not isinstance(other, Set):
153 return NotImplemented
154 if len(self) > len(other):
155 return False
156 for elem in self:
157 if elem not in other:
158 return False
159 return True
160
161 def __lt__(self, other):
162 if not isinstance(other, Set):
163 return NotImplemented
164 return len(self) < len(other) and self.__le__(other)
165
166 def __eq__(self, other):
167 if not isinstance(other, Set):
168 return NotImplemented
169 return len(self) == len(other) and self.__le__(other)
170
171 @classmethod
172 def _from_iterable(cls, it):
173 return frozenset(it)
174
175 def __and__(self, other):
176 if not isinstance(other, Iterable):
177 return NotImplemented
178 return self._from_iterable(value for value in other if value in self)
179
Raymond Hettingerabf3fcf2008-01-30 00:01:07 +0000180 def isdisjoint(self, other):
181 for value in other:
182 if value in self:
183 return False
184 return True
185
Guido van Rossum64c06e32007-11-22 00:55:51 +0000186 def __or__(self, other):
187 if not isinstance(other, Iterable):
188 return NotImplemented
189 return self._from_iterable(itertools.chain(self, other))
190
191 def __sub__(self, other):
192 if not isinstance(other, Set):
193 if not isinstance(other, Iterable):
194 return NotImplemented
195 other = self._from_iterable(other)
196 return self._from_iterable(value for value in self
197 if value not in other)
198
199 def __xor__(self, other):
200 if not isinstance(other, Set):
201 if not isinstance(other, Iterable):
202 return NotImplemented
203 other = self._from_iterable(other)
204 return (self - other) | (other - self)
205
206 def _hash(self):
207 """Compute the hash value of a set.
208
209 Note that we don't define __hash__: not all sets are hashable.
210 But if you define a hashable set type, its __hash__ should
211 call this function.
212
213 This must be compatible __eq__.
214
215 All sets ought to compare equal if they contain the same
216 elements, regardless of how they are implemented, and
217 regardless of the order of the elements; so there's not much
218 freedom for __eq__ or __hash__. We match the algorithm used
219 by the built-in frozenset type.
220 """
221 MAX = sys.maxint
222 MASK = 2 * MAX + 1
223 n = len(self)
224 h = 1927868237 * (n + 1)
225 h &= MASK
226 for x in self:
227 hx = hash(x)
228 h ^= (hx ^ (hx << 16) ^ 89869747) * 3644798167
229 h &= MASK
230 h = h * 69069 + 907133923
231 h &= MASK
232 if h > MAX:
233 h -= MASK + 1
234 if h == -1:
235 h = 590923713
236 return h
237
238Set.register(frozenset)
239
240
241class MutableSet(Set):
242
243 @abstractmethod
244 def add(self, value):
245 """Return True if it was added, False if already there."""
246 raise NotImplementedError
247
248 @abstractmethod
249 def discard(self, value):
250 """Return True if it was deleted, False if not there."""
251 raise NotImplementedError
252
Raymond Hettinger7d518f42008-01-30 00:08:31 +0000253 def remove(self, value):
254 """Remove an element. If not a member, raise a KeyError."""
255 if value not in self:
256 raise KeyError(value)
257 self.discard(value)
258
Guido van Rossum64c06e32007-11-22 00:55:51 +0000259 def pop(self):
260 """Return the popped value. Raise KeyError if empty."""
261 it = iter(self)
262 try:
263 value = it.__next__()
264 except StopIteration:
265 raise KeyError
266 self.discard(value)
267 return value
268
Guido van Rossum64c06e32007-11-22 00:55:51 +0000269 def clear(self):
270 """This is slow (creates N new iterators!) but effective."""
271 try:
272 while True:
273 self.pop()
274 except KeyError:
275 pass
276
277 def __ior__(self, it):
278 for value in it:
279 self.add(value)
280 return self
281
282 def __iand__(self, c):
283 for value in self:
284 if value not in c:
285 self.discard(value)
286 return self
287
288 def __ixor__(self, it):
Raymond Hettingere67420d2008-01-31 01:38:15 +0000289 if not isinstance(it, Set):
290 it = self._from_iterable(it)
Guido van Rossum64c06e32007-11-22 00:55:51 +0000291 for value in it:
Raymond Hettingere67420d2008-01-31 01:38:15 +0000292 if value in self:
293 self.discard(value)
294 else:
295 self.add(value)
Raymond Hettingere973c612008-01-31 01:42:11 +0000296 return self
Guido van Rossum64c06e32007-11-22 00:55:51 +0000297
298 def __isub__(self, it):
299 for value in it:
300 self.discard(value)
301 return self
302
303MutableSet.register(set)
304
305
306### MAPPINGS ###
307
308
309class Mapping:
310 __metaclass__ = ABCMeta
311
312 @abstractmethod
313 def __getitem__(self, key):
314 raise KeyError
315
316 def get(self, key, default=None):
317 try:
318 return self[key]
319 except KeyError:
320 return default
321
322 def __contains__(self, key):
323 try:
324 self[key]
325 except KeyError:
326 return False
327 else:
328 return True
329
330 @abstractmethod
331 def __len__(self):
332 return 0
333
334 @abstractmethod
335 def __iter__(self):
336 while False:
337 yield None
338
339 def keys(self):
340 return KeysView(self)
341
342 def items(self):
343 return ItemsView(self)
344
345 def values(self):
346 return ValuesView(self)
347
Raymond Hettinger45eda642008-02-06 01:49:00 +0000348 def __eq__(self, other):
349 return isinstance(other, Mapping) and \
350 dict(self.items()) == dict(other.items())
351
352 def __ne__(self, other):
353 return not (self == other)
Guido van Rossum64c06e32007-11-22 00:55:51 +0000354
355class MappingView:
356 __metaclass__ = ABCMeta
357
358 def __init__(self, mapping):
359 self._mapping = mapping
360
361 def __len__(self):
362 return len(self._mapping)
363
364
365class KeysView(MappingView, Set):
366
367 def __contains__(self, key):
368 return key in self._mapping
369
370 def __iter__(self):
371 for key in self._mapping:
372 yield key
373
374KeysView.register(type({}.keys()))
375
376
377class ItemsView(MappingView, Set):
378
379 def __contains__(self, item):
380 key, value = item
381 try:
382 v = self._mapping[key]
383 except KeyError:
384 return False
385 else:
386 return v == value
387
388 def __iter__(self):
389 for key in self._mapping:
390 yield (key, self._mapping[key])
391
392ItemsView.register(type({}.items()))
393
394
395class ValuesView(MappingView):
396
397 def __contains__(self, value):
398 for key in self._mapping:
399 if value == self._mapping[key]:
400 return True
401 return False
402
403 def __iter__(self):
404 for key in self._mapping:
405 yield self._mapping[key]
406
407ValuesView.register(type({}.values()))
408
409
410class MutableMapping(Mapping):
411
412 @abstractmethod
413 def __setitem__(self, key, value):
414 raise KeyError
415
416 @abstractmethod
417 def __delitem__(self, key):
418 raise KeyError
419
420 __marker = object()
421
422 def pop(self, key, default=__marker):
423 try:
424 value = self[key]
425 except KeyError:
426 if default is self.__marker:
427 raise
428 return default
429 else:
430 del self[key]
431 return value
432
433 def popitem(self):
434 try:
435 key = next(iter(self))
436 except StopIteration:
437 raise KeyError
438 value = self[key]
439 del self[key]
440 return key, value
441
442 def clear(self):
443 try:
444 while True:
445 self.popitem()
446 except KeyError:
447 pass
448
449 def update(self, other=(), **kwds):
450 if isinstance(other, Mapping):
451 for key in other:
452 self[key] = other[key]
453 elif hasattr(other, "keys"):
454 for key in other.keys():
455 self[key] = other[key]
456 else:
457 for key, value in other:
458 self[key] = value
459 for key, value in kwds.items():
460 self[key] = value
461
Raymond Hettinger45eda642008-02-06 01:49:00 +0000462 def setdefault(self, key, default=None):
463 try:
464 return self[key]
465 except KeyError:
466 self[key] = default
467 return default
468
Guido van Rossum64c06e32007-11-22 00:55:51 +0000469MutableMapping.register(dict)
470
471
472### SEQUENCES ###
473
474
475class Sequence:
476 __metaclass__ = ABCMeta
477
478 """All the operations on a read-only sequence.
479
480 Concrete subclasses must override __new__ or __init__,
481 __getitem__, and __len__.
482 """
483
484 @abstractmethod
485 def __getitem__(self, index):
486 raise IndexError
487
488 @abstractmethod
489 def __len__(self):
490 return 0
491
492 def __iter__(self):
493 i = 0
494 while True:
495 try:
496 v = self[i]
497 except IndexError:
498 break
499 yield v
500 i += 1
501
502 def __contains__(self, value):
503 for v in self:
504 if v == value:
505 return True
506 return False
507
508 def __reversed__(self):
509 for i in reversed(range(len(self))):
510 yield self[i]
511
512 def index(self, value):
513 for i, v in enumerate(self):
514 if v == value:
515 return i
516 raise ValueError
517
518 def count(self, value):
519 return sum(1 for v in self if v == value)
520
521Sequence.register(tuple)
522Sequence.register(basestring)
523Sequence.register(buffer)
524
525
526class MutableSequence(Sequence):
527
528 @abstractmethod
529 def __setitem__(self, index, value):
530 raise IndexError
531
532 @abstractmethod
533 def __delitem__(self, index):
534 raise IndexError
535
536 @abstractmethod
537 def insert(self, index, value):
538 raise IndexError
539
540 def append(self, value):
541 self.insert(len(self), value)
542
543 def reverse(self):
544 n = len(self)
545 for i in range(n//2):
546 self[i], self[n-i-1] = self[n-i-1], self[i]
547
548 def extend(self, values):
549 for v in values:
550 self.append(v)
551
552 def pop(self, index=-1):
553 v = self[index]
554 del self[index]
555 return v
556
557 def remove(self, value):
558 del self[self.index(value)]
559
560 def __iadd__(self, values):
561 self.extend(values)
562
563MutableSequence.register(list)