"""Python implementation of PEP-380 (yield from)."""
from functools import wraps
class _from(object):
"""Wrap a generator function to be used from a supergenerator."""
def __init__(self, genfunc):
self.genfunc = genfunc
def supergenerator(genfunc):
"""
Decorate a generator so it can yield nested generators (using _from class).
@supergenerator
def mysupergen():
yield "normal yield"
yield "one more yield"
yield _from(othergen())
yield _from(yet_othergen())
yield "last yield"
Note that nested generators can, in turn, yield other generators.
"""
def _process(gen):
tosend = None
while 1:
yielded = gen.send(tosend)
if isinstance(yielded, _from):
nested_gen = _process(yielded.genfunc)
nested_tosend = None
while 1:
try:
nested_yielded = nested_gen.send(nested_tosend)
except StopIteration, exc:
new_tosend = (exc.args[0] if exc.args else None)
break
except Exception, exc:
yielded.genfunc.close()
yielded2 = gen.throw(exc)
new_tosend = (yield yielded2)
break
nested_tosend = (yield nested_yielded)
else:
new_tosend = (yield yielded)
tosend = new_tosend
@wraps(genfunc)
def _wrapper(*args, **kwargs):
return _process(genfunc(*args, **kwargs))
return _wrapper
Diff to Previous Revision
--- revision 2 2010-03-26 19:53:45
+++ revision 3 2010-04-25 23:08:07
@@ -1,3 +1,6 @@
+"""Python implementation of PEP-380 (yield from)."""
+from functools import wraps
+
class _from(object):
"""Wrap a generator function to be used from a supergenerator."""
def __init__(self, genfunc):
@@ -39,6 +42,7 @@
else:
new_tosend = (yield yielded)
tosend = new_tosend
+ @wraps(genfunc)
def _wrapper(*args, **kwargs):
return _process(genfunc(*args, **kwargs))
return _wrapper