|
20 | 20 | from collections import ChainMap |
21 | 21 | from collections import deque |
22 | 22 | from collections.abc import Awaitable, Coroutine, AsyncIterator, AsyncIterable |
23 | | -from collections.abc import Hashable, Iterable, Iterator, Generator |
| 23 | +from collections.abc import Hashable, Iterable, Iterator, Generator, Reversible |
24 | 24 | from collections.abc import Sized, Container, Callable |
25 | 25 | from collections.abc import Set, MutableSet |
26 | 26 | from collections.abc import Mapping, MutableMapping, KeysView, ItemsView |
@@ -689,6 +689,31 @@ def __iter__(self): |
689 | 689 | self.validate_abstract_methods(Iterable, '__iter__') |
690 | 690 | self.validate_isinstance(Iterable, '__iter__') |
691 | 691 |
|
| 692 | + def test_Reversible(self): |
| 693 | + # Check some non-reversibles |
| 694 | + non_samples = [None, 42, 3.14, 1j, dict(), set(), frozenset()] |
| 695 | + for x in non_samples: |
| 696 | + self.assertNotIsInstance(x, Reversible) |
| 697 | + self.assertFalse(issubclass(type(x), Reversible), repr(type(x))) |
| 698 | + # Check some reversibles |
| 699 | + samples = [tuple(), list()] |
| 700 | + for x in samples: |
| 701 | + self.assertIsInstance(x, Reversible) |
| 702 | + self.assertTrue(issubclass(type(x), Reversible), repr(type(x))) |
| 703 | + # Check also Mapping, MutableMapping, and Sequence |
| 704 | + self.assertTrue(issubclass(Sequence, Reversible), repr(Sequence)) |
| 705 | + self.assertFalse(issubclass(Mapping, Reversible), repr(Mapping)) |
| 706 | + self.assertFalse(issubclass(MutableMapping, Reversible), repr(MutableMapping)) |
| 707 | + # Check direct subclassing |
| 708 | + class R(Reversible): |
| 709 | + def __iter__(self): |
| 710 | + return iter(list()) |
| 711 | + def __reversed__(self): |
| 712 | + return iter(list()) |
| 713 | + self.assertEqual(list(reversed(R())), []) |
| 714 | + self.assertFalse(issubclass(float, R)) |
| 715 | + self.validate_abstract_methods(Reversible, '__reversed__', '__iter__') |
| 716 | + |
692 | 717 | def test_Iterator(self): |
693 | 718 | non_samples = [None, 42, 3.14, 1j, b"", "", (), [], {}, set()] |
694 | 719 | for x in non_samples: |
@@ -842,14 +867,14 @@ def test_Callable(self): |
842 | 867 | self.validate_isinstance(Callable, '__call__') |
843 | 868 |
|
844 | 869 | def test_direct_subclassing(self): |
845 | | - for B in Hashable, Iterable, Iterator, Sized, Container, Callable: |
| 870 | + for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable: |
846 | 871 | class C(B): |
847 | 872 | pass |
848 | 873 | self.assertTrue(issubclass(C, B)) |
849 | 874 | self.assertFalse(issubclass(int, C)) |
850 | 875 |
|
851 | 876 | def test_registration(self): |
852 | | - for B in Hashable, Iterable, Iterator, Sized, Container, Callable: |
| 877 | + for B in Hashable, Iterable, Iterator, Reversible, Sized, Container, Callable: |
853 | 878 | class C: |
854 | 879 | __hash__ = None # Make sure it isn't hashable by default |
855 | 880 | self.assertFalse(issubclass(C, B), B.__name__) |
|
0 commit comments