@@ -194,6 +194,24 @@ def setup() -> dict[str, t.Any]:
194194master = None
195195
196196parser = doctest .DocTestParser ()
197+ _DIRECTIVES_READY = False
198+ _REQUIRED_DIRECTIVES = ("doctest" , "testsetup" , "testcleanup" , "tab" )
199+
200+
201+ def _directive_registry () -> dict [str , t .Any ]:
202+ """Return docutils directive registry with typing info."""
203+ return t .cast (dict [str , t .Any ], directives .__dict__ ["_directives" ])
204+
205+
206+ def _ensure_directives_registered () -> None :
207+ """Register doctest-related directives once per interpreter."""
208+ global _DIRECTIVES_READY
209+ registry = _directive_registry ()
210+ missing = any (name not in registry for name in _REQUIRED_DIRECTIVES )
211+ if _DIRECTIVES_READY and not missing :
212+ return
213+ setup ()
214+ _DIRECTIVES_READY = True
197215
198216
199217class DocTestFinderNameDoesNotExist (ValueError ):
@@ -226,6 +244,7 @@ def __init__(
226244 DocTest). The signature for this factory function should match the signature
227245 of the DocTest constructor.
228246 """
247+ _ensure_directives_registered ()
229248 self ._parser = parser
230249 self ._verbose = verbose
231250
@@ -455,6 +474,7 @@ def testdocutils(
455474
456475 # Keep the absolute file paths. This is needed for Include directies to work.
457476 # The absolute path will be applied to source_path when creating the docutils doc.
477+ _ensure_directives_registered ()
458478 text , _ = doctest ._load_testfile ( # type: ignore
459479 filename ,
460480 package ,
@@ -567,6 +587,7 @@ def _test() -> int:
567587 options |= doctest .FAIL_FAST
568588 for filename in testfiles :
569589 if filename .endswith ((".rst" , ".md" )) or args .docutils :
590+ _ensure_directives_registered ()
570591 failures , _ = testdocutils ( # type: ignore[misc,unused-ignore]
571592 filename ,
572593 module_relative = False ,
0 commit comments