1
1
import greenlet , pytest
2
2
from twisted .internet import reactor , defer
3
+ from twisted .internet .threads import blockingCallFromThread
3
4
from twisted .python import failure
4
5
from decorator import decorator
5
6
8
9
9
10
def blockon (d ):
10
11
current = greenlet .getcurrent ()
11
- assert current is not gr_twisted , "blockon cannot be called from the twisted greenlet"
12
+ assert current is not gr_twisted , \
13
+ "blockon cannot be called from the twisted greenlet"
12
14
result = []
13
15
14
16
def cb (r ):
@@ -27,21 +29,18 @@ def cb(r):
27
29
return result [0 ]
28
30
29
31
32
+ def block_from_thread (d ):
33
+ return blockingCallFromThread (reactor , lambda x : x , d )
34
+
35
+
30
36
@decorator
31
37
def inlineCallbacks (fun , * args , ** kw ):
32
38
return defer .inlineCallbacks (fun )(* args , ** kw )
33
39
34
40
35
41
def pytest_namespace ():
36
- return dict (inlineCallbacks = inlineCallbacks , blockon = blockon )
37
-
38
-
39
- def init_twisted_greenlet ():
40
- global gr_twisted
41
- if not gr_twisted :
42
- gr_twisted = greenlet .greenlet (reactor .run )
43
- failure .Failure .cleanFailure = lambda self : None # give me better tracebacks
44
- return gr_twisted
42
+ return dict (inlineCallbacks = inlineCallbacks ,
43
+ blockon = block_from_thread if reactor .running else blockon )
45
44
46
45
47
46
def stop_twisted_greenlet ():
@@ -51,7 +50,11 @@ def stop_twisted_greenlet():
51
50
52
51
53
52
def pytest_addhooks (pluginmanager ):
54
- init_twisted_greenlet ()
53
+ global gr_twisted
54
+ if not gr_twisted and not reactor .running :
55
+ gr_twisted = greenlet .greenlet (reactor .run )
56
+ # give me better tracebacks:
57
+ failure .Failure .cleanFailure = lambda self : None
55
58
56
59
57
60
@pytest .fixture (scope = "session" , autouse = True )
@@ -76,10 +79,18 @@ def _pytest_pyfunc_call(pyfuncitem):
76
79
77
80
78
81
def pytest_pyfunc_call (pyfuncitem ):
79
- if gr_twisted .dead :
80
- raise RuntimeError ("twisted reactor has stopped" )
82
+ if gr_twisted is not None :
83
+ if gr_twisted .dead :
84
+ raise RuntimeError ("twisted reactor has stopped" )
81
85
82
- d = defer .Deferred ()
83
- reactor .callLater (0.0 , lambda : defer .maybeDeferred (_pytest_pyfunc_call , pyfuncitem ).chainDeferred (d ))
84
- blockon (d )
86
+ def in_reactor (d , f , * args ):
87
+ return defer .maybeDeferred (f , * args ).chainDeferred (d )
88
+
89
+ d = defer .Deferred ()
90
+ reactor .callLater (0.0 , in_reactor , d , _pytest_pyfunc_call , pyfuncitem )
91
+ blockon (d )
92
+ else :
93
+ if not reactor .running :
94
+ raise RuntimeError ("twisted reactor is not running" )
95
+ blockingCallFromThread (reactor , _pytest_pyfunc_call , pyfuncitem )
85
96
return True
0 commit comments