import unittest from greenlet import greenlet class genlet(greenlet): def __init__(self, *args, **kwds): self.args = args self.kwds = kwds self.child = None def run(self): fn, = self.fn fn(*self.args, **self.kwds) def __iter__(self): return self def set_child(self, child): self.child = child def __next__(self): if self.child: child = self.child while child.child: tmp = child child = child.child tmp.child = None result = child.switch() else: self.parent = greenlet.getcurrent() result = self.switch() if self: return result else: raise StopIteration # Hack: Python < 2.6 compatibility next = __next__ def Yield(value, level=1): g = greenlet.getcurrent() while level != 0: if not isinstance(g, genlet): raise RuntimeError('yield outside a genlet') if level > 1: g.parent.set_child(g) g = g.parent level -= 1 g.switch(value) def Genlet(func): class Genlet(genlet): fn = (func,) return Genlet # ____________________________________________________________ def g1(n, seen): for i in range(n): seen.append(i + 1) yield i def g2(n, seen): for i in range(n): seen.append(i + 1) Yield(i) g2 = Genlet(g2) def nested(i): Yield(i) def g3(n, seen): for i in range(n): seen.append(i + 1) nested(i) g3 = Genlet(g3) def a(n): if n == 0: return for ii in ax(n - 1): Yield(ii) Yield(n) ax = Genlet(a) def perms(l): if len(l) > 1: for e in l: # No syntactical sugar for generator expressions [Yield([e] + p) for p in perms([x for x in l if x != e])] else: Yield(l) perms = Genlet(perms) def gr1(n): for ii in range(1, n): Yield(ii) Yield(ii * ii, 2) gr1 = Genlet(gr1) def gr2(n, seen): for ii in gr1(n): seen.append(ii) gr2 = Genlet(gr2) class NestedGeneratorTests(unittest.TestCase): def test_layered_genlets(self): seen = [] for ii in gr2(5, seen): seen.append(ii) self.assertEqual(seen, [1, 1, 2, 4, 3, 9, 4, 16]) def test_permutations(self): gen_perms = perms(list(range(4))) permutations = list(gen_perms) self.assertEqual(len(permutations), 4 * 3 * 2 * 1) self.assertTrue([0, 1, 2, 3] in permutations) self.assertTrue([3, 2, 1, 0] in permutations) res = [] for ii in zip(perms(list(range(4))), perms(list(range(3)))): res.append(ii) self.assertEqual( res, [([0, 1, 2, 3], [0, 1, 2]), ([0, 1, 3, 2], [0, 2, 1]), ([0, 2, 1, 3], [1, 0, 2]), ([0, 2, 3, 1], [1, 2, 0]), ([0, 3, 1, 2], [2, 0, 1]), ([0, 3, 2, 1], [2, 1, 0])]) # XXX Test to make sure we are working as a generator expression def test_genlet_simple(self): for g in [g1, g2, g3]: seen = [] for k in range(3): for j in g(5, seen): seen.append(j) self.assertEqual(seen, 3 * [1, 0, 2, 1, 3, 2, 4, 3, 5, 4]) def test_genlet_bad(self): try: Yield(10) except RuntimeError: pass def test_nested_genlets(self): seen = [] for ii in ax(5): seen.append(ii)