Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Comment on lines +453 to +455
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix formatting to reflect typical real use case.

Suggested change
This is a narrative line, before another doctest snippet
>>> import foobar
This is a narrative line, before another doctest snippet::
>>> import foobar

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not matter, all the snippets should be collected no matter if there are :: or correct number of spaces before the >>>.

"""
)
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
Loading