Skip to content

Commit 65a85a5

Browse files
committed
MNT: Compat with pytest>=5.4
1 parent e5f0ae6 commit 65a85a5

File tree

1 file changed

+47
-27
lines changed

1 file changed

+47
-27
lines changed

pytest_doctestplus/plugin.py

Lines changed: 47 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import re
1010
import sys
1111
import warnings
12+
from distutils.version import LooseVersion
1213

1314
import pytest
1415
import six
@@ -22,13 +23,14 @@
2223
def indent(text, prefix):
2324
return '\n'.join([prefix + line for line in text.splitlines()])
2425

26+
PYTEST_LT_5_4 = LooseVersion(pytest.__version__) < LooseVersion('5.4')
27+
2528
comment_characters = {
2629
'.txt': '#',
2730
'.tex': '%',
2831
'.rst': r'\.\.'
2932
}
3033

31-
3234
# For the IGNORE_WARNINGS option, we create a context manager that doesn't
3335
# require us to add any imports to the example list and contains everything
3436
# that is needed to silence warnings.
@@ -154,10 +156,7 @@ def pytest_configure(config):
154156
class DocTestModulePlus(doctest_plugin.DoctestModule):
155157
# pytest 2.4.0 defines "collect". Prior to that, it defined
156158
# "runtest". The "collect" approach is better, because we can
157-
# skip modules altogether that have no doctests. However, we
158-
# need to continue to override "runtest" so that the built-in
159-
# behavior (which doesn't do whitespace normalization or
160-
# handling __doctest_skip__) doesn't happen.
159+
# skip modules altogether that have no doctests.
161160
def collect(self):
162161
# When running directly from pytest we need to make sure that we
163162
# don't accidentally import setup.py!
@@ -194,7 +193,7 @@ def collect(self):
194193
# wrapping the source in a context manager.
195194
if example.options.get(IGNORE_WARNINGS, False):
196195
example.source = ("with _doctestplus_ignore_all_warnings():\n"
197-
+ indent(example.source, ' '))
196+
+ indent(example.source, ' '))
198197
ignore_warnings_context_needed = True
199198

200199
if example.options.get(REMOTE_DATA):
@@ -208,25 +207,34 @@ def collect(self):
208207
yield doctest_plugin.DoctestItem(
209208
test.name, self, runner, test)
210209

211-
class DocTestTextfilePlus(doctest_plugin.DoctestItem, pytest.Module):
212-
# Some pytest plugins such as hypothesis try and access the 'obj'
213-
# attribute, and by default this returns an error for this class
214-
# so we override it here to avoid any issues.
215-
def obj(self):
216-
pass
217-
218-
def runtest(self):
219-
# satisfy `FixtureRequest` constructor...
220-
self.funcargs = {}
221-
fixture_request = doctest_plugin._setup_fixtures(self)
222-
223-
options = get_optionflags(self) | FIX
210+
class DocTestTextfilePlus(doctest_plugin.DoctestTextfile):
224211

225-
doctest.testfile(
226-
str(self.fspath), module_relative=False,
227-
optionflags=options, parser=DocTestParserPlus(),
228-
extraglobs=dict(getfixture=fixture_request.getfixturevalue),
229-
raise_on_error=True, verbose=False, encoding='utf-8')
212+
def collect(self):
213+
from _pytest.doctest import (_get_runner, _get_checker,
214+
_get_continue_on_failure, DoctestItem)
215+
216+
encoding = 'utf-8'
217+
text = self.fspath.read_text(encoding)
218+
filename = str(self.fspath)
219+
name = self.fspath.basename
220+
globs = {"__name__": "__main__"}
221+
222+
optionflags = get_optionflags(self) | FIX
223+
224+
runner = _get_runner(
225+
verbose=False,
226+
optionflags=optionflags,
227+
checker=_get_checker(),
228+
continue_on_failure=_get_continue_on_failure(self.config))
229+
230+
parser = DocTestParserPlus()
231+
test = parser.get_doctest(text, globs, name, filename, 0)
232+
if test.examples:
233+
if PYTEST_LT_5_4:
234+
yield DoctestItem(test.name, self, runner, test)
235+
else:
236+
yield DoctestItem.from_parent(
237+
self, name=test.name, runner=runner, dtest=test)
230238

231239
def reportinfo(self):
232240
"""
@@ -272,7 +280,7 @@ def parse(self, s, name=None):
272280
if ext not in comment_characters:
273281
warnings.warn("file format '{}' is not recognized, assuming "
274282
"'{}' as the comment character."
275-
.format(ext, comment_characters['rst']))
283+
.format(ext, comment_characters['.rst']))
276284
ext = '.rst'
277285
comment_char = comment_characters[ext]
278286

@@ -452,8 +460,14 @@ def pytest_collect_file(self, path, parent):
452460
if path.basename == 'conf.py':
453461
return None
454462

463+
if PYTEST_LT_5_4:
464+
x = self._doctest_module_item_cls(path, parent)
465+
else:
466+
x = self._doctest_textfile_item_cls.from_parent(
467+
parent, fspath=path)
468+
455469
# Don't override the built-in doctest plugin
456-
return self._doctest_module_item_cls(path, parent)
470+
return x
457471
elif any([path.check(fnmatch=pat) for pat in self._file_globs]):
458472
# Ignore generated .rst files
459473
parts = str(path).split(os.path.sep)
@@ -479,7 +493,13 @@ def pytest_collect_file(self, path, parent):
479493

480494
# TODO: Get better names on these items when they are
481495
# displayed in py.test output
482-
return self._doctest_textfile_item_cls(path, parent)
496+
if PYTEST_LT_5_4:
497+
x = self._doctest_textfile_item_cls(path, parent)
498+
else:
499+
x = self._doctest_textfile_item_cls.from_parent(
500+
parent, fspath=path)
501+
502+
return x
483503

484504

485505
class DocTestFinderPlus(doctest.DocTestFinder):

0 commit comments

Comments
 (0)