2
2
3
3
from __future__ import annotations
4
4
5
+ import contextlib
5
6
import importlib
7
+ import os
6
8
import sys
7
9
import traceback
8
10
import typing
21
23
)
22
24
23
25
if TYPE_CHECKING :
26
+ from types import ModuleType
27
+
24
28
from sphinx .ext .autodoc import ObjectMember
25
29
26
30
logger = logging .getLogger (__name__ )
@@ -69,6 +73,19 @@ def import_module(modname: str, warningiserror: bool = False) -> Any:
69
73
raise ImportError (exc , traceback .format_exc ()) from exc
70
74
71
75
76
+ def _reload_module (module : ModuleType , warningiserror : bool = False ) -> Any :
77
+ """
78
+ Call importlib.reload(module), convert exceptions to ImportError
79
+ """
80
+ try :
81
+ with logging .skip_warningiserror (not warningiserror ):
82
+ return importlib .reload (module )
83
+ except BaseException as exc :
84
+ # Importing modules may cause any side effects, including
85
+ # SystemExit, so we need to catch all errors.
86
+ raise ImportError (exc , traceback .format_exc ()) from exc
87
+
88
+
72
89
def import_object (modname : str , objpath : list [str ], objtype : str = '' ,
73
90
attrgetter : Callable [[Any , str ], Any ] = safe_getattr ,
74
91
warningiserror : bool = False ) -> Any :
@@ -83,23 +100,20 @@ def import_object(modname: str, objpath: list[str], objtype: str = '',
83
100
objpath = list (objpath )
84
101
while module is None :
85
102
try :
86
- orig_modules = frozenset (sys .modules )
87
- try :
88
- # try importing with ``typing.TYPE_CHECKING == True``
89
- typing .TYPE_CHECKING = True
90
- module = import_module (modname , warningiserror = warningiserror )
91
- except ImportError :
92
- # if that fails (e.g. circular import), retry with
93
- # ``typing.TYPE_CHECKING == False`` after reverting
94
- # changes made to ``sys.modules`` by the failed try
95
- for m in [m for m in sys .modules if m not in orig_modules ]:
96
- sys .modules .pop (m )
97
-
98
- typing .TYPE_CHECKING = False
99
- module = import_module (modname , warningiserror = warningiserror )
100
- finally :
101
- # ensure ``typing.TYPE_CHECKING == False``
102
- typing .TYPE_CHECKING = False
103
+ original_module_names = frozenset (sys .modules )
104
+ module = import_module (modname , warningiserror = warningiserror )
105
+ if os .environ .get ('SPHINX_AUTODOC_RELOAD_MODULES' ):
106
+ new_modules = [m for m in sys .modules if m not in original_module_names ]
107
+ # Try reloading modules with ``typing.TYPE_CHECKING == True``.
108
+ try :
109
+ typing .TYPE_CHECKING = True
110
+ # Ignore failures; we've already successfully loaded these modules
111
+ with contextlib .suppress (ImportError , KeyError ):
112
+ for m in new_modules :
113
+ _reload_module (sys .modules [m ])
114
+ finally :
115
+ typing .TYPE_CHECKING = False
116
+ module = sys .modules [modname ]
103
117
logger .debug ('[autodoc] import %s => %r' , modname , module )
104
118
except ImportError as exc :
105
119
logger .debug ('[autodoc] import %s => failed' , modname )
0 commit comments