@@ -25,6 +25,74 @@ def last_cb():
2525 pass
2626
2727
28+ class DuckFuture :
29+ # Class that does not inherit from Future but aims to be duck-type
30+ # compatible with it.
31+
32+ _asyncio_future_blocking = False
33+ __cancelled = False
34+ __result = None
35+ __exception = None
36+
37+ def cancel (self ):
38+ if self .done ():
39+ return False
40+ self .__cancelled = True
41+ return True
42+
43+ def cancelled (self ):
44+ return self .__cancelled
45+
46+ def done (self ):
47+ return (self .__cancelled
48+ or self .__result is not None
49+ or self .__exception is not None )
50+
51+ def result (self ):
52+ assert not self .cancelled ()
53+ if self .__exception is not None :
54+ raise self .__exception
55+ return self .__result
56+
57+ def exception (self ):
58+ assert not self .cancelled ()
59+ return self .__exception
60+
61+ def set_result (self , result ):
62+ assert not self .done ()
63+ assert result is not None
64+ self .__result = result
65+
66+ def set_exception (self , exception ):
67+ assert not self .done ()
68+ assert exception is not None
69+ self .__exception = exception
70+
71+ def __iter__ (self ):
72+ if not self .done ():
73+ self ._asyncio_future_blocking = True
74+ yield self
75+ assert self .done ()
76+ return self .result ()
77+
78+
79+ class DuckTests (test_utils .TestCase ):
80+
81+ def setUp (self ):
82+ self .loop = self .new_test_loop ()
83+ self .addCleanup (self .loop .close )
84+
85+ def test_wrap_future (self ):
86+ f = DuckFuture ()
87+ g = asyncio .wrap_future (f )
88+ assert g is f
89+
90+ def test_ensure_future (self ):
91+ f = DuckFuture ()
92+ g = asyncio .ensure_future (f )
93+ assert g is f
94+
95+
2896class FutureTests (test_utils .TestCase ):
2997
3098 def setUp (self ):
0 commit comments