demonstrate ExitStack assuming connect returns a context manager

This commit is contained in:
Thomas Grainger 2019-07-15 14:05:19 +01:00
parent c224c4f1d6
commit a96710dd8a
No known key found for this signature in database
GPG Key ID: E452A1247BAC1A88
1 changed files with 9 additions and 11 deletions

View File

@ -418,16 +418,10 @@ close all resources created by a fixture even if one of them fails to be created
@pytest.fixture @pytest.fixture
def equipments(): def equipments():
with contextlib.ExitStack() as stack: with contextlib.ExitStack() as stack:
r = [] yield [stack.enter_context(connect(port)) for port in ("C1", "C3", "C28")]
for port in ("C1", "C3", "C28"):
equip = connect(port)
stack.callback(equip.disconnect)
r.append(equip)
yield r
In the example above, if ``"C28"`` fails with an exception, ``"C1"`` and ``"C3"`` will still In the example above, if ``"C28"`` fails with an exception, ``"C1"`` and ``"C3"`` will still
be properly closed. Of course, if an exception happens before the finalize function is be properly closed.
registered then it will not be executed.
Note that if an exception happens during the *setup* code (before the ``yield`` keyword), the Note that if an exception happens during the *setup* code (before the ``yield`` keyword), the
*teardown* code (after the ``yield``) will not be called. *teardown* code (after the ``yield``) will not be called.
@ -464,6 +458,7 @@ Here's the ``equipments`` fixture changed to use ``addfinalizer`` for cleanup:
# content of test_yield3.py # content of test_yield3.py
import contextlib import contextlib
import functools
import pytest import pytest
@ -474,14 +469,17 @@ Here's the ``equipments`` fixture changed to use ``addfinalizer`` for cleanup:
def equipments(request): def equipments(request):
r = [] r = []
for port in ("C1", "C3", "C28"): for port in ("C1", "C3", "C28"):
equip = connect(port) cm = connect(port)
request.addfinalizer(equip.disconnect) equip = cm.__enter__()
request.addfinalizer(functools.partial(cm.__exit__, None, None, None))
r.append(equip) r.append(equip)
return r return r
Both ``yield`` and ``addfinalizer`` methods work similarly by calling their code after the test Both ``yield`` and ``addfinalizer`` methods work similarly by calling their code after the test
ends. ends. Of course, if an exception happens before the finalize function is registered then it
will not be executed.
.. _`request-context`: .. _`request-context`: