Coverage for Lib/_collections_abc.py: 19%

662 statements  

« prev     ^ index     » next       coverage.py v7.2.1, created at 2023-03-15 12:34 +0300

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 

6Unit 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 

35from abc import ABCMeta, abstractmethod 

36import sys 

37 

38GenericAlias = type(list[int]) 

39EllipsisType = type(...) 

40def _f(): pass 

41FunctionType = type(_f) 

42del _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", 

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. 

68bytes_iterator = type(iter(b'')) 

69bytearray_iterator = type(iter(bytearray())) 

70#callable_iterator = ??? 

71dict_keyiterator = type(iter({}.keys())) 

72dict_valueiterator = type(iter({}.values())) 

73dict_itemiterator = type(iter({}.items())) 

74list_iterator = type(iter([])) 

75list_reverseiterator = type(iter(reversed([]))) 

76range_iterator = type(iter(range(0))) 

77longrange_iterator = type(iter(range(1 << 1000))) 

78set_iterator = type(iter(set())) 

79str_iterator = type(iter("")) 

80tuple_iterator = type(iter(())) 

81zip_iterator = type(iter(zip())) 

82## views ## 

83dict_keys = type({}.keys()) 

84dict_values = type({}.values()) 

85dict_items = type({}.items()) 

86## misc ## 

87mappingproxy = type(type.__dict__) 

88generator = type((lambda: (yield))()) 

89## coroutine ## 

90async def _coro(): pass 

91_coro = _coro() 

92coroutine = type(_coro) 

93_coro.close() # Prevent ResourceWarning 

94del _coro 

95## asynchronous generator ## 

96async def _ag(): yield 

97_ag = _ag() 

98async_generator = type(_ag) 

99del _ag 

100 

101 

102### ONE-TRICK PONIES ### 

103 

104def _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 

116class 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: 126 ↛ 128line 126 didn't jump to line 128, because the condition on line 126 was never false

127 return _check_methods(C, "__hash__") 

128 return NotImplemented 

129 

130 

131class 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 

148class 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: 184 ↛ 186line 184 didn't jump to line 186, because the condition on line 184 was never false

185 return _check_methods(C, '__await__', 'send', 'throw', 'close') 

186 return NotImplemented 

187 

188 

189Coroutine.register(coroutine) 

190 

191 

192class 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: 202 ↛ 204line 202 didn't jump to line 204, because the condition on line 202 was never false

203 return _check_methods(C, "__aiter__") 

204 return NotImplemented 

205 

206 __class_getitem__ = classmethod(GenericAlias) 

207 

208 

209class 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 

228class 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 

276AsyncGenerator.register(async_generator) 

277 

278 

279class 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 

297class 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: 311 ↛ 313line 311 didn't jump to line 313, because the condition on line 311 was never false

312 return _check_methods(C, '__iter__', '__next__') 

313 return NotImplemented 

314 

315 

316Iterator.register(bytes_iterator) 

317Iterator.register(bytearray_iterator) 

318#Iterator.register(callable_iterator) 

319Iterator.register(dict_keyiterator) 

320Iterator.register(dict_valueiterator) 

321Iterator.register(dict_itemiterator) 

322Iterator.register(list_iterator) 

323Iterator.register(list_reverseiterator) 

324Iterator.register(range_iterator) 

325Iterator.register(longrange_iterator) 

326Iterator.register(set_iterator) 

327Iterator.register(str_iterator) 

328Iterator.register(tuple_iterator) 

329Iterator.register(zip_iterator) 

330 

331 

332class 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 

348class 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 

396Generator.register(generator) 

397 

398 

399class 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 

414class 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 

431class 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 

442class _CallableGenericAlias(GenericAlias): 

443 """ Represent `Callable[argtypes, resulttype]`. 

444 

445 This sets ``__args__`` to a tuple containing the flattened ``argtypes`` 

446 followed by ``resulttype``. 

447 

448 Example: ``Callable[[int, str], float]`` sets ``__args__`` to 

449 ``(int, str, float)``. 

450 """ 

451 

452 __slots__ = () 

453 

454 def __new__(cls, origin, args): 

455 if not (isinstance(args, tuple) and len(args) == 2): 

456 raise TypeError( 

457 "Callable must be used as Callable[[arg, ...], result].") 

458 t_args, t_result = args 

459 if isinstance(t_args, (tuple, list)): 

460 args = (*t_args, t_result) 

461 elif not _is_param_expr(t_args): 461 ↛ 462line 461 didn't jump to line 462, because the condition on line 461 was never true

462 raise TypeError(f"Expected a list of types, an ellipsis, " 

463 f"ParamSpec, or Concatenate. Got {t_args}") 

464 return super().__new__(cls, origin, args) 

465 

466 def __repr__(self): 

467 if len(self.__args__) == 2 and _is_param_expr(self.__args__[0]): 

468 return super().__repr__() 

469 return (f'collections.abc.Callable' 

470 f'[[{", ".join([_type_repr(a) for a in self.__args__[:-1]])}], ' 

471 f'{_type_repr(self.__args__[-1])}]') 

472 

473 def __reduce__(self): 

474 args = self.__args__ 

475 if not (len(args) == 2 and _is_param_expr(args[0])): 475 ↛ 477line 475 didn't jump to line 477, because the condition on line 475 was never false

476 args = list(args[:-1]), args[-1] 

477 return _CallableGenericAlias, (Callable, args) 

478 

479 def __getitem__(self, item): 

480 # Called during TypeVar substitution, returns the custom subclass 

481 # rather than the default types.GenericAlias object. Most of the 

482 # code is copied from typing's _GenericAlias and the builtin 

483 # types.GenericAlias. 

484 

485 if not isinstance(item, tuple): 

486 item = (item,) 

487 # A special case in PEP 612 where if X = Callable[P, int], 

488 # then X[int, str] == X[[int, str]]. 

489 if (len(self.__parameters__) == 1 

490 and _is_param_expr(self.__parameters__[0]) 

491 and item and not _is_param_expr(item[0])): 

492 item = (item,) 

493 

494 new_args = super().__getitem__(item).__args__ 

495 

496 # args[0] occurs due to things like Z[[int, str, bool]] from PEP 612 

497 if not isinstance(new_args[0], (tuple, list)): 

498 t_result = new_args[-1] 

499 t_args = new_args[:-1] 

500 new_args = (t_args, t_result) 

501 return _CallableGenericAlias(Callable, tuple(new_args)) 

502 

503def _is_param_expr(obj): 

504 """Checks if obj matches either a list of types, ``...``, ``ParamSpec`` or 

505 ``_ConcatenateGenericAlias`` from typing.py 

506 """ 

507 if obj is Ellipsis: 

508 return True 

509 if isinstance(obj, list): 

510 return True 

511 obj = type(obj) 

512 names = ('ParamSpec', '_ConcatenateGenericAlias') 

513 return obj.__module__ == 'typing' and any(obj.__name__ == name for name in names) 

514 

515def _type_repr(obj): 

516 """Return the repr() of an object, special-casing types (internal helper). 

517 

518 Copied from :mod:`typing` since collections.abc 

519 shouldn't depend on that module. 

520 """ 

521 if isinstance(obj, GenericAlias): 

522 return repr(obj) 

523 if isinstance(obj, type): 

524 if obj.__module__ == 'builtins': 

525 return obj.__qualname__ 

526 return f'{obj.__module__}.{obj.__qualname__}' 

527 if obj is Ellipsis: 527 ↛ 528line 527 didn't jump to line 528, because the condition on line 527 was never true

528 return '...' 

529 if isinstance(obj, FunctionType): 529 ↛ 530line 529 didn't jump to line 530, because the condition on line 529 was never true

530 return obj.__name__ 

531 return repr(obj) 

532 

533 

534class Callable(metaclass=ABCMeta): 

535 

536 __slots__ = () 

537 

538 @abstractmethod 

539 def __call__(self, *args, **kwds): 

540 return False 

541 

542 @classmethod 

543 def __subclasshook__(cls, C): 

544 if cls is Callable: 544 ↛ 546line 544 didn't jump to line 546, because the condition on line 544 was never false

545 return _check_methods(C, "__call__") 

546 return NotImplemented 

547 

548 __class_getitem__ = classmethod(_CallableGenericAlias) 

549 

550 

551### SETS ### 

552 

553 

554class Set(Collection): 

555 """A set is a finite, iterable container. 

556 

557 This class provides concrete generic implementations of all 

558 methods except for __contains__, __iter__ and __len__. 

559 

560 To override the comparisons (presumably for speed, as the 

561 semantics are fixed), redefine __le__ and __ge__, 

562 then the other operations will automatically follow suit. 

563 """ 

564 

565 __slots__ = () 

566 

567 def __le__(self, other): 

568 if not isinstance(other, Set): 

569 return NotImplemented 

570 if len(self) > len(other): 

571 return False 

572 for elem in self: 

573 if elem not in other: 

574 return False 

575 return True 

576 

577 def __lt__(self, other): 

578 if not isinstance(other, Set): 

579 return NotImplemented 

580 return len(self) < len(other) and self.__le__(other) 

581 

582 def __gt__(self, other): 

583 if not isinstance(other, Set): 

584 return NotImplemented 

585 return len(self) > len(other) and self.__ge__(other) 

586 

587 def __ge__(self, other): 

588 if not isinstance(other, Set): 

589 return NotImplemented 

590 if len(self) < len(other): 

591 return False 

592 for elem in other: 

593 if elem not in self: 

594 return False 

595 return True 

596 

597 def __eq__(self, other): 

598 if not isinstance(other, Set): 

599 return NotImplemented 

600 return len(self) == len(other) and self.__le__(other) 

601 

602 @classmethod 

603 def _from_iterable(cls, it): 

604 '''Construct an instance of the class from any iterable input. 

605 

606 Must override this method if the class constructor signature 

607 does not accept an iterable for an input. 

608 ''' 

609 return cls(it) 

610 

611 def __and__(self, other): 

612 if not isinstance(other, Iterable): 

613 return NotImplemented 

614 return self._from_iterable(value for value in other if value in self) 

615 

616 __rand__ = __and__ 

617 

618 def isdisjoint(self, other): 

619 'Return True if two sets have a null intersection.' 

620 for value in other: 

621 if value in self: 

622 return False 

623 return True 

624 

625 def __or__(self, other): 

626 if not isinstance(other, Iterable): 

627 return NotImplemented 

628 chain = (e for s in (self, other) for e in s) 

629 return self._from_iterable(chain) 

630 

631 __ror__ = __or__ 

632 

633 def __sub__(self, other): 

634 if not isinstance(other, Set): 

635 if not isinstance(other, Iterable): 

636 return NotImplemented 

637 other = self._from_iterable(other) 

638 return self._from_iterable(value for value in self 

639 if value not in other) 

640 

641 def __rsub__(self, other): 

642 if not isinstance(other, Set): 

643 if not isinstance(other, Iterable): 

644 return NotImplemented 

645 other = self._from_iterable(other) 

646 return self._from_iterable(value for value in other 

647 if value not in self) 

648 

649 def __xor__(self, other): 

650 if not isinstance(other, Set): 

651 if not isinstance(other, Iterable): 

652 return NotImplemented 

653 other = self._from_iterable(other) 

654 return (self - other) | (other - self) 

655 

656 __rxor__ = __xor__ 

657 

658 def _hash(self): 

659 """Compute the hash value of a set. 

660 

661 Note that we don't define __hash__: not all sets are hashable. 

662 But if you define a hashable set type, its __hash__ should 

663 call this function. 

664 

665 This must be compatible __eq__. 

666 

667 All sets ought to compare equal if they contain the same 

668 elements, regardless of how they are implemented, and 

669 regardless of the order of the elements; so there's not much 

670 freedom for __eq__ or __hash__. We match the algorithm used 

671 by the built-in frozenset type. 

672 """ 

673 MAX = sys.maxsize 

674 MASK = 2 * MAX + 1 

675 n = len(self) 

676 h = 1927868237 * (n + 1) 

677 h &= MASK 

678 for x in self: 

679 hx = hash(x) 

680 h ^= (hx ^ (hx << 16) ^ 89869747) * 3644798167 

681 h &= MASK 

682 h ^= (h >> 11) ^ (h >> 25) 

683 h = h * 69069 + 907133923 

684 h &= MASK 

685 if h > MAX: 

686 h -= MASK + 1 

687 if h == -1: 

688 h = 590923713 

689 return h 

690 

691 

692Set.register(frozenset) 

693 

694 

695class MutableSet(Set): 

696 """A mutable set is a finite, iterable container. 

697 

698 This class provides concrete generic implementations of all 

699 methods except for __contains__, __iter__, __len__, 

700 add(), and discard(). 

701 

702 To override the comparisons (presumably for speed, as the 

703 semantics are fixed), all you have to do is redefine __le__ and 

704 then the other operations will automatically follow suit. 

705 """ 

706 

707 __slots__ = () 

708 

709 @abstractmethod 

710 def add(self, value): 

711 """Add an element.""" 

712 raise NotImplementedError 

713 

714 @abstractmethod 

715 def discard(self, value): 

716 """Remove an element. Do not raise an exception if absent.""" 

717 raise NotImplementedError 

718 

719 def remove(self, value): 

720 """Remove an element. If not a member, raise a KeyError.""" 

721 if value not in self: 

722 raise KeyError(value) 

723 self.discard(value) 

724 

725 def pop(self): 

726 """Return the popped value. Raise KeyError if empty.""" 

727 it = iter(self) 

728 try: 

729 value = next(it) 

730 except StopIteration: 

731 raise KeyError from None 

732 self.discard(value) 

733 return value 

734 

735 def clear(self): 

736 """This is slow (creates N new iterators!) but effective.""" 

737 try: 

738 while True: 

739 self.pop() 

740 except KeyError: 

741 pass 

742 

743 def __ior__(self, it): 

744 for value in it: 

745 self.add(value) 

746 return self 

747 

748 def __iand__(self, it): 

749 for value in (self - it): 

750 self.discard(value) 

751 return self 

752 

753 def __ixor__(self, it): 

754 if it is self: 

755 self.clear() 

756 else: 

757 if not isinstance(it, Set): 

758 it = self._from_iterable(it) 

759 for value in it: 

760 if value in self: 

761 self.discard(value) 

762 else: 

763 self.add(value) 

764 return self 

765 

766 def __isub__(self, it): 

767 if it is self: 

768 self.clear() 

769 else: 

770 for value in it: 

771 self.discard(value) 

772 return self 

773 

774 

775MutableSet.register(set) 

776 

777 

778### MAPPINGS ### 

779 

780class Mapping(Collection): 

781 """A Mapping is a generic container for associating key/value 

782 pairs. 

783 

784 This class provides concrete generic implementations of all 

785 methods except for __getitem__, __iter__, and __len__. 

786 """ 

787 

788 __slots__ = () 

789 

790 # Tell ABCMeta.__new__ that this class should have TPFLAGS_MAPPING set. 

791 __abc_tpflags__ = 1 << 6 # Py_TPFLAGS_MAPPING 

792 

793 @abstractmethod 

794 def __getitem__(self, key): 

795 raise KeyError 

796 

797 def get(self, key, default=None): 

798 'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.' 

799 try: 

800 return self[key] 

801 except KeyError: 

802 return default 

803 

804 def __contains__(self, key): 

805 try: 

806 self[key] 

807 except KeyError: 

808 return False 

809 else: 

810 return True 

811 

812 def keys(self): 

813 "D.keys() -> a set-like object providing a view on D's keys" 

814 return KeysView(self) 

815 

816 def items(self): 

817 "D.items() -> a set-like object providing a view on D's items" 

818 return ItemsView(self) 

819 

820 def values(self): 

821 "D.values() -> an object providing a view on D's values" 

822 return ValuesView(self) 

823 

824 def __eq__(self, other): 

825 if not isinstance(other, Mapping): 825 ↛ 826line 825 didn't jump to line 826, because the condition on line 825 was never true

826 return NotImplemented 

827 return dict(self.items()) == dict(other.items()) 

828 

829 __reversed__ = None 

830 

831Mapping.register(mappingproxy) 

832 

833 

834class MappingView(Sized): 

835 

836 __slots__ = '_mapping', 

837 

838 def __init__(self, mapping): 

839 self._mapping = mapping 

840 

841 def __len__(self): 

842 return len(self._mapping) 

843 

844 def __repr__(self): 

845 return '{0.__class__.__name__}({0._mapping!r})'.format(self) 

846 

847 __class_getitem__ = classmethod(GenericAlias) 

848 

849 

850class KeysView(MappingView, Set): 

851 

852 __slots__ = () 

853 

854 @classmethod 

855 def _from_iterable(cls, it): 

856 return set(it) 

857 

858 def __contains__(self, key): 

859 return key in self._mapping 

860 

861 def __iter__(self): 

862 yield from self._mapping 

863 

864 

865KeysView.register(dict_keys) 

866 

867 

868class ItemsView(MappingView, Set): 

869 

870 __slots__ = () 

871 

872 @classmethod 

873 def _from_iterable(cls, it): 

874 return set(it) 

875 

876 def __contains__(self, item): 

877 key, value = item 

878 try: 

879 v = self._mapping[key] 

880 except KeyError: 

881 return False 

882 else: 

883 return v is value or v == value 

884 

885 def __iter__(self): 

886 for key in self._mapping: 

887 yield (key, self._mapping[key]) 

888 

889 

890ItemsView.register(dict_items) 

891 

892 

893class ValuesView(MappingView, Collection): 

894 

895 __slots__ = () 

896 

897 def __contains__(self, value): 

898 for key in self._mapping: 

899 v = self._mapping[key] 

900 if v is value or v == value: 

901 return True 

902 return False 

903 

904 def __iter__(self): 

905 for key in self._mapping: 

906 yield self._mapping[key] 

907 

908 

909ValuesView.register(dict_values) 

910 

911 

912class MutableMapping(Mapping): 

913 """A MutableMapping is a generic container for associating 

914 key/value pairs. 

915 

916 This class provides concrete generic implementations of all 

917 methods except for __getitem__, __setitem__, __delitem__, 

918 __iter__, and __len__. 

919 """ 

920 

921 __slots__ = () 

922 

923 @abstractmethod 

924 def __setitem__(self, key, value): 

925 raise KeyError 

926 

927 @abstractmethod 

928 def __delitem__(self, key): 

929 raise KeyError 

930 

931 __marker = object() 

932 

933 def pop(self, key, default=__marker): 

934 '''D.pop(k[,d]) -> v, remove specified key and return the corresponding value. 

935 If key is not found, d is returned if given, otherwise KeyError is raised. 

936 ''' 

937 try: 

938 value = self[key] 

939 except KeyError: 

940 if default is self.__marker: 

941 raise 

942 return default 

943 else: 

944 del self[key] 

945 return value 

946 

947 def popitem(self): 

948 '''D.popitem() -> (k, v), remove and return some (key, value) pair 

949 as a 2-tuple; but raise KeyError if D is empty. 

950 ''' 

951 try: 

952 key = next(iter(self)) 

953 except StopIteration: 

954 raise KeyError from None 

955 value = self[key] 

956 del self[key] 

957 return key, value 

958 

959 def clear(self): 

960 'D.clear() -> None. Remove all items from D.' 

961 try: 

962 while True: 

963 self.popitem() 

964 except KeyError: 

965 pass 

966 

967 def update(self, other=(), /, **kwds): 

968 ''' D.update([E, ]**F) -> None. Update D from mapping/iterable E and F. 

969 If E present and has a .keys() method, does: for k in E: D[k] = E[k] 

970 If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v 

971 In either case, this is followed by: for k, v in F.items(): D[k] = v 

972 ''' 

973 if isinstance(other, Mapping): 973 ↛ 974line 973 didn't jump to line 974, because the condition on line 973 was never true

974 for key in other: 

975 self[key] = other[key] 

976 elif hasattr(other, "keys"): 976 ↛ 977line 976 didn't jump to line 977, because the condition on line 976 was never true

977 for key in other.keys(): 

978 self[key] = other[key] 

979 else: 

980 for key, value in other: 980 ↛ 981line 980 didn't jump to line 981, because the loop on line 980 never started

981 self[key] = value 

982 for key, value in kwds.items(): 982 ↛ 983line 982 didn't jump to line 983, because the loop on line 982 never started

983 self[key] = value 

984 

985 def setdefault(self, key, default=None): 

986 'D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D' 

987 try: 

988 return self[key] 

989 except KeyError: 

990 self[key] = default 

991 return default 

992 

993 

994MutableMapping.register(dict) 

995 

996 

997### SEQUENCES ### 

998 

999class Sequence(Reversible, Collection): 

1000 """All the operations on a read-only sequence. 

1001 

1002 Concrete subclasses must override __new__ or __init__, 

1003 __getitem__, and __len__. 

1004 """ 

1005 

1006 __slots__ = () 

1007 

1008 # Tell ABCMeta.__new__ that this class should have TPFLAGS_SEQUENCE set. 

1009 __abc_tpflags__ = 1 << 5 # Py_TPFLAGS_SEQUENCE 

1010 

1011 @abstractmethod 

1012 def __getitem__(self, index): 

1013 raise IndexError 

1014 

1015 def __iter__(self): 

1016 i = 0 

1017 try: 

1018 while True: 

1019 v = self[i] 

1020 yield v 

1021 i += 1 

1022 except IndexError: 

1023 return 

1024 

1025 def __contains__(self, value): 

1026 for v in self: 

1027 if v is value or v == value: 

1028 return True 

1029 return False 

1030 

1031 def __reversed__(self): 

1032 for i in reversed(range(len(self))): 

1033 yield self[i] 

1034 

1035 def index(self, value, start=0, stop=None): 

1036 '''S.index(value, [start, [stop]]) -> integer -- return first index of value. 

1037 Raises ValueError if the value is not present. 

1038 

1039 Supporting start and stop arguments is optional, but 

1040 recommended. 

1041 ''' 

1042 if start is not None and start < 0: 

1043 start = max(len(self) + start, 0) 

1044 if stop is not None and stop < 0: 

1045 stop += len(self) 

1046 

1047 i = start 

1048 while stop is None or i < stop: 

1049 try: 

1050 v = self[i] 

1051 except IndexError: 

1052 break 

1053 if v is value or v == value: 

1054 return i 

1055 i += 1 

1056 raise ValueError 

1057 

1058 def count(self, value): 

1059 'S.count(value) -> integer -- return number of occurrences of value' 

1060 return sum(1 for v in self if v is value or v == value) 

1061 

1062Sequence.register(tuple) 

1063Sequence.register(str) 

1064Sequence.register(range) 

1065Sequence.register(memoryview) 

1066 

1067 

1068class ByteString(Sequence): 

1069 """This unifies bytes and bytearray. 

1070 

1071 XXX Should add all their methods. 

1072 """ 

1073 

1074 __slots__ = () 

1075 

1076ByteString.register(bytes) 

1077ByteString.register(bytearray) 

1078 

1079 

1080class MutableSequence(Sequence): 

1081 """All the operations on a read-write sequence. 

1082 

1083 Concrete subclasses must provide __new__ or __init__, 

1084 __getitem__, __setitem__, __delitem__, __len__, and insert(). 

1085 """ 

1086 

1087 __slots__ = () 

1088 

1089 @abstractmethod 

1090 def __setitem__(self, index, value): 

1091 raise IndexError 

1092 

1093 @abstractmethod 

1094 def __delitem__(self, index): 

1095 raise IndexError 

1096 

1097 @abstractmethod 

1098 def insert(self, index, value): 

1099 'S.insert(index, value) -- insert value before index' 

1100 raise IndexError 

1101 

1102 def append(self, value): 

1103 'S.append(value) -- append value to the end of the sequence' 

1104 self.insert(len(self), value) 

1105 

1106 def clear(self): 

1107 'S.clear() -> None -- remove all items from S' 

1108 try: 

1109 while True: 

1110 self.pop() 

1111 except IndexError: 

1112 pass 

1113 

1114 def reverse(self): 

1115 'S.reverse() -- reverse *IN PLACE*' 

1116 n = len(self) 

1117 for i in range(n//2): 

1118 self[i], self[n-i-1] = self[n-i-1], self[i] 

1119 

1120 def extend(self, values): 

1121 'S.extend(iterable) -- extend sequence by appending elements from the iterable' 

1122 if values is self: 

1123 values = list(values) 

1124 for v in values: 

1125 self.append(v) 

1126 

1127 def pop(self, index=-1): 

1128 '''S.pop([index]) -> item -- remove and return item at index (default last). 

1129 Raise IndexError if list is empty or index is out of range. 

1130 ''' 

1131 v = self[index] 

1132 del self[index] 

1133 return v 

1134 

1135 def remove(self, value): 

1136 '''S.remove(value) -- remove first occurrence of value. 

1137 Raise ValueError if the value is not present. 

1138 ''' 

1139 del self[self.index(value)] 

1140 

1141 def __iadd__(self, values): 

1142 self.extend(values) 

1143 return self 

1144 

1145 

1146MutableSequence.register(list) 

1147MutableSequence.register(bytearray) # Multiply inheriting, see ByteString