mirror of
https://github.com/python/cpython.git
synced 2025-11-01 18:51:43 +00:00
Issue #24018: Add a collections.Generator abstract base class.
This commit is contained in:
parent
dae2ef1cfa
commit
bd60e8dece
4 changed files with 145 additions and 2 deletions
|
|
@ -14,7 +14,7 @@ import sys
|
|||
from collections import UserDict
|
||||
from collections import ChainMap
|
||||
from collections import deque
|
||||
from collections.abc import Hashable, Iterable, Iterator
|
||||
from collections.abc import Hashable, Iterable, Iterator, Generator
|
||||
from collections.abc import Sized, Container, Callable
|
||||
from collections.abc import Set, MutableSet
|
||||
from collections.abc import Mapping, MutableMapping, KeysView, ItemsView
|
||||
|
|
@ -522,6 +522,77 @@ class TestOneTrickPonyABCs(ABCTestCase):
|
|||
return
|
||||
self.assertNotIsInstance(NextOnly(), Iterator)
|
||||
|
||||
def test_Generator(self):
|
||||
class NonGen1:
|
||||
def __iter__(self): return self
|
||||
def __next__(self): return None
|
||||
def close(self): pass
|
||||
def throw(self, typ, val=None, tb=None): pass
|
||||
|
||||
class NonGen2:
|
||||
def __iter__(self): return self
|
||||
def __next__(self): return None
|
||||
def close(self): pass
|
||||
def send(self, value): return value
|
||||
|
||||
class NonGen3:
|
||||
def close(self): pass
|
||||
def send(self, value): return value
|
||||
def throw(self, typ, val=None, tb=None): pass
|
||||
|
||||
non_samples = [
|
||||
None, 42, 3.14, 1j, b"", "", (), [], {}, set(),
|
||||
iter(()), iter([]), NonGen1(), NonGen2(), NonGen3()]
|
||||
for x in non_samples:
|
||||
self.assertNotIsInstance(x, Generator)
|
||||
self.assertFalse(issubclass(type(x), Generator), repr(type(x)))
|
||||
|
||||
class Gen:
|
||||
def __iter__(self): return self
|
||||
def __next__(self): return None
|
||||
def close(self): pass
|
||||
def send(self, value): return value
|
||||
def throw(self, typ, val=None, tb=None): pass
|
||||
|
||||
class MinimalGen(Generator):
|
||||
def send(self, value):
|
||||
return value
|
||||
def throw(self, typ, val=None, tb=None):
|
||||
super().throw(typ, val, tb)
|
||||
|
||||
def gen():
|
||||
yield 1
|
||||
|
||||
samples = [gen(), (lambda: (yield))(), Gen(), MinimalGen()]
|
||||
for x in samples:
|
||||
self.assertIsInstance(x, Iterator)
|
||||
self.assertIsInstance(x, Generator)
|
||||
self.assertTrue(issubclass(type(x), Generator), repr(type(x)))
|
||||
self.validate_abstract_methods(Generator, 'send', 'throw')
|
||||
|
||||
# mixin tests
|
||||
mgen = MinimalGen()
|
||||
self.assertIs(mgen, iter(mgen))
|
||||
self.assertIs(mgen.send(None), next(mgen))
|
||||
self.assertEqual(2, mgen.send(2))
|
||||
self.assertIsNone(mgen.close())
|
||||
self.assertRaises(ValueError, mgen.throw, ValueError)
|
||||
self.assertRaisesRegex(ValueError, "^huhu$",
|
||||
mgen.throw, ValueError, ValueError("huhu"))
|
||||
self.assertRaises(StopIteration, mgen.throw, StopIteration())
|
||||
|
||||
class FailOnClose(Generator):
|
||||
def send(self, value): return value
|
||||
def throw(self, *args): raise ValueError
|
||||
|
||||
self.assertRaises(ValueError, FailOnClose().close)
|
||||
|
||||
class IgnoreGeneratorExit(Generator):
|
||||
def send(self, value): return value
|
||||
def throw(self, *args): pass
|
||||
|
||||
self.assertRaises(RuntimeError, IgnoreGeneratorExit().close)
|
||||
|
||||
def test_Sized(self):
|
||||
non_samples = [None, 42, 3.14, 1j,
|
||||
(lambda: (yield))(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue