Skip to content

Commit 3a3f748

Browse files
committed
trade concurrency for correct order
1 parent 365fc4f commit 3a3f748

File tree

2 files changed

+31
-52
lines changed

2 files changed

+31
-52
lines changed

pytest_twisted.py

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,6 @@ class _instances:
5050
reactor = None
5151

5252

53-
class _tracking:
54-
async_yield_fixture_cache = {}
55-
to_be_torn_down = []
56-
57-
5853
def _deprecate(deprecated, recommended):
5954
def decorator(f):
6055
@functools.wraps(f)
@@ -282,6 +277,13 @@ def pytest_fixture_setup(fixturedef, request):
282277
return not None
283278

284279

280+
def async_yield_fixture_finalizer(coroutine):
281+
_run_inline_callbacks(
282+
tear_it_down,
283+
defer.ensureDeferred(coroutine.__anext__()),
284+
)
285+
286+
285287
@defer.inlineCallbacks
286288
def _async_pytest_fixture_setup(fixturedef, request, mark):
287289
"""Setup an async or async yield fixture."""
@@ -299,15 +301,14 @@ def _async_pytest_fixture_setup(fixturedef, request, mark):
299301
elif mark == 'async_yield_fixture':
300302
coroutine = fixture_function(**kwargs)
301303

302-
finalizer = functools.partial(
303-
_tracking.to_be_torn_down.append,
304-
coroutine,
304+
request.addfinalizer(
305+
functools.partial(
306+
async_yield_fixture_finalizer,
307+
coroutine=coroutine,
308+
),
305309
)
306-
request.addfinalizer(finalizer)
307310

308-
arg_value = yield defer.ensureDeferred(
309-
coroutine.__anext__(),
310-
)
311+
arg_value = yield defer.ensureDeferred(coroutine.__anext__())
311312
else:
312313
raise UnrecognizedCoroutineMarkError.from_mark(mark=mark)
313314

@@ -348,22 +349,6 @@ def in_reactor(d, f, *args):
348349
blockingCallFromThread(_instances.reactor, f, *args)
349350

350351

351-
@pytest.hookimpl(hookwrapper=True)
352-
def pytest_runtest_teardown(item):
353-
"""Tear down collected async yield fixtures."""
354-
yield
355-
356-
deferreds = []
357-
while len(_tracking.to_be_torn_down) > 0:
358-
coroutine = _tracking.to_be_torn_down.pop(0)
359-
deferred = defer.ensureDeferred(coroutine.__anext__())
360-
361-
deferreds.append(deferred)
362-
363-
for deferred in deferreds:
364-
_run_inline_callbacks(tear_it_down, deferred)
365-
366-
367352
def pytest_pyfunc_call(pyfuncitem):
368353
"""Interface to async test call handler."""
369354
# TODO: only handle 'our' tests? what is the point of handling others?

testing/test_basic.py

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -413,40 +413,34 @@ def test_is_function_scope(scope):
413413

414414

415415
@skip_if_no_async_generators()
416-
def test_async_yield_fixture_concurrent_teardown(testdir, cmd_opts):
416+
def test_async_yield_fixture_ordered_teardown(testdir, cmd_opts):
417417
test_file = """
418418
from twisted.internet import reactor, defer
419419
import pytest
420420
import pytest_twisted
421421
422422
423-
here = defer.Deferred()
424-
there = defer.Deferred()
423+
results = []
425424
426-
@pytest_twisted.async_yield_fixture()
427-
async def this():
425+
@pytest.fixture(scope='function')
426+
def sync_fixture():
428427
yield 42
429-
430-
there.callback(None)
431-
reactor.callLater(5, here.cancel)
432-
await here
433-
434-
@pytest_twisted.async_yield_fixture()
435-
async def that():
436-
yield 37
437-
438-
here.callback(None)
439-
reactor.callLater(5, there.cancel)
440-
await there
441-
442-
def test_succeed(this, that):
443-
pass
428+
results.append(2)
429+
430+
@pytest_twisted.async_yield_fixture(scope='function')
431+
async def async_fixture(sync_fixture):
432+
yield sync_fixture
433+
results.append(1)
434+
435+
def test_first(async_fixture):
436+
assert async_fixture == 42
437+
438+
def test_second():
439+
assert results == [1, 2]
444440
"""
445441
testdir.makepyfile(test_file)
446-
# TODO: add a timeout, failure just hangs indefinitely for now
447-
# https://github.com/pytest-dev/pytest/issues/4073
448-
rr = testdir.run(*cmd_opts, timeout=timeout)
449-
assert_outcomes(rr, {"passed": 1})
442+
rr = testdir.run(*cmd_opts)#, timeout=timeout)
443+
assert_outcomes(rr, {"passed": 2})
450444

451445

452446
@skip_if_no_async_generators()

0 commit comments

Comments
 (0)