162 lines
3.2 KiB
Python
162 lines
3.2 KiB
Python
from __future__ import generators
|
|
import py
|
|
try:
|
|
from py.magic import greenlet
|
|
except (ImportError, RuntimeError), e:
|
|
py.test.skip(str(e))
|
|
|
|
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
|
|
|
|
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 test_genlet_simple():
|
|
|
|
for g in [g1, g2, g3]:
|
|
seen = []
|
|
for k in range(3):
|
|
for j in g(5, seen):
|
|
seen.append(j)
|
|
|
|
assert seen == 3 * [1, 0, 2, 1, 3, 2, 4, 3, 5, 4]
|
|
|
|
def test_genlet_bad():
|
|
try:
|
|
Yield(10)
|
|
except RuntimeError:
|
|
pass
|
|
|
|
test_genlet_bad()
|
|
test_genlet_simple()
|
|
test_genlet_bad()
|
|
|
|
def a(n):
|
|
if n == 0:
|
|
return
|
|
for ii in ax(n-1):
|
|
Yield(ii)
|
|
Yield(n)
|
|
ax = Genlet(a)
|
|
|
|
def test_nested_genlets():
|
|
seen = []
|
|
for ii in ax(5):
|
|
seen.append(ii)
|
|
|
|
test_nested_genlets()
|
|
|
|
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 test_perms():
|
|
gen_perms = perms(range(4))
|
|
permutations = list(gen_perms)
|
|
assert len(permutations) == 4*3*2*1
|
|
assert [0,1,2,3] in permutations
|
|
assert [3,2,1,0] in permutations
|
|
res = []
|
|
for ii in zip(perms(range(4)), perms(range(3))):
|
|
res.append(ii)
|
|
# XXX Test to make sure we are working as a generator expression
|
|
test_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)
|
|
|
|
def test_layered_genlets():
|
|
seen = []
|
|
for ii in gr2(5, seen):
|
|
seen.append(ii)
|
|
assert seen == [1, 1, 2, 4, 3, 9, 4, 16]
|
|
|
|
test_layered_genlets()
|