17
17
import types
18
18
from io import StringIO
19
19
from pathlib import Path
20
- from typing import TYPE_CHECKING , Any , Iterable , Optional , Tuple , Type
20
+ from typing import TYPE_CHECKING , Any , Dict , Iterable , Optional , Tuple , Type
21
21
22
22
import pytest
23
23
24
- import _pytest
25
24
from _pytest import outcomes
26
25
from _pytest .outcomes import OutcomeException
27
26
@@ -43,6 +42,8 @@ def pytest_configure(config: pytest.Config) -> None:
43
42
44
43
Todo: Find a way to make these plugins cooperate without collecting twice.
45
44
"""
45
+ setup ()
46
+
46
47
if config .pluginmanager .has_plugin ("doctest" ):
47
48
config .pluginmanager .set_blocked ("doctest" )
48
49
@@ -65,7 +66,11 @@ def pytest_collect_file(
65
66
def _is_doctest (config : pytest .Config , path : Path , parent : pytest .Collector ) -> bool :
66
67
if path .suffix in (".rst" , ".md" ) and parent .session .isinitpath (path ):
67
68
return True
68
- globs = config .getoption ("doctestglob" ) or ["*.rst" , "*.md" ]
69
+ globs = config .getoption (
70
+ "doctestglob" ,
71
+ default = ["*.rst" , "*.md" ],
72
+ skip = True ,
73
+ )
69
74
for glob in globs :
70
75
if path .match (path_pattern = glob ):
71
76
return True
@@ -181,26 +186,38 @@ def _DocTestRunner__patched_linecache_getlines(
181
186
182
187
class DocTestDocutilsFile (pytest .Module ):
183
188
def collect (self ) -> Iterable ["DoctestItem" ]:
184
- setup ()
189
+ import _pytest .doctest
190
+ from _pytest .doctest import DoctestItem
185
191
186
- encoding = self .config .getini ("doctest_encoding" )
192
+ try :
193
+ encoding = self .config .getini ("doctest_encoding" )
194
+ except (KeyError , ValueError ):
195
+ encoding = "utf-8"
187
196
text = self .fspath .read_text (encoding )
188
197
189
198
# Uses internal doctest module parsing mechanism.
190
199
finder = DocutilsDocTestFinder ()
191
200
192
- optionflags = _pytest .doctest .get_optionflags (self ) # type: ignore
201
+ try :
202
+ optionflags = _pytest .doctest .get_optionflags (self ) # type: ignore
203
+ except ValueError :
204
+ optionflags = 0
205
+
206
+ try :
207
+ continue_on_failure = (
208
+ _pytest .doctest ._get_continue_on_failure ( # type:ignore
209
+ self .config
210
+ )
211
+ )
212
+ except ValueError :
213
+ continue_on_failure = True
193
214
194
215
runner = _get_runner (
195
216
verbose = False ,
196
217
optionflags = optionflags ,
197
218
checker = _pytest .doctest ._get_checker (),
198
- continue_on_failure = _pytest .doctest ._get_continue_on_failure ( # type:ignore
199
- self .config
200
- ),
219
+ continue_on_failure = continue_on_failure ,
201
220
)
202
- from _pytest .doctest import DoctestItem
203
-
204
221
for test in finder .find (
205
222
text ,
206
223
str (self .fspath ),
@@ -209,3 +226,21 @@ def collect(self) -> Iterable["DoctestItem"]:
209
226
yield DoctestItem .from_parent (
210
227
self , name = test .name , runner = runner , dtest = test # type: ignore
211
228
)
229
+
230
+
231
+ @pytest .fixture (scope = "session" )
232
+ def doctest_namespace () -> Dict [str , Any ]:
233
+ """Fixture that returns a :py:class:`dict` that will be injected into the
234
+ namespace of doctests.
235
+
236
+ Usually this fixture is used in conjunction with another ``autouse`` fixture:
237
+
238
+ .. code-block:: python
239
+
240
+ @pytest.fixture(autouse=True)
241
+ def add_np(doctest_namespace):
242
+ doctest_namespace["np"] = numpy
243
+
244
+ For more details: :ref:`doctest_namespace`.
245
+ """
246
+ return {}
0 commit comments