Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/Lib/_collections_abc.py
12 views
1
# 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
6
Unit tests are in test_collections.
7
"""
8
9
############ Maintenance notes #########################################
10
#
11
# ABCs are different from other standard library modules in that they
12
# specify compliance tests. In general, once an ABC has been published,
13
# new methods (either abstract or concrete) cannot be added.
14
#
15
# Though classes that inherit from an ABC would automatically receive a
16
# new mixin method, registered classes would become non-compliant and
17
# violate the contract promised by ``isinstance(someobj, SomeABC)``.
18
#
19
# Though irritating, the correct procedure for adding new abstract or
20
# mixin methods is to create a new ABC as a subclass of the previous
21
# ABC. For example, union(), intersection(), and difference() cannot
22
# be added to Set but could go into a new ABC that extends Set.
23
#
24
# Because they are so hard to change, new ABCs should have their APIs
25
# carefully thought through prior to publication.
26
#
27
# Since ABCMeta only checks for the presence of methods, it is possible
28
# to alter the signature of a method by adding optional arguments
29
# or changing parameters names. This is still a bit dubious but at
30
# least it won't cause isinstance() to return an incorrect result.
31
#
32
#
33
#######################################################################
34
35
from abc import ABCMeta, abstractmethod
36
import sys
37
38
GenericAlias = type(list[int])
39
EllipsisType = type(...)
40
def _f(): pass
41
FunctionType = type(_f)
42
del _f
43
44
__all__ = ["Awaitable", "Coroutine",
45
"AsyncIterable", "AsyncIterator", "AsyncGenerator",
46
"Hashable", "Iterable", "Iterator", "Generator", "Reversible",
47
"Sized", "Container", "Callable", "Collection",
48
"Set", "MutableSet",
49
"Mapping", "MutableMapping",
50
"MappingView", "KeysView", "ItemsView", "ValuesView",
51
"Sequence", "MutableSequence",
52
"ByteString", "Buffer",
53
]
54
55
# This module has been renamed from collections.abc to _collections_abc to
56
# speed up interpreter startup. Some of the types such as MutableMapping are
57
# required early but collections module imports a lot of other modules.
58
# See issue #19218
59
__name__ = "collections.abc"
60
61
# Private list of types that we want to register with the various ABCs
62
# so that they will pass tests like:
63
# it = iter(somebytearray)
64
# assert isinstance(it, Iterable)
65
# Note: in other implementations, these types might not be distinct
66
# and they may have their own implementation specific types that
67
# are not included on this list.
68
bytes_iterator = type(iter(b''))
69
bytearray_iterator = type(iter(bytearray()))
70
#callable_iterator = ???
71
dict_keyiterator = type(iter({}.keys()))
72
dict_valueiterator = type(iter({}.values()))
73
dict_itemiterator = type(iter({}.items()))
74
list_iterator = type(iter([]))
75
list_reverseiterator = type(iter(reversed([])))
76
range_iterator = type(iter(range(0)))
77
longrange_iterator = type(iter(range(1 << 1000)))
78
set_iterator = type(iter(set()))
79
str_iterator = type(iter(""))
80
tuple_iterator = type(iter(()))
81
zip_iterator = type(iter(zip()))
82
## views ##
83
dict_keys = type({}.keys())
84
dict_values = type({}.values())
85
dict_items = type({}.items())
86
## misc ##
87
mappingproxy = type(type.__dict__)
88
generator = type((lambda: (yield))())
89
## coroutine ##
90
async def _coro(): pass
91
_coro = _coro()
92
coroutine = type(_coro)
93
_coro.close() # Prevent ResourceWarning
94
del _coro
95
## asynchronous generator ##
96
async def _ag(): yield
97
_ag = _ag()
98
async_generator = type(_ag)
99
del _ag
100
101
102
### ONE-TRICK PONIES ###
103
104
def _check_methods(C, *methods):
105
mro = C.__mro__
106
for method in methods:
107
for B in mro:
108
if method in B.__dict__:
109
if B.__dict__[method] is None:
110
return NotImplemented
111
break
112
else:
113
return NotImplemented
114
return True
115
116
class Hashable(metaclass=ABCMeta):
117
118
__slots__ = ()
119
120
@abstractmethod
121
def __hash__(self):
122
return 0
123
124
@classmethod
125
def __subclasshook__(cls, C):
126
if cls is Hashable:
127
return _check_methods(C, "__hash__")
128
return NotImplemented
129
130
131
class Awaitable(metaclass=ABCMeta):
132
133
__slots__ = ()
134
135
@abstractmethod
136
def __await__(self):
137
yield
138
139
@classmethod
140
def __subclasshook__(cls, C):
141
if cls is Awaitable:
142
return _check_methods(C, "__await__")
143
return NotImplemented
144
145
__class_getitem__ = classmethod(GenericAlias)
146
147
148
class Coroutine(Awaitable):
149
150
__slots__ = ()
151
152
@abstractmethod
153
def send(self, value):
154
"""Send a value into the coroutine.
155
Return next yielded value or raise StopIteration.
156
"""
157
raise StopIteration
158
159
@abstractmethod
160
def throw(self, typ, val=None, tb=None):
161
"""Raise an exception in the coroutine.
162
Return next yielded value or raise StopIteration.
163
"""
164
if val is None:
165
if tb is None:
166
raise typ
167
val = typ()
168
if tb is not None:
169
val = val.with_traceback(tb)
170
raise val
171
172
def close(self):
173
"""Raise GeneratorExit inside coroutine.
174
"""
175
try:
176
self.throw(GeneratorExit)
177
except (GeneratorExit, StopIteration):
178
pass
179
else:
180
raise RuntimeError("coroutine ignored GeneratorExit")
181
182
@classmethod
183
def __subclasshook__(cls, C):
184
if cls is Coroutine:
185
return _check_methods(C, '__await__', 'send', 'throw', 'close')
186
return NotImplemented
187
188
189
Coroutine.register(coroutine)
190
191
192
class AsyncIterable(metaclass=ABCMeta):
193
194
__slots__ = ()
195
196
@abstractmethod
197
def __aiter__(self):
198
return AsyncIterator()
199
200
@classmethod
201
def __subclasshook__(cls, C):
202
if cls is AsyncIterable:
203
return _check_methods(C, "__aiter__")
204
return NotImplemented
205
206
__class_getitem__ = classmethod(GenericAlias)
207
208
209
class AsyncIterator(AsyncIterable):
210
211
__slots__ = ()
212
213
@abstractmethod
214
async def __anext__(self):
215
"""Return the next item or raise StopAsyncIteration when exhausted."""
216
raise StopAsyncIteration
217
218
def __aiter__(self):
219
return self
220
221
@classmethod
222
def __subclasshook__(cls, C):
223
if cls is AsyncIterator:
224
return _check_methods(C, "__anext__", "__aiter__")
225
return NotImplemented
226
227
228
class AsyncGenerator(AsyncIterator):
229
230
__slots__ = ()
231
232
async def __anext__(self):
233
"""Return the next item from the asynchronous generator.
234
When exhausted, raise StopAsyncIteration.
235
"""
236
return await self.asend(None)
237
238
@abstractmethod
239
async def asend(self, value):
240
"""Send a value into the asynchronous generator.
241
Return next yielded value or raise StopAsyncIteration.
242
"""
243
raise StopAsyncIteration
244
245
@abstractmethod
246
async def athrow(self, typ, val=None, tb=None):
247
"""Raise an exception in the asynchronous generator.
248
Return next yielded value or raise StopAsyncIteration.
249
"""
250
if val is None:
251
if tb is None:
252
raise typ
253
val = typ()
254
if tb is not None:
255
val = val.with_traceback(tb)
256
raise val
257
258
async def aclose(self):
259
"""Raise GeneratorExit inside coroutine.
260
"""
261
try:
262
await self.athrow(GeneratorExit)
263
except (GeneratorExit, StopAsyncIteration):
264
pass
265
else:
266
raise RuntimeError("asynchronous generator ignored GeneratorExit")
267
268
@classmethod
269
def __subclasshook__(cls, C):
270
if cls is AsyncGenerator:
271
return _check_methods(C, '__aiter__', '__anext__',
272
'asend', 'athrow', 'aclose')
273
return NotImplemented
274
275
276
AsyncGenerator.register(async_generator)
277
278
279
class Iterable(metaclass=ABCMeta):
280
281
__slots__ = ()
282
283
@abstractmethod
284
def __iter__(self):
285
while False:
286
yield None
287
288
@classmethod
289
def __subclasshook__(cls, C):
290
if cls is Iterable:
291
return _check_methods(C, "__iter__")
292
return NotImplemented
293
294
__class_getitem__ = classmethod(GenericAlias)
295
296
297
class Iterator(Iterable):
298
299
__slots__ = ()
300
301
@abstractmethod
302
def __next__(self):
303
'Return the next item from the iterator. When exhausted, raise StopIteration'
304
raise StopIteration
305
306
def __iter__(self):
307
return self
308
309
@classmethod
310
def __subclasshook__(cls, C):
311
if cls is Iterator:
312
return _check_methods(C, '__iter__', '__next__')
313
return NotImplemented
314
315
316
Iterator.register(bytes_iterator)
317
Iterator.register(bytearray_iterator)
318
#Iterator.register(callable_iterator)
319
Iterator.register(dict_keyiterator)
320
Iterator.register(dict_valueiterator)
321
Iterator.register(dict_itemiterator)
322
Iterator.register(list_iterator)
323
Iterator.register(list_reverseiterator)
324
Iterator.register(range_iterator)
325
Iterator.register(longrange_iterator)
326
Iterator.register(set_iterator)
327
Iterator.register(str_iterator)
328
Iterator.register(tuple_iterator)
329
Iterator.register(zip_iterator)
330
331
332
class Reversible(Iterable):
333
334
__slots__ = ()
335
336
@abstractmethod
337
def __reversed__(self):
338
while False:
339
yield None
340
341
@classmethod
342
def __subclasshook__(cls, C):
343
if cls is Reversible:
344
return _check_methods(C, "__reversed__", "__iter__")
345
return NotImplemented
346
347
348
class Generator(Iterator):
349
350
__slots__ = ()
351
352
def __next__(self):
353
"""Return the next item from the generator.
354
When exhausted, raise StopIteration.
355
"""
356
return self.send(None)
357
358
@abstractmethod
359
def send(self, value):
360
"""Send a value into the generator.
361
Return next yielded value or raise StopIteration.
362
"""
363
raise StopIteration
364
365
@abstractmethod
366
def throw(self, typ, val=None, tb=None):
367
"""Raise an exception in the generator.
368
Return next yielded value or raise StopIteration.
369
"""
370
if val is None:
371
if tb is None:
372
raise typ
373
val = typ()
374
if tb is not None:
375
val = val.with_traceback(tb)
376
raise val
377
378
def close(self):
379
"""Raise GeneratorExit inside generator.
380
"""
381
try:
382
self.throw(GeneratorExit)
383
except (GeneratorExit, StopIteration):
384
pass
385
else:
386
raise RuntimeError("generator ignored GeneratorExit")
387
388
@classmethod
389
def __subclasshook__(cls, C):
390
if cls is Generator:
391
return _check_methods(C, '__iter__', '__next__',
392
'send', 'throw', 'close')
393
return NotImplemented
394
395
396
Generator.register(generator)
397
398
399
class Sized(metaclass=ABCMeta):
400
401
__slots__ = ()
402
403
@abstractmethod
404
def __len__(self):
405
return 0
406
407
@classmethod
408
def __subclasshook__(cls, C):
409
if cls is Sized:
410
return _check_methods(C, "__len__")
411
return NotImplemented
412
413
414
class Container(metaclass=ABCMeta):
415
416
__slots__ = ()
417
418
@abstractmethod
419
def __contains__(self, x):
420
return False
421
422
@classmethod
423
def __subclasshook__(cls, C):
424
if cls is Container:
425
return _check_methods(C, "__contains__")
426
return NotImplemented
427
428
__class_getitem__ = classmethod(GenericAlias)
429
430
431
class Collection(Sized, Iterable, Container):
432
433
__slots__ = ()
434
435
@classmethod
436
def __subclasshook__(cls, C):
437
if cls is Collection:
438
return _check_methods(C, "__len__", "__iter__", "__contains__")
439
return NotImplemented
440
441
442
class Buffer(metaclass=ABCMeta):
443
444
__slots__ = ()
445
446
@abstractmethod
447
def __buffer__(self, flags: int, /) -> memoryview:
448
raise NotImplementedError
449
450
@classmethod
451
def __subclasshook__(cls, C):
452
if cls is Buffer:
453
return _check_methods(C, "__buffer__")
454
return NotImplemented
455
456
457
class _CallableGenericAlias(GenericAlias):
458
""" Represent `Callable[argtypes, resulttype]`.
459
460
This sets ``__args__`` to a tuple containing the flattened ``argtypes``
461
followed by ``resulttype``.
462
463
Example: ``Callable[[int, str], float]`` sets ``__args__`` to
464
``(int, str, float)``.
465
"""
466
467
__slots__ = ()
468
469
def __new__(cls, origin, args):
470
if not (isinstance(args, tuple) and len(args) == 2):
471
raise TypeError(
472
"Callable must be used as Callable[[arg, ...], result].")
473
t_args, t_result = args
474
if isinstance(t_args, (tuple, list)):
475
args = (*t_args, t_result)
476
elif not _is_param_expr(t_args):
477
raise TypeError(f"Expected a list of types, an ellipsis, "
478
f"ParamSpec, or Concatenate. Got {t_args}")
479
return super().__new__(cls, origin, args)
480
481
def __repr__(self):
482
if len(self.__args__) == 2 and _is_param_expr(self.__args__[0]):
483
return super().__repr__()
484
return (f'collections.abc.Callable'
485
f'[[{", ".join([_type_repr(a) for a in self.__args__[:-1]])}], '
486
f'{_type_repr(self.__args__[-1])}]')
487
488
def __reduce__(self):
489
args = self.__args__
490
if not (len(args) == 2 and _is_param_expr(args[0])):
491
args = list(args[:-1]), args[-1]
492
return _CallableGenericAlias, (Callable, args)
493
494
def __getitem__(self, item):
495
# Called during TypeVar substitution, returns the custom subclass
496
# rather than the default types.GenericAlias object. Most of the
497
# code is copied from typing's _GenericAlias and the builtin
498
# types.GenericAlias.
499
if not isinstance(item, tuple):
500
item = (item,)
501
502
new_args = super().__getitem__(item).__args__
503
504
# args[0] occurs due to things like Z[[int, str, bool]] from PEP 612
505
if not isinstance(new_args[0], (tuple, list)):
506
t_result = new_args[-1]
507
t_args = new_args[:-1]
508
new_args = (t_args, t_result)
509
return _CallableGenericAlias(Callable, tuple(new_args))
510
511
def _is_param_expr(obj):
512
"""Checks if obj matches either a list of types, ``...``, ``ParamSpec`` or
513
``_ConcatenateGenericAlias`` from typing.py
514
"""
515
if obj is Ellipsis:
516
return True
517
if isinstance(obj, list):
518
return True
519
obj = type(obj)
520
names = ('ParamSpec', '_ConcatenateGenericAlias')
521
return obj.__module__ == 'typing' and any(obj.__name__ == name for name in names)
522
523
def _type_repr(obj):
524
"""Return the repr() of an object, special-casing types (internal helper).
525
526
Copied from :mod:`typing` since collections.abc
527
shouldn't depend on that module.
528
(Keep this roughly in sync with the typing version.)
529
"""
530
if isinstance(obj, type):
531
if obj.__module__ == 'builtins':
532
return obj.__qualname__
533
return f'{obj.__module__}.{obj.__qualname__}'
534
if obj is Ellipsis:
535
return '...'
536
if isinstance(obj, FunctionType):
537
return obj.__name__
538
return repr(obj)
539
540
541
class Callable(metaclass=ABCMeta):
542
543
__slots__ = ()
544
545
@abstractmethod
546
def __call__(self, *args, **kwds):
547
return False
548
549
@classmethod
550
def __subclasshook__(cls, C):
551
if cls is Callable:
552
return _check_methods(C, "__call__")
553
return NotImplemented
554
555
__class_getitem__ = classmethod(_CallableGenericAlias)
556
557
558
### SETS ###
559
560
561
class Set(Collection):
562
"""A set is a finite, iterable container.
563
564
This class provides concrete generic implementations of all
565
methods except for __contains__, __iter__ and __len__.
566
567
To override the comparisons (presumably for speed, as the
568
semantics are fixed), redefine __le__ and __ge__,
569
then the other operations will automatically follow suit.
570
"""
571
572
__slots__ = ()
573
574
def __le__(self, other):
575
if not isinstance(other, Set):
576
return NotImplemented
577
if len(self) > len(other):
578
return False
579
for elem in self:
580
if elem not in other:
581
return False
582
return True
583
584
def __lt__(self, other):
585
if not isinstance(other, Set):
586
return NotImplemented
587
return len(self) < len(other) and self.__le__(other)
588
589
def __gt__(self, other):
590
if not isinstance(other, Set):
591
return NotImplemented
592
return len(self) > len(other) and self.__ge__(other)
593
594
def __ge__(self, other):
595
if not isinstance(other, Set):
596
return NotImplemented
597
if len(self) < len(other):
598
return False
599
for elem in other:
600
if elem not in self:
601
return False
602
return True
603
604
def __eq__(self, other):
605
if not isinstance(other, Set):
606
return NotImplemented
607
return len(self) == len(other) and self.__le__(other)
608
609
@classmethod
610
def _from_iterable(cls, it):
611
'''Construct an instance of the class from any iterable input.
612
613
Must override this method if the class constructor signature
614
does not accept an iterable for an input.
615
'''
616
return cls(it)
617
618
def __and__(self, other):
619
if not isinstance(other, Iterable):
620
return NotImplemented
621
return self._from_iterable(value for value in other if value in self)
622
623
__rand__ = __and__
624
625
def isdisjoint(self, other):
626
'Return True if two sets have a null intersection.'
627
for value in other:
628
if value in self:
629
return False
630
return True
631
632
def __or__(self, other):
633
if not isinstance(other, Iterable):
634
return NotImplemented
635
chain = (e for s in (self, other) for e in s)
636
return self._from_iterable(chain)
637
638
__ror__ = __or__
639
640
def __sub__(self, other):
641
if not isinstance(other, Set):
642
if not isinstance(other, Iterable):
643
return NotImplemented
644
other = self._from_iterable(other)
645
return self._from_iterable(value for value in self
646
if value not in other)
647
648
def __rsub__(self, other):
649
if not isinstance(other, Set):
650
if not isinstance(other, Iterable):
651
return NotImplemented
652
other = self._from_iterable(other)
653
return self._from_iterable(value for value in other
654
if value not in self)
655
656
def __xor__(self, other):
657
if not isinstance(other, Set):
658
if not isinstance(other, Iterable):
659
return NotImplemented
660
other = self._from_iterable(other)
661
return (self - other) | (other - self)
662
663
__rxor__ = __xor__
664
665
def _hash(self):
666
"""Compute the hash value of a set.
667
668
Note that we don't define __hash__: not all sets are hashable.
669
But if you define a hashable set type, its __hash__ should
670
call this function.
671
672
This must be compatible __eq__.
673
674
All sets ought to compare equal if they contain the same
675
elements, regardless of how they are implemented, and
676
regardless of the order of the elements; so there's not much
677
freedom for __eq__ or __hash__. We match the algorithm used
678
by the built-in frozenset type.
679
"""
680
MAX = sys.maxsize
681
MASK = 2 * MAX + 1
682
n = len(self)
683
h = 1927868237 * (n + 1)
684
h &= MASK
685
for x in self:
686
hx = hash(x)
687
h ^= (hx ^ (hx << 16) ^ 89869747) * 3644798167
688
h &= MASK
689
h ^= (h >> 11) ^ (h >> 25)
690
h = h * 69069 + 907133923
691
h &= MASK
692
if h > MAX:
693
h -= MASK + 1
694
if h == -1:
695
h = 590923713
696
return h
697
698
699
Set.register(frozenset)
700
701
702
class MutableSet(Set):
703
"""A mutable set is a finite, iterable container.
704
705
This class provides concrete generic implementations of all
706
methods except for __contains__, __iter__, __len__,
707
add(), and discard().
708
709
To override the comparisons (presumably for speed, as the
710
semantics are fixed), all you have to do is redefine __le__ and
711
then the other operations will automatically follow suit.
712
"""
713
714
__slots__ = ()
715
716
@abstractmethod
717
def add(self, value):
718
"""Add an element."""
719
raise NotImplementedError
720
721
@abstractmethod
722
def discard(self, value):
723
"""Remove an element. Do not raise an exception if absent."""
724
raise NotImplementedError
725
726
def remove(self, value):
727
"""Remove an element. If not a member, raise a KeyError."""
728
if value not in self:
729
raise KeyError(value)
730
self.discard(value)
731
732
def pop(self):
733
"""Return the popped value. Raise KeyError if empty."""
734
it = iter(self)
735
try:
736
value = next(it)
737
except StopIteration:
738
raise KeyError from None
739
self.discard(value)
740
return value
741
742
def clear(self):
743
"""This is slow (creates N new iterators!) but effective."""
744
try:
745
while True:
746
self.pop()
747
except KeyError:
748
pass
749
750
def __ior__(self, it):
751
for value in it:
752
self.add(value)
753
return self
754
755
def __iand__(self, it):
756
for value in (self - it):
757
self.discard(value)
758
return self
759
760
def __ixor__(self, it):
761
if it is self:
762
self.clear()
763
else:
764
if not isinstance(it, Set):
765
it = self._from_iterable(it)
766
for value in it:
767
if value in self:
768
self.discard(value)
769
else:
770
self.add(value)
771
return self
772
773
def __isub__(self, it):
774
if it is self:
775
self.clear()
776
else:
777
for value in it:
778
self.discard(value)
779
return self
780
781
782
MutableSet.register(set)
783
784
785
### MAPPINGS ###
786
787
class Mapping(Collection):
788
"""A Mapping is a generic container for associating key/value
789
pairs.
790
791
This class provides concrete generic implementations of all
792
methods except for __getitem__, __iter__, and __len__.
793
"""
794
795
__slots__ = ()
796
797
# Tell ABCMeta.__new__ that this class should have TPFLAGS_MAPPING set.
798
__abc_tpflags__ = 1 << 6 # Py_TPFLAGS_MAPPING
799
800
@abstractmethod
801
def __getitem__(self, key):
802
raise KeyError
803
804
def get(self, key, default=None):
805
'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.'
806
try:
807
return self[key]
808
except KeyError:
809
return default
810
811
def __contains__(self, key):
812
try:
813
self[key]
814
except KeyError:
815
return False
816
else:
817
return True
818
819
def keys(self):
820
"D.keys() -> a set-like object providing a view on D's keys"
821
return KeysView(self)
822
823
def items(self):
824
"D.items() -> a set-like object providing a view on D's items"
825
return ItemsView(self)
826
827
def values(self):
828
"D.values() -> an object providing a view on D's values"
829
return ValuesView(self)
830
831
def __eq__(self, other):
832
if not isinstance(other, Mapping):
833
return NotImplemented
834
return dict(self.items()) == dict(other.items())
835
836
__reversed__ = None
837
838
Mapping.register(mappingproxy)
839
840
841
class MappingView(Sized):
842
843
__slots__ = '_mapping',
844
845
def __init__(self, mapping):
846
self._mapping = mapping
847
848
def __len__(self):
849
return len(self._mapping)
850
851
def __repr__(self):
852
return '{0.__class__.__name__}({0._mapping!r})'.format(self)
853
854
__class_getitem__ = classmethod(GenericAlias)
855
856
857
class KeysView(MappingView, Set):
858
859
__slots__ = ()
860
861
@classmethod
862
def _from_iterable(cls, it):
863
return set(it)
864
865
def __contains__(self, key):
866
return key in self._mapping
867
868
def __iter__(self):
869
yield from self._mapping
870
871
872
KeysView.register(dict_keys)
873
874
875
class ItemsView(MappingView, Set):
876
877
__slots__ = ()
878
879
@classmethod
880
def _from_iterable(cls, it):
881
return set(it)
882
883
def __contains__(self, item):
884
key, value = item
885
try:
886
v = self._mapping[key]
887
except KeyError:
888
return False
889
else:
890
return v is value or v == value
891
892
def __iter__(self):
893
for key in self._mapping:
894
yield (key, self._mapping[key])
895
896
897
ItemsView.register(dict_items)
898
899
900
class ValuesView(MappingView, Collection):
901
902
__slots__ = ()
903
904
def __contains__(self, value):
905
for key in self._mapping:
906
v = self._mapping[key]
907
if v is value or v == value:
908
return True
909
return False
910
911
def __iter__(self):
912
for key in self._mapping:
913
yield self._mapping[key]
914
915
916
ValuesView.register(dict_values)
917
918
919
class MutableMapping(Mapping):
920
"""A MutableMapping is a generic container for associating
921
key/value pairs.
922
923
This class provides concrete generic implementations of all
924
methods except for __getitem__, __setitem__, __delitem__,
925
__iter__, and __len__.
926
"""
927
928
__slots__ = ()
929
930
@abstractmethod
931
def __setitem__(self, key, value):
932
raise KeyError
933
934
@abstractmethod
935
def __delitem__(self, key):
936
raise KeyError
937
938
__marker = object()
939
940
def pop(self, key, default=__marker):
941
'''D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
942
If key is not found, d is returned if given, otherwise KeyError is raised.
943
'''
944
try:
945
value = self[key]
946
except KeyError:
947
if default is self.__marker:
948
raise
949
return default
950
else:
951
del self[key]
952
return value
953
954
def popitem(self):
955
'''D.popitem() -> (k, v), remove and return some (key, value) pair
956
as a 2-tuple; but raise KeyError if D is empty.
957
'''
958
try:
959
key = next(iter(self))
960
except StopIteration:
961
raise KeyError from None
962
value = self[key]
963
del self[key]
964
return key, value
965
966
def clear(self):
967
'D.clear() -> None. Remove all items from D.'
968
try:
969
while True:
970
self.popitem()
971
except KeyError:
972
pass
973
974
def update(self, other=(), /, **kwds):
975
''' D.update([E, ]**F) -> None. Update D from mapping/iterable E and F.
976
If E present and has a .keys() method, does: for k in E: D[k] = E[k]
977
If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v
978
In either case, this is followed by: for k, v in F.items(): D[k] = v
979
'''
980
if isinstance(other, Mapping):
981
for key in other:
982
self[key] = other[key]
983
elif hasattr(other, "keys"):
984
for key in other.keys():
985
self[key] = other[key]
986
else:
987
for key, value in other:
988
self[key] = value
989
for key, value in kwds.items():
990
self[key] = value
991
992
def setdefault(self, key, default=None):
993
'D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D'
994
try:
995
return self[key]
996
except KeyError:
997
self[key] = default
998
return default
999
1000
1001
MutableMapping.register(dict)
1002
1003
1004
### SEQUENCES ###
1005
1006
class Sequence(Reversible, Collection):
1007
"""All the operations on a read-only sequence.
1008
1009
Concrete subclasses must override __new__ or __init__,
1010
__getitem__, and __len__.
1011
"""
1012
1013
__slots__ = ()
1014
1015
# Tell ABCMeta.__new__ that this class should have TPFLAGS_SEQUENCE set.
1016
__abc_tpflags__ = 1 << 5 # Py_TPFLAGS_SEQUENCE
1017
1018
@abstractmethod
1019
def __getitem__(self, index):
1020
raise IndexError
1021
1022
def __iter__(self):
1023
i = 0
1024
try:
1025
while True:
1026
v = self[i]
1027
yield v
1028
i += 1
1029
except IndexError:
1030
return
1031
1032
def __contains__(self, value):
1033
for v in self:
1034
if v is value or v == value:
1035
return True
1036
return False
1037
1038
def __reversed__(self):
1039
for i in reversed(range(len(self))):
1040
yield self[i]
1041
1042
def index(self, value, start=0, stop=None):
1043
'''S.index(value, [start, [stop]]) -> integer -- return first index of value.
1044
Raises ValueError if the value is not present.
1045
1046
Supporting start and stop arguments is optional, but
1047
recommended.
1048
'''
1049
if start is not None and start < 0:
1050
start = max(len(self) + start, 0)
1051
if stop is not None and stop < 0:
1052
stop += len(self)
1053
1054
i = start
1055
while stop is None or i < stop:
1056
try:
1057
v = self[i]
1058
except IndexError:
1059
break
1060
if v is value or v == value:
1061
return i
1062
i += 1
1063
raise ValueError
1064
1065
def count(self, value):
1066
'S.count(value) -> integer -- return number of occurrences of value'
1067
return sum(1 for v in self if v is value or v == value)
1068
1069
Sequence.register(tuple)
1070
Sequence.register(str)
1071
Sequence.register(range)
1072
Sequence.register(memoryview)
1073
1074
class _DeprecateByteStringMeta(ABCMeta):
1075
def __new__(cls, name, bases, namespace, **kwargs):
1076
if name != "ByteString":
1077
import warnings
1078
1079
warnings._deprecated(
1080
"collections.abc.ByteString",
1081
remove=(3, 14),
1082
)
1083
return super().__new__(cls, name, bases, namespace, **kwargs)
1084
1085
def __instancecheck__(cls, instance):
1086
import warnings
1087
1088
warnings._deprecated(
1089
"collections.abc.ByteString",
1090
remove=(3, 14),
1091
)
1092
return super().__instancecheck__(instance)
1093
1094
class ByteString(Sequence, metaclass=_DeprecateByteStringMeta):
1095
"""This unifies bytes and bytearray.
1096
1097
XXX Should add all their methods.
1098
"""
1099
1100
__slots__ = ()
1101
1102
ByteString.register(bytes)
1103
ByteString.register(bytearray)
1104
1105
1106
class MutableSequence(Sequence):
1107
"""All the operations on a read-write sequence.
1108
1109
Concrete subclasses must provide __new__ or __init__,
1110
__getitem__, __setitem__, __delitem__, __len__, and insert().
1111
"""
1112
1113
__slots__ = ()
1114
1115
@abstractmethod
1116
def __setitem__(self, index, value):
1117
raise IndexError
1118
1119
@abstractmethod
1120
def __delitem__(self, index):
1121
raise IndexError
1122
1123
@abstractmethod
1124
def insert(self, index, value):
1125
'S.insert(index, value) -- insert value before index'
1126
raise IndexError
1127
1128
def append(self, value):
1129
'S.append(value) -- append value to the end of the sequence'
1130
self.insert(len(self), value)
1131
1132
def clear(self):
1133
'S.clear() -> None -- remove all items from S'
1134
try:
1135
while True:
1136
self.pop()
1137
except IndexError:
1138
pass
1139
1140
def reverse(self):
1141
'S.reverse() -- reverse *IN PLACE*'
1142
n = len(self)
1143
for i in range(n//2):
1144
self[i], self[n-i-1] = self[n-i-1], self[i]
1145
1146
def extend(self, values):
1147
'S.extend(iterable) -- extend sequence by appending elements from the iterable'
1148
if values is self:
1149
values = list(values)
1150
for v in values:
1151
self.append(v)
1152
1153
def pop(self, index=-1):
1154
'''S.pop([index]) -> item -- remove and return item at index (default last).
1155
Raise IndexError if list is empty or index is out of range.
1156
'''
1157
v = self[index]
1158
del self[index]
1159
return v
1160
1161
def remove(self, value):
1162
'''S.remove(value) -- remove first occurrence of value.
1163
Raise ValueError if the value is not present.
1164
'''
1165
del self[self.index(value)]
1166
1167
def __iadd__(self, values):
1168
self.extend(values)
1169
return self
1170
1171
1172
MutableSequence.register(list)
1173
MutableSequence.register(bytearray) # Multiply inheriting, see ByteString
1174
1175