@@ -163,19 +163,22 @@ def decorator(f):
163
163
164
164
165
165
def pytest_fixture_setup (fixturedef , request ):
166
+ """Interface pytest to async setup for async and async yield fixtures."""
167
+ # TODO: what about inlineCallbacks fixtures?
166
168
maybe_mark = getattr (fixturedef .func , _mark_attribute_name , None )
167
169
if maybe_mark is None :
168
170
return None
169
171
170
172
mark = maybe_mark
171
173
172
- run_inline_callbacks (_pytest_fixture_setup , fixturedef , request , mark )
174
+ run_inline_callbacks (_async_pytest_fixture_setup , fixturedef , request , mark )
173
175
174
176
return True
175
177
176
178
177
179
@defer .inlineCallbacks
178
- def _pytest_fixture_setup (fixturedef , request , mark ):
180
+ def _async_pytest_fixture_setup (fixturedef , request , mark ):
181
+ """Setup async and async yield fixtures."""
179
182
fixture_function = fixturedef .func
180
183
181
184
kwargs = {
@@ -204,6 +207,7 @@ def _pytest_fixture_setup(fixturedef, request, mark):
204
207
205
208
# TODO: but don't we want to do the finalizer? not wait until post it?
206
209
def pytest_fixture_post_finalizer (fixturedef , request ):
210
+ """Collect async yield fixture teardown requests for later handling."""
207
211
maybe_coroutine = _tracking .async_yield_fixture_cache .pop (
208
212
request .param_index ,
209
213
None ,
@@ -221,6 +225,7 @@ def pytest_fixture_post_finalizer(fixturedef, request):
221
225
222
226
@defer .inlineCallbacks
223
227
def tear_it_down (deferred ):
228
+ """Tear down a specific async yield fixture."""
224
229
try :
225
230
yield deferred
226
231
except StopAsyncIteration :
@@ -230,6 +235,7 @@ def tear_it_down(deferred):
230
235
else :
231
236
e = None
232
237
238
+ # TODO: six.raise_from()
233
239
raise AsyncGeneratorFixtureDidNotStopError .from_generator (
234
240
generator = deferred ,
235
241
)
@@ -240,6 +246,7 @@ def tear_it_down(deferred):
240
246
241
247
242
248
def run_inline_callbacks (f , * args ):
249
+ """Interface into Twisted greenlet to run and wait for deferred."""
243
250
if _instances .gr_twisted is not None :
244
251
if _instances .gr_twisted .dead :
245
252
raise RuntimeError ("twisted reactor has stopped" )
@@ -258,15 +265,24 @@ def in_reactor(d, f, *args):
258
265
259
266
@pytest .hookimpl (hookwrapper = True )
260
267
def pytest_runtest_teardown (item ):
268
+ """Tear down collected async yield fixtures."""
261
269
yield
262
270
263
271
while len (_tracking .to_be_torn_down ) > 0 :
264
272
deferred = _tracking .to_be_torn_down .pop (0 )
265
273
run_inline_callbacks (tear_it_down , deferred )
266
274
267
275
276
+ def pytest_pyfunc_call (pyfuncitem ):
277
+ """Interface to async test call handler."""
278
+ # TODO: only handle 'our' tests? what is the point of handling others?
279
+ run_inline_callbacks (_async_pytest_pyfunc_call , pyfuncitem )
280
+ return True
281
+
282
+
268
283
@defer .inlineCallbacks
269
- def _pytest_pyfunc_call (pyfuncitem ):
284
+ def _async_pytest_pyfunc_call (pyfuncitem ):
285
+ """Run test function."""
270
286
kwargs = {
271
287
name : value
272
288
for name , value in pyfuncitem .funcargs .items ()
@@ -276,17 +292,13 @@ def _pytest_pyfunc_call(pyfuncitem):
276
292
defer .returnValue (result )
277
293
278
294
279
- def pytest_pyfunc_call (pyfuncitem ):
280
- run_inline_callbacks (_pytest_pyfunc_call , pyfuncitem )
281
- return True
282
-
283
-
284
295
@pytest .fixture (scope = "session" , autouse = True )
285
296
def twisted_greenlet ():
286
297
return _instances .gr_twisted
287
298
288
299
289
300
def init_default_reactor ():
301
+ """Install the default Twisted reactor."""
290
302
import twisted .internet .default
291
303
292
304
module = inspect .getmodule (twisted .internet .default .install )
@@ -302,6 +314,7 @@ def init_default_reactor():
302
314
303
315
304
316
def init_qt5_reactor ():
317
+ """Install the qt5reactor... reactor."""
305
318
import qt5reactor
306
319
307
320
_install_reactor (
@@ -310,6 +323,7 @@ def init_qt5_reactor():
310
323
311
324
312
325
def init_asyncio_reactor ():
326
+ """Install the Twisted reactor for asyncio."""
313
327
from twisted .internet import asyncioreactor
314
328
315
329
_install_reactor (
@@ -326,6 +340,7 @@ def init_asyncio_reactor():
326
340
327
341
328
342
def _install_reactor (reactor_installer , reactor_type ):
343
+ """Install the specified reactor and create the greenlet."""
329
344
try :
330
345
reactor_installer ()
331
346
except error .ReactorAlreadyInstalledError :
@@ -345,6 +360,7 @@ def _install_reactor(reactor_installer, reactor_type):
345
360
346
361
347
362
def pytest_addoption (parser ):
363
+ """Add options into the pytest CLI."""
348
364
group = parser .getgroup ("twisted" )
349
365
group .addoption (
350
366
"--reactor" ,
@@ -354,6 +370,7 @@ def pytest_addoption(parser):
354
370
355
371
356
372
def pytest_configure (config ):
373
+ """Identify and install chosen reactor."""
357
374
pytest .inlineCallbacks = _deprecate (
358
375
deprecated = 'pytest.inlineCallbacks' ,
359
376
recommended = 'pytest_twisted.inlineCallbacks' ,
@@ -367,10 +384,12 @@ def pytest_configure(config):
367
384
368
385
369
386
def pytest_unconfigure (config ):
387
+ """Stop the reactor greenlet."""
370
388
stop_twisted_greenlet ()
371
389
372
390
373
391
def _use_asyncio_selector_if_required (config ):
392
+ """Set asyncio selector event loop policy if needed."""
374
393
# https://twistedmatrix.com/trac/ticket/9766
375
394
# https://github.com/pytest-dev/pytest-twisted/issues/80
376
395
0 commit comments