2 new commits in pytest: https://bitbucket.org/hpk42/pytest/commits/5968d75acef9/ Changeset: 5968d75acef9 User: hpk42 Date: 2013-09-30 13:42:39 Summary: strike keyword argument in favour of new pytest.yield_fixture decorator Affected #: 5 files
diff -r 7da5c02ece03592164e4e681ab7463de2a65cedb -r 5968d75acef96230be6fe6b8d0bd656e1628a731 CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -16,9 +16,12 @@ new features: -- experimentally allow fixture functions to "yield" instead of "return" - a fixture value, allowing direct integration with with-context managers - in fixture functions and avoiding registration of finalization callbacks. +- experimentally introduce a new pytest.yield_fixture decorator which + has exactly the same parameters as pytest.fixture but expects + a ``yield`` statement instead of a ``return statement`` from fixture functions. + This allows direct integration with with-context managers + in fixture functions and generally avoids registering of finalization callbacks + in favour of treating the "after-yield" as teardown code. Thanks Andreas Pelme, Vladimir Keleshev, Floris Bruynooghe, Ronny Pfannschmidt and many others for discussions. diff -r 7da5c02ece03592164e4e681ab7463de2a65cedb -r 5968d75acef96230be6fe6b8d0bd656e1628a731 _pytest/python.py --- a/_pytest/python.py +++ b/_pytest/python.py @@ -40,7 +40,7 @@ return function -def fixture(scope="function", params=None, autouse=False, yieldctx=False): +def fixture(scope="function", params=None, autouse=False): """ (return a) decorator to mark a fixture factory function. This decorator can be used (with or or without parameters) to define @@ -62,16 +62,29 @@ can see it. If False (the default) then an explicit reference is needed to activate the fixture. - :arg yieldctx: if True, the fixture function yields a fixture value. - Code after such a ``yield`` statement is treated as - teardown code. """ if callable(scope) and params is None and autouse == False: # direct decoration return FixtureFunctionMarker( - "function", params, autouse, yieldctx)(scope) + "function", params, autouse)(scope) else: - return FixtureFunctionMarker(scope, params, autouse, yieldctx) + return FixtureFunctionMarker(scope, params, autouse) + +def yield_fixture(scope="function", params=None, autouse=False): + """ (return a) decorator to mark a yield-fixture factory function + (EXPERIMENTAL). + + This takes the same arguments as :py:func:`pytest.fixture` but + expects a fixture function to use a ``yield`` instead of a ``return`` + statement to provide a fixture. See + http://pytest.org/en/latest/yieldfixture.html for more info. + """ + if callable(scope) and params is None and autouse == False: + # direct decoration + return FixtureFunctionMarker( + "function", params, autouse, yieldctx=True)(scope) + else: + return FixtureFunctionMarker(scope, params, autouse, yieldctx=True) defaultfuncargprefixmarker = fixture() @@ -136,6 +149,7 @@ raises.Exception = pytest.fail.Exception return { 'fixture': fixture, + 'yield_fixture': yield_fixture, 'raises' : raises, 'collect': { 'Module': Module, 'Class': Class, 'Instance': Instance, @@ -1675,7 +1689,7 @@ if yieldctx: if not is_generator(fixturefunc): fail_fixturefunc(fixturefunc, - msg="yieldctx=True requires yield statement") + msg="yield_fixture requires yield statement in function") iter = fixturefunc(**kwargs) next = getattr(iter, "__next__", None) if next is None: @@ -1688,7 +1702,7 @@ pass else: fail_fixturefunc(fixturefunc, - "fixture function has more than one 'yield'") + "yield_fixture function has more than one 'yield'") request.addfinalizer(teardown) else: res = fixturefunc(**kwargs) diff -r 7da5c02ece03592164e4e681ab7463de2a65cedb -r 5968d75acef96230be6fe6b8d0bd656e1628a731 doc/en/fixture.txt --- a/doc/en/fixture.txt +++ b/doc/en/fixture.txt @@ -276,8 +276,8 @@ of fixture setup. Note that pytest-2.4 introduced an experimental alternative -:ref:`yield fixture mechanism <yieldctx>` for easier context manager integration -and more linear writing of teardown code. +:ref:`yield fixture mechanism <yieldfixture>` for easier context manager +integration and more linear writing of teardown code. .. _`request-context`: diff -r 7da5c02ece03592164e4e681ab7463de2a65cedb -r 5968d75acef96230be6fe6b8d0bd656e1628a731 doc/en/yieldfixture.txt --- a/doc/en/yieldfixture.txt +++ b/doc/en/yieldfixture.txt @@ -1,5 +1,5 @@ -.. _yieldctx: +.. _yieldfixture: Fixture functions using "yield" / context manager integration --------------------------------------------------------------- @@ -16,10 +16,9 @@ "yielding" fixture values is an experimental feature and its exact declaration may change later but earliest in a 2.5 release. You can thus - safely use this feature in the 2.4 series but may need to adapt your - fixtures later. Test functions themselves will not need to change - (they can be completely ignorant of the return/yield modes of - fixture functions). + safely use this feature in the 2.4 series but may need to adapt later. + Test functions themselves will not need to change (as a general + feature, they are ignorant of how fixtures are setup). Let's look at a simple standalone-example using the new ``yield`` syntax:: @@ -27,7 +26,7 @@ import pytest - @pytest.fixture(yieldctx=True) + @pytest.yield_fixture def passwd(): print ("\nsetup before yield") f = open("/etc/passwd") @@ -62,7 +61,7 @@ import pytest - @pytest.fixture(yieldctx=True) + @pytest.yield_fixture def passwd(): with open("/etc/passwd") as f: yield f.readlines() diff -r 7da5c02ece03592164e4e681ab7463de2a65cedb -r 5968d75acef96230be6fe6b8d0bd656e1628a731 testing/python/fixture.py --- a/testing/python/fixture.py +++ b/testing/python/fixture.py @@ -1980,7 +1980,7 @@ def test_simple(self, testdir): testdir.makepyfile(""" import pytest - @pytest.fixture(yieldctx=True) + @pytest.yield_fixture def arg1(): print ("setup") yield 1 @@ -2004,7 +2004,7 @@ def test_scoped(self, testdir): testdir.makepyfile(""" import pytest - @pytest.fixture(scope="module", yieldctx=True) + @pytest.yield_fixture(scope="module") def arg1(): print ("setup") yield 1 @@ -2025,7 +2025,7 @@ def test_setup_exception(self, testdir): testdir.makepyfile(""" import pytest - @pytest.fixture(scope="module", yieldctx=True) + @pytest.yield_fixture(scope="module") def arg1(): pytest.fail("setup") yield 1 @@ -2041,7 +2041,7 @@ def test_teardown_exception(self, testdir): testdir.makepyfile(""" import pytest - @pytest.fixture(scope="module", yieldctx=True) + @pytest.yield_fixture(scope="module") def arg1(): yield 1 pytest.fail("teardown") @@ -2057,7 +2057,7 @@ def test_yields_more_than_one(self, testdir): testdir.makepyfile(""" import pytest - @pytest.fixture(scope="module", yieldctx=True) + @pytest.yield_fixture(scope="module") def arg1(): yield 1 yield 2 @@ -2074,7 +2074,7 @@ def test_no_yield(self, testdir): testdir.makepyfile(""" import pytest - @pytest.fixture(scope="module", yieldctx=True) + @pytest.yield_fixture(scope="module") def arg1(): return 1 def test_1(arg1): @@ -2082,9 +2082,8 @@ """) result = testdir.runpytest("-s") result.stdout.fnmatch_lines(""" - *yieldctx*requires*yield* - *yieldctx=True* + *yield_fixture*requires*yield* + *yield_fixture* *def arg1* """) - https://bitbucket.org/hpk42/pytest/commits/6a3d8793bf5f/ Changeset: 6a3d8793bf5f User: hpk42 Date: 2013-09-30 13:56:54 Summary: disallow yield in non-yield-fixtures for now. This is an incompataibility but we want to prepare for possibly merging fixture and yield_fixture some day. Affected #: 3 files diff -r 5968d75acef96230be6fe6b8d0bd656e1628a731 -r 6a3d8793bf5fe8f9be829bddb8bf1e95ee183323 CHANGELOG --- a/CHANGELOG +++ b/CHANGELOG @@ -14,12 +14,18 @@ - the pytest_plugin_unregister hook wasn't ever properly called and there is no known implementation of the hook - so it got removed. +- pytest.fixture-decorated functions cannot be generators (i.e. use yield) anymore. + This change might be reversed in 2.4.1 if it causes unforeseen real-life issues. + However, you can always write and return an inner function/generator + and change the fixture consumer to iterate over the returned generator. + This change was done in lieu of the new ``pytest.yield_fixture`` decorator, see below. + new features: -- experimentally introduce a new pytest.yield_fixture decorator which - has exactly the same parameters as pytest.fixture but expects +- experimentally introduce a new ``pytest.yield_fixture`` decorator which + accepts exactly the same parameters as pytest.fixture but mandates a ``yield`` statement instead of a ``return statement`` from fixture functions. - This allows direct integration with with-context managers + This allows direct integration with "with-style" context managers in fixture functions and generally avoids registering of finalization callbacks in favour of treating the "after-yield" as teardown code. Thanks Andreas Pelme, Vladimir Keleshev, Floris Bruynooghe, Ronny Pfannschmidt diff -r 5968d75acef96230be6fe6b8d0bd656e1628a731 -r 6a3d8793bf5fe8f9be829bddb8bf1e95ee183323 _pytest/python.py --- a/_pytest/python.py +++ b/_pytest/python.py @@ -1705,6 +1705,11 @@ "yield_fixture function has more than one 'yield'") request.addfinalizer(teardown) else: + if is_generator(fixturefunc): + fail_fixturefunc(fixturefunc, + msg="pytest.fixture functions cannot use ``yield``. " + "Instead write and return an inner function/generator " + "and let the consumer call and iterate over it.") res = fixturefunc(**kwargs) return res diff -r 5968d75acef96230be6fe6b8d0bd656e1628a731 -r 6a3d8793bf5fe8f9be829bddb8bf1e95ee183323 testing/python/fixture.py --- a/testing/python/fixture.py +++ b/testing/python/fixture.py @@ -2087,3 +2087,18 @@ *def arg1* """) + def test_yield_not_allowed_in_non_yield(self, testdir): + testdir.makepyfile(""" + import pytest + @pytest.fixture(scope="module") + def arg1(): + yield 1 + def test_1(arg1): + pass + """) + result = testdir.runpytest("-s") + result.stdout.fnmatch_lines(""" + *fixture*cannot use*yield* + *def arg1* + """) + Repository URL: https://bitbucket.org/hpk42/pytest/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email. _______________________________________________ pytest-commit mailing list pytest-commit@python.org https://mail.python.org/mailman/listinfo/pytest-commit