blob: 122aac085cbaba68846636661c3a80e35d76095a [file] [log] [blame]
Guido van Rossumcd16bf62007-06-13 18:07:49 +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
Guido van Rossum7eaf8222007-06-18 17:58:50 +00007via collections; they are defined here only to alleviate certain
Guido van Rossumcd16bf62007-06-13 18:07:49 +00008bootstrapping 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",
Guido van Rossumd05eb002007-11-21 22:26:24 +000019 "ByteString",
Christian Heimesf83be4e2007-11-28 09:44:38 +000020 "bytearray_iterator", "bytes_iterator", "dict_itemiterator",
Christian Heimes0db38532007-11-29 16:21:13 +000021 "dict_items", "dict_keyiterator", "dict_keys", "dict_proxy",
Christian Heimesf83be4e2007-11-28 09:44:38 +000022 "dict_valueiterator", "dict_values", "list_iterator",
23 "list_reverseiterator", "range_iterator", "set_iterator",
24 "str_iterator", "tuple_iterator", "zip_iterator",
Guido van Rossumcd16bf62007-06-13 18:07:49 +000025 ]
26
Christian Heimesf83be4e2007-11-28 09:44:38 +000027
28### collection related types which are not exposed through builtin ###
29## iterators ##
30bytes_iterator = type(iter(b''))
31bytearray_iterator = type(iter(bytearray()))
32#callable_iterator = ???
33dict_keyiterator = type(iter({}.keys()))
34dict_valueiterator = type(iter({}.values()))
35dict_itemiterator = type(iter({}.items()))
36list_iterator = type(iter([]))
37list_reverseiterator = type(iter(reversed([])))
38range_iterator = type(iter(range(0)))
39set_iterator = type(iter(set()))
40str_iterator = type(iter(""))
41tuple_iterator = type(iter(()))
42zip_iterator = type(iter(zip()))
43## views ##
44dict_keys = type({}.keys())
45dict_values = type({}.values())
46dict_items = type({}.items())
Christian Heimes0db38532007-11-29 16:21:13 +000047## misc ##
48dict_proxy = type(type.__dict__)
Christian Heimesf83be4e2007-11-28 09:44:38 +000049
50
Guido van Rossumcd16bf62007-06-13 18:07:49 +000051### ONE-TRICK PONIES ###
52
53class Hashable(metaclass=ABCMeta):
54
55 @abstractmethod
56 def __hash__(self):
57 return 0
58
59 @classmethod
60 def __subclasshook__(cls, C):
61 if cls is Hashable:
62 for B in C.__mro__:
63 if "__hash__" in B.__dict__:
64 if B.__dict__["__hash__"]:
65 return True
66 break
67 return NotImplemented
68
69
70class Iterable(metaclass=ABCMeta):
71
72 @abstractmethod
73 def __iter__(self):
74 while False:
75 yield None
76
77 @classmethod
78 def __subclasshook__(cls, C):
79 if cls is Iterable:
80 if any("__iter__" in B.__dict__ for B in C.__mro__):
81 return True
82 return NotImplemented
83
Guido van Rossumcd16bf62007-06-13 18:07:49 +000084
85class Iterator(metaclass=ABCMeta):
86
87 @abstractmethod
88 def __next__(self):
89 raise StopIteration
90
91 def __iter__(self):
92 return self
93
94 @classmethod
95 def __subclasshook__(cls, C):
96 if cls is Iterator:
97 if any("__next__" in B.__dict__ for B in C.__mro__):
98 return True
99 return NotImplemented
100
Christian Heimesf83be4e2007-11-28 09:44:38 +0000101Iterator.register(bytes_iterator)
102Iterator.register(bytearray_iterator)
103#Iterator.register(callable_iterator)
104Iterator.register(dict_keyiterator)
105Iterator.register(dict_valueiterator)
106Iterator.register(dict_itemiterator)
107Iterator.register(list_iterator)
108Iterator.register(list_reverseiterator)
109Iterator.register(range_iterator)
110Iterator.register(set_iterator)
111Iterator.register(str_iterator)
112Iterator.register(tuple_iterator)
113Iterator.register(zip_iterator)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000114
115class Sized(metaclass=ABCMeta):
116
117 @abstractmethod
118 def __len__(self):
119 return 0
120
121 @classmethod
122 def __subclasshook__(cls, C):
123 if cls is Sized:
124 if any("__len__" in B.__dict__ for B in C.__mro__):
125 return True
126 return NotImplemented
127
128
129class Container(metaclass=ABCMeta):
130
131 @abstractmethod
132 def __contains__(self, x):
133 return False
134
135 @classmethod
136 def __subclasshook__(cls, C):
137 if cls is Container:
138 if any("__contains__" in B.__dict__ for B in C.__mro__):
139 return True
140 return NotImplemented
141
142
143class Callable(metaclass=ABCMeta):
144
145 @abstractmethod
146 def __contains__(self, x):
147 return False
148
149 @classmethod
150 def __subclasshook__(cls, C):
151 if cls is Callable:
152 if any("__call__" in B.__dict__ for B in C.__mro__):
153 return True
154 return NotImplemented
155
156
157### SETS ###
158
159
160class Set(metaclass=ABCMeta):
161
162 """A set is a finite, iterable container.
163
164 This class provides concrete generic implementations of all
165 methods except for __contains__, __iter__ and __len__.
166
167 To override the comparisons (presumably for speed, as the
168 semantics are fixed), all you have to do is redefine __le__ and
169 then the other operations will automatically follow suit.
170 """
171
172 @abstractmethod
173 def __contains__(self, value):
174 return False
175
176 @abstractmethod
177 def __iter__(self):
178 while False:
179 yield None
180
181 @abstractmethod
182 def __len__(self):
183 return 0
184
185 def __le__(self, other):
186 if not isinstance(other, Set):
187 return NotImplemented
188 if len(self) > len(other):
189 return False
190 for elem in self:
191 if elem not in other:
192 return False
193 return True
194
195 def __lt__(self, other):
196 if not isinstance(other, Set):
197 return NotImplemented
198 return len(self) < len(other) and self.__le__(other)
199
200 def __eq__(self, other):
201 if not isinstance(other, Set):
202 return NotImplemented
203 return len(self) == len(other) and self.__le__(other)
204
205 @classmethod
206 def _from_iterable(cls, it):
207 return frozenset(it)
208
209 def __and__(self, other):
210 if not isinstance(other, Iterable):
211 return NotImplemented
212 return self._from_iterable(value for value in other if value in self)
213
214 def __or__(self, other):
215 if not isinstance(other, Iterable):
216 return NotImplemented
217 return self._from_iterable(itertools.chain(self, other))
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 __xor__(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 - other) | (other - self)
233
234 def _hash(self):
235 """Compute the hash value of a set.
236
237 Note that we don't define __hash__: not all sets are hashable.
238 But if you define a hashable set type, its __hash__ should
239 call this function.
240
241 This must be compatible __eq__.
242
243 All sets ought to compare equal if they contain the same
244 elements, regardless of how they are implemented, and
245 regardless of the order of the elements; so there's not much
246 freedom for __eq__ or __hash__. We match the algorithm used
247 by the built-in frozenset type.
248 """
249 MAX = sys.maxint
250 MASK = 2 * MAX + 1
251 n = len(self)
252 h = 1927868237 * (n + 1)
253 h &= MASK
254 for x in self:
255 hx = hash(x)
256 h ^= (hx ^ (hx << 16) ^ 89869747) * 3644798167
257 h &= MASK
258 h = h * 69069 + 907133923
259 h &= MASK
260 if h > MAX:
261 h -= MASK + 1
262 if h == -1:
263 h = 590923713
264 return h
265
266Set.register(frozenset)
267
268
269class MutableSet(Set):
270
271 @abstractmethod
272 def add(self, value):
273 """Return True if it was added, False if already there."""
274 raise NotImplementedError
275
276 @abstractmethod
277 def discard(self, value):
278 """Return True if it was deleted, False if not there."""
279 raise NotImplementedError
280
281 def pop(self):
282 """Return the popped value. Raise KeyError if empty."""
283 it = iter(self)
284 try:
285 value = it.__next__()
286 except StopIteration:
287 raise KeyError
288 self.discard(value)
289 return value
290
291 def toggle(self, value):
292 """Return True if it was added, False if deleted."""
293 # XXX This implementation is not thread-safe
294 if value in self:
295 self.discard(value)
296 return False
297 else:
298 self.add(value)
299 return True
300
301 def clear(self):
302 """This is slow (creates N new iterators!) but effective."""
303 try:
304 while True:
305 self.pop()
306 except KeyError:
307 pass
308
309 def __ior__(self, it: Iterable):
310 for value in it:
311 self.add(value)
312 return self
313
314 def __iand__(self, c: Container):
315 for value in self:
316 if value not in c:
317 self.discard(value)
318 return self
319
320 def __ixor__(self, it: Iterable):
321 # This calls toggle(), so if that is overridded, we call the override
322 for value in it:
323 self.toggle(it)
324 return self
325
326 def __isub__(self, it: Iterable):
327 for value in it:
328 self.discard(value)
329 return self
330
331MutableSet.register(set)
332
333
334### MAPPINGS ###
335
336
337class Mapping(metaclass=ABCMeta):
338
339 @abstractmethod
340 def __getitem__(self, key):
341 raise KeyError
342
343 def get(self, key, default=None):
344 try:
345 return self[key]
346 except KeyError:
347 return default
348
349 def __contains__(self, key):
350 try:
351 self[key]
352 except KeyError:
353 return False
354 else:
355 return True
356
357 @abstractmethod
358 def __len__(self):
359 return 0
360
361 @abstractmethod
362 def __iter__(self):
363 while False:
364 yield None
365
366 def keys(self):
367 return KeysView(self)
368
369 def items(self):
370 return ItemsView(self)
371
372 def values(self):
373 return ValuesView(self)
374
375
376class MappingView(metaclass=ABCMeta):
377
378 def __init__(self, mapping):
379 self._mapping = mapping
380
381 def __len__(self):
382 return len(self._mapping)
383
384
385class KeysView(MappingView, Set):
386
387 def __contains__(self, key):
388 return key in self._mapping
389
390 def __iter__(self):
391 for key in self._mapping:
392 yield key
393
Christian Heimesf83be4e2007-11-28 09:44:38 +0000394KeysView.register(dict_keys)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000395
396
397class ItemsView(MappingView, Set):
398
399 def __contains__(self, item):
400 key, value = item
401 try:
402 v = self._mapping[key]
403 except KeyError:
404 return False
405 else:
406 return v == value
407
408 def __iter__(self):
409 for key in self._mapping:
410 yield (key, self._mapping[key])
411
Christian Heimesf83be4e2007-11-28 09:44:38 +0000412ItemsView.register(dict_items)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000413
414
415class ValuesView(MappingView):
416
417 def __contains__(self, value):
418 for key in self._mapping:
419 if value == self._mapping[key]:
420 return True
421 return False
422
423 def __iter__(self):
424 for key in self._mapping:
425 yield self._mapping[key]
426
Christian Heimesf83be4e2007-11-28 09:44:38 +0000427ValuesView.register(dict_values)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000428
429
430class MutableMapping(Mapping):
431
432 @abstractmethod
433 def __setitem__(self, key, value):
434 raise KeyError
435
436 @abstractmethod
437 def __delitem__(self, key):
438 raise KeyError
439
440 __marker = object()
441
442 def pop(self, key, default=__marker):
443 try:
444 value = self[key]
445 except KeyError:
446 if default is self.__marker:
447 raise
448 return default
449 else:
450 del self[key]
451 return value
452
453 def popitem(self):
454 try:
455 key = next(iter(self))
456 except StopIteration:
457 raise KeyError
458 value = self[key]
459 del self[key]
460 return key, value
461
462 def clear(self):
463 try:
464 while True:
465 self.popitem()
466 except KeyError:
467 pass
468
469 def update(self, other=(), **kwds):
470 if isinstance(other, Mapping):
471 for key in other:
472 self[key] = other[key]
473 elif hasattr(other, "keys"):
474 for key in other.keys():
475 self[key] = other[key]
476 else:
477 for key, value in other:
478 self[key] = value
479 for key, value in kwds.items():
480 self[key] = value
481
482MutableMapping.register(dict)
483
484
485### SEQUENCES ###
486
487
488class Sequence(metaclass=ABCMeta):
489
490 """All the operations on a read-only sequence.
491
492 Concrete subclasses must override __new__ or __init__,
493 __getitem__, and __len__.
494 """
495
496 @abstractmethod
497 def __getitem__(self, index):
498 raise IndexError
499
500 @abstractmethod
501 def __len__(self):
502 return 0
503
504 def __iter__(self):
505 i = 0
506 while True:
507 try:
508 v = self[i]
509 except IndexError:
510 break
511 yield v
512 i += 1
513
514 def __contains__(self, value):
515 for v in self:
516 if v == value:
517 return True
518 return False
519
520 def __reversed__(self):
521 for i in reversed(range(len(self))):
522 yield self[i]
523
524 def index(self, value):
525 for i, v in enumerate(self):
526 if v == value:
527 return i
528 raise ValueError
529
530 def count(self, value):
531 return sum(1 for v in self if v == value)
532
533Sequence.register(tuple)
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000534Sequence.register(str)
Guido van Rossumd05eb002007-11-21 22:26:24 +0000535
536
537class ByteString(Sequence):
538
539 """This unifies bytes and bytearray.
540
541 XXX Should add all their methods.
542 """
543
544ByteString.register(bytes)
545ByteString.register(bytearray)
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000546
547
548class MutableSequence(Sequence):
549
550 @abstractmethod
551 def __setitem__(self, index, value):
552 raise IndexError
553
554 @abstractmethod
555 def __delitem__(self, index):
556 raise IndexError
557
558 @abstractmethod
559 def insert(self, index, value):
560 raise IndexError
561
562 def append(self, value):
563 self.insert(len(self), value)
564
565 def reverse(self):
566 n = len(self)
567 for i in range(n//2):
568 self[i], self[n-i-1] = self[n-i-1], self[i]
569
570 def extend(self, values):
571 for v in values:
572 self.append(v)
573
574 def pop(self, index=-1):
575 v = self[index]
576 del self[index]
577 return v
578
579 def remove(self, value):
580 del self[self.index(value)]
581
582 def __iadd__(self, values):
583 self.extend(values)
584
585MutableSequence.register(list)
Guido van Rossumd05eb002007-11-21 22:26:24 +0000586MutableSequence.register(bytearray) # Multiply inheriting, see ByteString