From 891e0295183d6cd8ca8b6e58af65c397cb7e2197 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Wed, 2 Mar 2016 12:43:57 +0000 Subject: [PATCH 1/4] Add a new doctest_namespace fixture This fixture can be used to inject names into the namespace in which your doctests run. --- AUTHORS | 1 + CHANGELOG.rst | 3 ++- _pytest/doctest.py | 13 +++++++++++ doc/en/doctest.rst | 25 +++++++++++++++++++++ testing/test_doctest.py | 50 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 91 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index b9868ef2a..47f137892 100644 --- a/AUTHORS +++ b/AUTHORS @@ -59,6 +59,7 @@ Marc Schlaich Mark Abramowitz Markus Unterwaditzer Martijn Faassen +Matt Williams Michael Aquilina Michael Birtwell Michael Droettboom diff --git a/CHANGELOG.rst b/CHANGELOG.rst index b5b400f9c..a203ae2c8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,7 +3,8 @@ **New Features** -* +* New ``doctest_namespace`` fixture for injecting names into the + namespace in which your doctests run. * diff --git a/_pytest/doctest.py b/_pytest/doctest.py index a57f7a494..4050d1ba7 100644 --- a/_pytest/doctest.py +++ b/_pytest/doctest.py @@ -71,6 +71,8 @@ class DoctestItem(pytest.Item): if self.dtest is not None: self.fixture_request = _setup_fixtures(self) globs = dict(getfixture=self.fixture_request.getfuncargvalue) + for name, value in self.fixture_request.getfuncargvalue('doctest_namespace').items(): + globs[name] = value self.dtest.globs.update(globs) def runtest(self): @@ -159,6 +161,9 @@ class DoctestTextfile(DoctestItem, pytest.Module): if '__name__' not in globs: globs['__name__'] = '__main__' + for name, value in fixture_request.getfuncargvalue('doctest_namespace').items(): + globs[name] = value + optionflags = get_optionflags(self) runner = doctest.DebugRunner(verbose=0, optionflags=optionflags, checker=_get_checker()) @@ -288,3 +293,11 @@ def _get_allow_bytes_flag(): """ import doctest return doctest.register_optionflag('ALLOW_BYTES') + + +@pytest.fixture(scope='session') +def doctest_namespace(): + """ + Inject names into the doctest namespace. + """ + return dict() diff --git a/doc/en/doctest.rst b/doc/en/doctest.rst index f13752e66..4798d9714 100644 --- a/doc/en/doctest.rst +++ b/doc/en/doctest.rst @@ -102,4 +102,29 @@ itself:: >>> get_unicode_greeting() # doctest: +ALLOW_UNICODE 'Hello' +The 'doctest_namespace' fixture +------------------------------- +The ``doctest_namespace`` fixture can be used to inject items into the +namespace in which your doctests run. It is intended to be used within +your own fixtures to provide the tests that use them with context. + +``doctest_namespace`` is a standard ``dict`` object into which you +place the objects you want to appear in the doctest namespace:: + + # content of conftest.py + import numpy + @pytest.fixture(autouse=True) + def add_np(doctest_namespace): + doctest_namespace['np'] = numpy + +which can then be used in your doctests directly:: + + # content of numpy.py + def arange(): + """ + >>> a = np.arange(10) + >>> len(a) + 10 + """ + pass diff --git a/testing/test_doctest.py b/testing/test_doctest.py index a4821ee4c..d104d98d3 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -713,3 +713,53 @@ class TestDoctestAutoUseFixtures: result = testdir.runpytest('--doctest-modules') assert 'FAILURES' not in str(result.stdout.str()) result.stdout.fnmatch_lines(['*=== 1 passed in *']) + + +class TestDoctestNamespaceFixture: + + SCOPES = ['module', 'session', 'class', 'function'] + + @pytest.mark.parametrize('scope', SCOPES) + def test_namespace_doctestfile(self, testdir, scope): + """ + Check that inserting something into the namespace works in a + simple text file doctest + """ + testdir.makeconftest(""" + import pytest + import contextlib + + @pytest.fixture(autouse=True, scope="{scope}") + def add_contextlib(doctest_namespace): + doctest_namespace['cl'] = contextlib + """.format(scope=scope)) + p = testdir.maketxtfile(""" + >>> print(cl.__name__) + contextlib + """) + reprec = testdir.inline_run(p) + reprec.assertoutcome(passed=1) + + @pytest.mark.parametrize('scope', SCOPES) + def test_namespace_pyfile(self, testdir, scope): + """ + Check that inserting something into the namespace works in a + simple Python file docstring doctest + """ + testdir.makeconftest(""" + import pytest + import contextlib + + @pytest.fixture(autouse=True, scope="{scope}") + def add_contextlib(doctest_namespace): + doctest_namespace['cl'] = contextlib + """.format(scope=scope)) + p = testdir.makepyfile(""" + def foo(): + ''' + >>> print(cl.__name__) + contextlib + ''' + """) + reprec = testdir.inline_run(p, "--doctest-modules") + reprec.assertoutcome(passed=1) From 6dd2ff5332b735487743a92b280ad276164536b1 Mon Sep 17 00:00:00 2001 From: Matt Williams Date: Wed, 2 Mar 2016 13:02:15 +0000 Subject: [PATCH 2/4] Correct indentation in documentation --- doc/en/doctest.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/doctest.rst b/doc/en/doctest.rst index 4798d9714..32e37008f 100644 --- a/doc/en/doctest.rst +++ b/doc/en/doctest.rst @@ -115,8 +115,8 @@ place the objects you want to appear in the doctest namespace:: # content of conftest.py import numpy @pytest.fixture(autouse=True) - def add_np(doctest_namespace): - doctest_namespace['np'] = numpy + def add_np(doctest_namespace): + doctest_namespace['np'] = numpy which can then be used in your doctests directly:: From 2e02a1c370f7b42baf3a2e2ab9ff0b314ef15cdd Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 2 Mar 2016 23:30:42 -0300 Subject: [PATCH 3/4] Give proper credit for PR #1428 --- CHANGELOG.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a203ae2c8..b53379e17 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,7 @@ * New ``doctest_namespace`` fixture for injecting names into the namespace in which your doctests run. + Thanks `@milliams`_ for the complete PR (`#1428`_). * @@ -29,6 +30,11 @@ * +.. _@milliams: https://github.com/milliams + +.. _#1428: https://github.com/pytest-dev/pytest/pull/1428 + + 2.9.0 ===== From 28937a5cd90c7d4faf65cf9933d5e8deff6c1fc6 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 2 Mar 2016 23:37:51 -0300 Subject: [PATCH 4/4] Add versionadded directive to doctest_namespace section --- doc/en/doctest.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/en/doctest.rst b/doc/en/doctest.rst index 32e37008f..64b5621d4 100644 --- a/doc/en/doctest.rst +++ b/doc/en/doctest.rst @@ -105,6 +105,8 @@ itself:: The 'doctest_namespace' fixture ------------------------------- +.. versionadded:: 2.10 + The ``doctest_namespace`` fixture can be used to inject items into the namespace in which your doctests run. It is intended to be used within your own fixtures to provide the tests that use them with context.