mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
autodoc: Reset `sys.modules
` on partial import failure (#11645)
If importing with ``TYPE_CHECKING is True`` fails, reset the state of ``sys.modules`` so that the attempt with ``TYPE_CHECKING is False`` may succeed. Co-authored-by: Adam Turner <9087854+aa-turner@users.noreply.github.com>
This commit is contained in:
parent
e494baa9dd
commit
8248be31db
5
CHANGES
5
CHANGES
@ -16,6 +16,11 @@ Features added
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* #11645: Fix a regression preventing autodoc from importing modules within
|
||||
packages that make use of ``if typing.TYPE_CHECKING:`` to guard circular
|
||||
imports needed by type checkers.
|
||||
Patch by Matt Wozniski.
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
import sys
|
||||
import traceback
|
||||
import typing
|
||||
from typing import TYPE_CHECKING, Any, Callable, NamedTuple
|
||||
@ -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 [m for m in sys.modules if m not in orig_modules]:
|
||||
sys.modules.pop(m)
|
||||
|
||||
typing.TYPE_CHECKING = False
|
||||
module = import_module(modname, warningiserror=warningiserror)
|
||||
finally:
|
||||
|
1
tests/roots/test-ext-autodoc/circular_import/__init__.py
Normal file
1
tests/roots/test-ext-autodoc/circular_import/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from circular_import.c import SomeClass
|
1
tests/roots/test-ext-autodoc/circular_import/a.py
Normal file
1
tests/roots/test-ext-autodoc/circular_import/a.py
Normal file
@ -0,0 +1 @@
|
||||
X = 42
|
4
tests/roots/test-ext-autodoc/circular_import/b.py
Normal file
4
tests/roots/test-ext-autodoc/circular_import/b.py
Normal file
@ -0,0 +1,4 @@
|
||||
import typing
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from circular_import import SomeClass
|
6
tests/roots/test-ext-autodoc/circular_import/c.py
Normal file
6
tests/roots/test-ext-autodoc/circular_import/c.py
Normal file
@ -0,0 +1,6 @@
|
||||
import circular_import.a
|
||||
import circular_import.b
|
||||
|
||||
|
||||
class SomeClass:
|
||||
X = circular_import.a.X
|
@ -2024,6 +2024,19 @@ def test_autodoc_TYPE_CHECKING(app):
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_autodoc_TYPE_CHECKING_circular_import(app):
|
||||
options = {"members": None,
|
||||
"undoc-members": None}
|
||||
actual = do_autodoc(app, 'module', 'circular_import', options)
|
||||
assert list(actual) == [
|
||||
'',
|
||||
'.. py:module:: circular_import',
|
||||
'',
|
||||
]
|
||||
assert sys.modules["circular_import"].a is sys.modules["circular_import.a"]
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_singledispatch(app):
|
||||
options = {"members": None}
|
||||
|
Loading…
Reference in New Issue
Block a user