_yieldfromtests.py.3only 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. # Copyright (c) Twisted Matrix Laboratories.
  2. # See LICENSE for details.
  3. """
  4. Tests for C{yield from} support in Deferreds.
  5. These tests can only work and be imported on Python 3!
  6. """
  7. import types
  8. from twisted.internet.defer import Deferred, ensureDeferred, fail
  9. from twisted.trial.unittest import TestCase
  10. from twisted.test.proto_helpers import Clock
  11. class YieldFromTests(TestCase):
  12. """
  13. Tests for using Deferreds in conjunction with PEP-380.
  14. """
  15. def test_ensureDeferred(self):
  16. """
  17. L{ensureDeferred} will turn a coroutine into a L{Deferred}.
  18. """
  19. def run():
  20. d = Deferred()
  21. d.callback("bar")
  22. yield from d
  23. res = yield from run2()
  24. return res
  25. def run2():
  26. d = Deferred()
  27. d.callback("foo")
  28. res = yield from d
  29. return res
  30. # It's a generator...
  31. r = run()
  32. self.assertIsInstance(r, types.GeneratorType)
  33. # Now it's a Deferred.
  34. d = ensureDeferred(r)
  35. self.assertIsInstance(d, Deferred)
  36. # The Deferred has the result we want.
  37. res = self.successResultOf(d)
  38. self.assertEqual(res, "foo")
  39. def test_basic(self):
  40. """
  41. L{ensureDeferred} allows a function to C{yield from} a L{Deferred}.
  42. """
  43. def run():
  44. d = Deferred()
  45. d.callback("foo")
  46. res = yield from d
  47. return res
  48. d = ensureDeferred(run())
  49. res = self.successResultOf(d)
  50. self.assertEqual(res, "foo")
  51. def test_exception(self):
  52. """
  53. An exception in a generator wrapped with L{ensureDeferred} will cause
  54. the returned L{Deferred} to fire with a failure.
  55. """
  56. def run():
  57. d = Deferred()
  58. d.callback("foo")
  59. yield from d
  60. raise ValueError("Oh no!")
  61. d = ensureDeferred(run())
  62. res = self.failureResultOf(d)
  63. self.assertEqual(type(res.value), ValueError)
  64. self.assertEqual(res.value.args, ("Oh no!",))
  65. def test_twoDeep(self):
  66. """
  67. An exception in a generator wrapped with L{ensureDeferred} will cause
  68. the returned L{Deferred} to fire with a failure.
  69. """
  70. reactor = Clock()
  71. sections = []
  72. def runone():
  73. sections.append(2)
  74. d = Deferred()
  75. reactor.callLater(1, d.callback, None)
  76. yield from d
  77. sections.append(3)
  78. return "Yay!"
  79. def run():
  80. sections.append(1)
  81. result = yield from runone()
  82. sections.append(4)
  83. d = Deferred()
  84. reactor.callLater(1, d.callback, None)
  85. yield from d
  86. sections.append(5)
  87. return result
  88. d = ensureDeferred(run())
  89. reactor.advance(0.9)
  90. self.assertEqual(sections, [1, 2])
  91. reactor.advance(0.1)
  92. self.assertEqual(sections, [1, 2, 3, 4])
  93. reactor.advance(0.9)
  94. self.assertEqual(sections, [1, 2, 3, 4])
  95. reactor.advance(0.1)
  96. self.assertEqual(sections, [1, 2, 3, 4, 5])
  97. res = self.successResultOf(d)
  98. self.assertEqual(res, "Yay!")
  99. def test_reraise(self):
  100. """
  101. Yielding from an already failed Deferred will raise the exception.
  102. """
  103. def test():
  104. try:
  105. yield from fail(ValueError("Boom"))
  106. except ValueError as e:
  107. self.assertEqual(e.args, ("Boom",))
  108. return 1
  109. return 0
  110. res = self.successResultOf(ensureDeferred(test()))
  111. self.assertEqual(res, 1)
  112. def test_chained(self):
  113. """
  114. Yielding from a paused & chained Deferred will give the result when it
  115. has one.
  116. """
  117. reactor = Clock()
  118. def test():
  119. d = Deferred()
  120. d2 = Deferred()
  121. d.addCallback(lambda ignored: d2)
  122. d.callback(None)
  123. reactor.callLater(0, d2.callback, "bye")
  124. res = yield from d
  125. return res
  126. d = ensureDeferred(test())
  127. reactor.advance(0.1)
  128. res = self.successResultOf(d)
  129. self.assertEqual(res, "bye")