1- """
1+ """Sphinx pytest plugin.
2+
23http://www.sphinx-doc.org/en/stable/ext/doctest.html
3- https://github.com/sphinx-doc/sphinx/blob/master/sphinx/ext/doctest.py
4+ https://github.com/sphinx-doc/sphinx/blob/master/sphinx/ext/doctest.py.
45
56* TODO
67** CLEANUP: use the sphinx directive parser from the sphinx project
78"""
89
10+ from __future__ import annotations
11+
912import doctest
1013import enum
1114import re
1215import sys
1316import textwrap
1417import traceback
18+ from collections .abc import Iterator
1519from pathlib import Path
1620from typing import TYPE_CHECKING
1721from typing import Any
18- from typing import Dict
19- from typing import Iterator
20- from typing import List
21- from typing import Optional
22- from typing import Tuple
23- from typing import Union
2422
2523import _pytest .doctest
2624import pytest
@@ -60,12 +58,12 @@ class SphinxDoctestDirectives(enum.Enum):
6058
6159
6260def pytest_collect_file (
63- file_path : Path , parent : Union [ Session , Package ]
64- ) -> Optional [ Union [ " SphinxDoctestModule" , " SphinxDoctestTextfile" ]] :
61+ file_path : Path , parent : Session | Package
62+ ) -> SphinxDoctestModule | SphinxDoctestTextfile | None :
6563 config = parent .config
6664 if file_path .suffix == ".py" :
6765 if config .option .doctestmodules :
68- mod : Union [ " SphinxDoctestModule" , " SphinxDoctestTextfile" ] = (
66+ mod : SphinxDoctestModule | SphinxDoctestTextfile = (
6967 SphinxDoctestModule .from_parent (parent , path = file_path )
7068 )
7169 return mod
@@ -74,10 +72,10 @@ def pytest_collect_file(
7472 return None
7573
7674
77- GlobDict = Dict [str , Any ]
75+ GlobDict = dict [str , Any ]
7876
7977
80- def _is_doctest (config : Config , path : Path , parent : Union [ Session , Package ] ) -> bool :
78+ def _is_doctest (config : Config , path : Path , parent : Session | Package ) -> bool :
8179 if path .suffix in (".txt" , ".rst" ) and parent .session .isinitpath (path ):
8280 return True
8381 globs = config .getoption ("doctestglob" ) or ["test*.txt" ]
@@ -108,7 +106,7 @@ def _is_doctest(config: Config, path: Path, parent: Union[Session, Package]) ->
108106
109107def _split_into_body_and_options (
110108 section_content : str ,
111- ) -> Tuple [str , Optional [ str ], Dict [int , bool ]]:
109+ ) -> tuple [str , str | None , dict [int , bool ]]:
112110 """Parse the the full content of a directive and split it.
113111
114112 It is split into a string, where the options (:options:, :hide: and
@@ -184,8 +182,8 @@ def _split_into_body_and_options(
184182
185183
186184def _get_next_textoutputsections (
187- sections : List [ " Section" ], index : int
188- ) -> Iterator [" Section" ]:
185+ sections : list [ Section ], index : int
186+ ) -> Iterator [Section ]:
189187 """Yield successive TESTOUTPUT sections."""
190188 for j in range (index , len (sections )):
191189 section = sections [j ]
@@ -195,7 +193,7 @@ def _get_next_textoutputsections(
195193 break
196194
197195
198- SectionGroups = Optional [ List [ str ]]
196+ SectionGroups = list [ str ] | None
199197
200198
201199class Section :
@@ -221,7 +219,7 @@ def __init__(
221219 self .options = options
222220
223221
224- def get_sections (docstring : str ) -> List [ Union [ Any , Section ] ]:
222+ def get_sections (docstring : str ) -> list [ Any | Section ]:
225223 lines = textwrap .dedent (docstring ).splitlines ()
226224 sections = []
227225
@@ -271,11 +269,11 @@ def add_match(
271269
272270
273271def docstring2examples (
274- docstring : str , globs : Optional [ GlobDict ] = None
275- ) -> List [ Union [ Any , doctest .Example ] ]:
276- """
277- Parse all sphinx test directives in the docstring and create a
278- list of examples.
272+ docstring : str , globs : GlobDict | None = None
273+ ) -> list [ Any | doctest .Example ]:
274+ """Parse all sphinx test directives in the docstring.
275+
276+ This function also creates a list of examples that are returned .
279277 """
280278 # TODO subclass doctest.DocTestParser instead?
281279
@@ -285,11 +283,11 @@ def docstring2examples(
285283 sections = get_sections (docstring )
286284
287285 def get_testoutput_section_data (
288- section : " Section" ,
289- ) -> Tuple [str , Dict [int , bool ], int , Optional [ Any ] ]:
286+ section : Section ,
287+ ) -> tuple [str , dict [int , bool ], int , Any | None ]:
290288 want = section .body
291289 exc_msg = None
292- options : Dict [int , bool ] = {}
290+ options : dict [int , bool ] = {}
293291
294292 if section .skipif_expr and eval (section .skipif_expr , globs ):
295293 want = ""
@@ -344,20 +342,19 @@ def get_testoutput_section_data(
344342
345343
346344class SphinxDocTestRunner (doctest .DebugRunner ):
347- """
348- overwrite doctest.DocTestRunner.__run, since it uses 'single' for the
349- `compile` function instead of 'exec'.
345+ """Overwrite `doctest.DocTestRunner.__run`.
346+
347+ since it uses 'single' for the `compile` function instead of 'exec'.
350348 """
351349
352- _checker : " doctest.OutputChecker"
353- _fakeout : " _SpoofOut"
354- debugger : " pdb.Pdb"
350+ _checker : doctest .OutputChecker
351+ _fakeout : _SpoofOut
352+ debugger : pdb .Pdb
355353
356354 def _DocTestRunner__run (
357- self , test : doctest .DocTest , compileflags : int , out : " _Out"
355+ self , test : doctest .DocTest , compileflags : int , out : _Out
358356 ) -> doctest .TestResults :
359- """
360- Run the examples in `test`.
357+ """Run the examples in `test`.
361358
362359 Write the outcome of each example with one of the
363360 `DocTestRunner.report_*` methods, using the writer function
@@ -409,7 +406,7 @@ def _DocTestRunner__run(
409406 # Use a special filename for compile(), so we can retrieve
410407 # the source code during interactive debugging (see
411408 # __patched_linecache_getlines).
412- filename = "<doctest %s[%d]>" % ( test .name , examplenum )
409+ filename = f "<doctest { test .name } [ { examplenum } ]>"
413410
414411 # Run the example in the given context (globs), and record
415412 # any exception that gets raised. (But don't intercept
@@ -484,7 +481,7 @@ def _DocTestRunner__run(
484481 )
485482 failures += 1
486483 else :
487- assert False , ( "unknown outcome" , outcome )
484+ raise AssertionError (( "unknown outcome" , outcome ) )
488485
489486 if failures and self .optionflags & doctest .FAIL_FAST :
490487 break
@@ -504,7 +501,7 @@ class SphinxDocTestParser:
504501 def get_doctest (
505502 self ,
506503 docstring : str ,
507- globs : Dict [str , Any ],
504+ globs : dict [str , Any ],
508505 name : str ,
509506 filename : str ,
510507 lineno : int ,
@@ -563,7 +560,7 @@ def collect(self) -> Iterator[_pytest.doctest.DoctestItem]:
563560 )
564561 except ImportError :
565562 if self .config .getvalue ("doctest_ignore_import_errors" ):
566- pytest .skip ("unable to import module %r" % self .path )
563+ pytest .skip (f "unable to import module { self .path !r } " )
567564 else :
568565 raise
569566 optionflags = _pytest .doctest .get_optionflags (self .config ) # type:ignore
0 commit comments