test_generator_nested.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. from greenlet import greenlet
  2. from . import TestCase
  3. from .leakcheck import fails_leakcheck
  4. class genlet(greenlet):
  5. parent = None
  6. def __init__(self, *args, **kwds):
  7. self.args = args
  8. self.kwds = kwds
  9. self.child = None
  10. def run(self):
  11. # Note the function is packed in a tuple
  12. # to avoid creating a bound method for it.
  13. fn, = self.fn
  14. fn(*self.args, **self.kwds)
  15. def __iter__(self):
  16. return self
  17. def set_child(self, child):
  18. self.child = child
  19. def __next__(self):
  20. if self.child:
  21. child = self.child
  22. while child.child:
  23. tmp = child
  24. child = child.child
  25. tmp.child = None
  26. result = child.switch()
  27. else:
  28. self.parent = greenlet.getcurrent()
  29. result = self.switch()
  30. if self:
  31. return result
  32. raise StopIteration
  33. next = __next__
  34. def Yield(value, level=1):
  35. g = greenlet.getcurrent()
  36. while level != 0:
  37. if not isinstance(g, genlet):
  38. raise RuntimeError('yield outside a genlet')
  39. if level > 1:
  40. g.parent.set_child(g)
  41. g = g.parent
  42. level -= 1
  43. g.switch(value)
  44. def Genlet(func):
  45. class TheGenlet(genlet):
  46. fn = (func,)
  47. return TheGenlet
  48. # ____________________________________________________________
  49. def g1(n, seen):
  50. for i in range(n):
  51. seen.append(i + 1)
  52. yield i
  53. def g2(n, seen):
  54. for i in range(n):
  55. seen.append(i + 1)
  56. Yield(i)
  57. g2 = Genlet(g2)
  58. def nested(i):
  59. Yield(i)
  60. def g3(n, seen):
  61. for i in range(n):
  62. seen.append(i + 1)
  63. nested(i)
  64. g3 = Genlet(g3)
  65. def a(n):
  66. if n == 0:
  67. return
  68. for ii in ax(n - 1):
  69. Yield(ii)
  70. Yield(n)
  71. ax = Genlet(a)
  72. def perms(l):
  73. if len(l) > 1:
  74. for e in l:
  75. # No syntactical sugar for generator expressions
  76. x = [Yield([e] + p) for p in perms([x for x in l if x != e])]
  77. assert x
  78. else:
  79. Yield(l)
  80. perms = Genlet(perms)
  81. def gr1(n):
  82. for ii in range(1, n):
  83. Yield(ii)
  84. Yield(ii * ii, 2)
  85. gr1 = Genlet(gr1)
  86. def gr2(n, seen):
  87. for ii in gr1(n):
  88. seen.append(ii)
  89. gr2 = Genlet(gr2)
  90. class NestedGeneratorTests(TestCase):
  91. def test_layered_genlets(self):
  92. seen = []
  93. for ii in gr2(5, seen):
  94. seen.append(ii)
  95. self.assertEqual(seen, [1, 1, 2, 4, 3, 9, 4, 16])
  96. @fails_leakcheck
  97. def test_permutations(self):
  98. gen_perms = perms(list(range(4)))
  99. permutations = list(gen_perms)
  100. self.assertEqual(len(permutations), 4 * 3 * 2 * 1)
  101. self.assertIn([0, 1, 2, 3], permutations)
  102. self.assertIn([3, 2, 1, 0], permutations)
  103. res = []
  104. for ii in zip(perms(list(range(4))), perms(list(range(3)))):
  105. res.append(ii)
  106. self.assertEqual(
  107. res,
  108. [([0, 1, 2, 3], [0, 1, 2]), ([0, 1, 3, 2], [0, 2, 1]),
  109. ([0, 2, 1, 3], [1, 0, 2]), ([0, 2, 3, 1], [1, 2, 0]),
  110. ([0, 3, 1, 2], [2, 0, 1]), ([0, 3, 2, 1], [2, 1, 0])])
  111. # XXX Test to make sure we are working as a generator expression
  112. def test_genlet_simple(self):
  113. for g in g1, g2, g3:
  114. seen = []
  115. for _ in range(3):
  116. for j in g(5, seen):
  117. seen.append(j)
  118. self.assertEqual(seen, 3 * [1, 0, 2, 1, 3, 2, 4, 3, 5, 4])
  119. def test_genlet_bad(self):
  120. try:
  121. Yield(10)
  122. except RuntimeError:
  123. pass
  124. def test_nested_genlets(self):
  125. seen = []
  126. for ii in ax(5):
  127. seen.append(ii)