summaryrefslogtreecommitdiffstats
path: root/Lib/_collections_abc.py
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2015-05-09 05:07:23 (GMT)
committerRaymond Hettinger <python@rcn.com>2015-05-09 05:07:23 (GMT)
commitbd60e8dece89440ebdc80a19b2217d5ba2515124 (patch)
tree97cf2f7e3802aede1de63eb304cefcf55791077e /Lib/_collections_abc.py
parentdae2ef1cfad60b149370b4012aa48bea2dd27445 (diff)
downloadcpython-bd60e8dece89440ebdc80a19b2217d5ba2515124.zip
cpython-bd60e8dece89440ebdc80a19b2217d5ba2515124.tar.gz
cpython-bd60e8dece89440ebdc80a19b2217d5ba2515124.tar.bz2
Issue #24018: Add a collections.Generator abstract base class.
Diffstat (limited to 'Lib/_collections_abc.py')
-rw-r--r--Lib/_collections_abc.py61
1 files changed, 60 insertions, 1 deletions
diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py
index 3d3f07b..cb87e6b 100644
--- a/Lib/_collections_abc.py
+++ b/Lib/_collections_abc.py
@@ -9,7 +9,7 @@ Unit tests are in test_collections.
from abc import ABCMeta, abstractmethod
import sys
-__all__ = ["Hashable", "Iterable", "Iterator",
+__all__ = ["Hashable", "Iterable", "Iterator", "Generator",
"Sized", "Container", "Callable",
"Set", "MutableSet",
"Mapping", "MutableMapping",
@@ -50,6 +50,7 @@ dict_values = type({}.values())
dict_items = type({}.items())
## misc ##
mappingproxy = type(type.__dict__)
+generator = type((lambda: (yield))())
### ONE-TRICK PONIES ###
@@ -124,6 +125,64 @@ Iterator.register(str_iterator)
Iterator.register(tuple_iterator)
Iterator.register(zip_iterator)
+
+class Generator(Iterator):
+
+ __slots__ = ()
+
+ def __next__(self):
+ """Return the next item from the generator.
+ When exhausted, raise StopIteration.
+ """
+ return self.send(None)
+
+ @abstractmethod
+ def send(self, value):
+ """Send a value into the generator.
+ Return next yielded value or raise StopIteration.
+ """
+ raise StopIteration
+
+ @abstractmethod
+ def throw(self, typ, val=None, tb=None):
+ """Raise an exception in the generator.
+ Return next yielded value or raise StopIteration.
+ """
+ if val is None:
+ if tb is None:
+ raise typ
+ val = typ()
+ if tb is not None:
+ val = val.with_traceback(tb)
+ raise val
+
+ def close(self):
+ """Raise GeneratorExit inside generator.
+ """
+ try:
+ self.throw(GeneratorExit)
+ except (GeneratorExit, StopIteration):
+ pass
+ else:
+ raise RuntimeError("generator ignored GeneratorExit")
+
+ @classmethod
+ def __subclasshook__(cls, C):
+ if cls is Generator:
+ mro = C.__mro__
+ for method in ('__iter__', '__next__', 'send', 'throw', 'close'):
+ for base in mro:
+ if method in base.__dict__:
+ break
+ else:
+ return NotImplemented
+ return True
+ return NotImplemented
+
+
+Generator.register(generator)
+
+
class Sized(metaclass=ABCMeta):
__slots__ = ()