Skip to content

Commit

Permalink
Clean sys.modules if TYPE_CHECKING=True import fails
Browse files Browse the repository at this point in the history
autodoc now attempts to import with `typing.TYPE_CHECKING = True`
first, and then falls back to `typing.TYPE_CHECKING = False` if that
fails. Unfortunately, the first import can leave behind some
partially-imported modules in `sys.modules` such that the retry fails.

Attempt to work around this by detecting what modules were added to
`sys.modules` by the first attempt and removing them before retrying.

Signed-off-by: Matt Wozniski <mwozniski@bloomberg.net>
  • Loading branch information
godlygeek committed Aug 26, 2023
1 parent 2f6ea14 commit d5bdf5e
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 1 deletion.
8 changes: 7 additions & 1 deletion sphinx/ext/autodoc/importer.py
Expand Up @@ -3,6 +3,7 @@
from __future__ import annotations

import importlib
import sys
import traceback
import typing
from typing import TYPE_CHECKING, Any, Callable, NamedTuple
Expand Down Expand Up @@ -82,13 +83,18 @@ def import_object(modname: str, objpath: list[str], objtype: str = '',
objpath = list(objpath)
while module is None:
try:
orig_modules = frozenset(sys.modules)
try:
# try importing with ``typing.TYPE_CHECKING == True``
typing.TYPE_CHECKING = True
module = import_module(modname, warningiserror=warningiserror)
except ImportError:
# if that fails (e.g. circular import), retry with
# ``typing.TYPE_CHECKING == False``
# ``typing.TYPE_CHECKING == False`` after reverting
# changes made to ``sys.modules`` by the failed try
for m in frozenset(sys.modules) - orig_modules:
sys.modules.pop(m)

typing.TYPE_CHECKING = False
module = import_module(modname, warningiserror=warningiserror)
finally:
Expand Down
1 change: 1 addition & 0 deletions tests/roots/test-ext-autodoc/circular_import/__init__.py
@@ -0,0 +1 @@
from circular_import.c import SomeClass
1 change: 1 addition & 0 deletions tests/roots/test-ext-autodoc/circular_import/a.py
@@ -0,0 +1 @@
X = 42
4 changes: 4 additions & 0 deletions tests/roots/test-ext-autodoc/circular_import/b.py
@@ -0,0 +1,4 @@
import typing

if typing.TYPE_CHECKING:
from circular_import import SomeClass
7 changes: 7 additions & 0 deletions tests/roots/test-ext-autodoc/circular_import/c.py
@@ -0,0 +1,7 @@
import circular_import.a
import circular_import.b


class SomeClass:
assert hasattr(circular_import, "a")
X = circular_import.a.X
2 changes: 2 additions & 0 deletions tests/roots/test-ext-autodoc/index.rst
Expand Up @@ -13,3 +13,5 @@
.. autofunction:: target.overload.sum

.. autofunction:: target.typehints.tuple_args

.. automodule:: circular_import

0 comments on commit d5bdf5e

Please sign in to comment.