Skip to content

Commit

Permalink
Merge pull request #280 from bsipocz/doctest-requires-all
Browse files Browse the repository at this point in the history
ENH: adding doctest-requires-all directive
  • Loading branch information
bsipocz authored Jan 24, 2025
2 parents 81fe4fd + 74cebb8 commit d620c96
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

- Fixing compatibility with pytest-asyncio. [#278]

- Adding new directive ``doctest-requires-all`` to conditionally skip all
doctests in narrative documentations based on availability of
dependencies. [#280]

- Versions of Python <3.9 are no longer supported. [#274]

1.3.0 (2024-11-25)
Expand Down
3 changes: 3 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,9 @@ the package's ``setup.cfg`` file. The syntax for this option is a list of

Multiple requirements can be specified if separated by semicolons.

It is also possible to conditionally skip all the doctests in a narrative
documentation with ``doctest-requires-all``.

Remote Data
~~~~~~~~~~~

Expand Down
14 changes: 13 additions & 1 deletion pytest_doctestplus/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,10 @@ class DocTestParserPlus(doctest.DocTestParser):
doctest chunk if the given modules/packages are not
installed.
- ``.. doctest-requires-all:: module1, module2``: Skip all subsequent
doctest chunks if the given modules/packages are not
installed.
- ``.. doctest-skip-all``: Skip all subsequent doctests.
- ``.. doctest-remote-data::``: Skip the next doctest chunk if
Expand Down Expand Up @@ -422,10 +426,18 @@ def parse(self, s, name=None):

if isinstance(entry, str) and entry:
required = []
required_all = []
skip_next = False
lines = entry.strip().splitlines()
requires_all_match = [re.match(
fr'{comment_char}\s+doctest-requires-all\s*::\s+(.*)', x) for x in lines]
if any(requires_all_match):
required_all = [re.split(r'\s*[,\s]\s*', match.group(1)) for match in requires_all_match if match][0]

required_modules_all = DocTestFinderPlus.check_required_modules(required_all)

if any(re.match(
f'{comment_char} doctest-skip-all', x.strip()) for x in lines):
f'{comment_char} doctest-skip-all', x.strip()) for x in lines) or not required_modules_all:
skip_all = True
continue

Expand Down
1 change: 1 addition & 0 deletions pytest_doctestplus/sphinx/doctestplus.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class DoctestRequiresDirective(DoctestSkipDirective):
def setup(app):

app.add_directive('doctest-requires', DoctestRequiresDirective)
app.add_directive('doctest-requires-all', DoctestRequiresDirective)
app.add_directive('doctest-skip', DoctestSkipDirective)
app.add_directive('doctest-skip-all', DoctestSkipDirective)
app.add_directive('doctest', DoctestSkipDirective, override=True)
Expand Down
23 changes: 23 additions & 0 deletions tests/test_doctestplus.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,29 @@ def test_requires(testdir):
testdir.inline_run(p, '--doctest-plus', '--doctest-rst').assertoutcome(skipped=1)


def test_requires_all(testdir):
testdir.makeini(
"""
[pytest]
doctestplus = enabled
""")

# should be ignored
p = testdir.makefile(
'.rst',
"""
.. doctest-requires-all:: foobar
>>> import foobar
This is a narrative line, before another doctest snippet
>>> import foobar
"""
)
testdir.inline_run(p, '--doctest-plus', '--doctest-rst').assertoutcome(skipped=1)


def test_ignore_warnings_module(testdir):

# First check that we get a warning if we don't add the IGNORE_WARNINGS
Expand Down

0 comments on commit d620c96

Please sign in to comment.