| 255 | |
| 256 | |
| 257 | class SphinxDocTestRunner(doctest.DocTestRunner): |
| 258 | def summarize( # type: ignore[override] |
| 259 | self, out: Callable[[str], None], verbose: bool | None = None |
| 260 | ) -> tuple[int, int]: |
| 261 | string_io = StringIO() |
| 262 | old_stdout = sys.stdout |
| 263 | sys.stdout = string_io |
| 264 | try: |
| 265 | res = super().summarize(verbose) |
| 266 | finally: |
| 267 | sys.stdout = old_stdout |
| 268 | out(string_io.getvalue()) |
| 269 | return res |
| 270 | |
| 271 | def _DocTestRunner__patched_linecache_getlines( |
| 272 | self, filename: str, module_globals: Any = None |
| 273 | ) -> Any: |
| 274 | # this is overridden from DocTestRunner adding the try-except below |
| 275 | m = self._DocTestRunner__LINECACHE_FILENAME_RE.match(filename) # type: ignore[attr-defined] |
| 276 | if m and m.group('name') == self.test.name: |
| 277 | try: |
| 278 | example = self.test.examples[int(m.group('examplenum'))] |
| 279 | # because we compile multiple doctest blocks with the same name |
| 280 | # (viz. the group name) this might, for outer stack frames in a |
| 281 | # traceback, get the wrong test which might not have enough examples |
| 282 | except IndexError: |
| 283 | pass |
| 284 | else: |
| 285 | return example.source.splitlines(True) |
| 286 | return self.save_linecache_getlines(filename, module_globals) # type: ignore[attr-defined] |
| 287 | |
| 288 | |
| 289 | # the new builder -- use sphinx-build.py -b doctest to run |