Skip to content

Commit

Permalink
Merge branch 'master' into pa-search-index-reproducible
Browse files Browse the repository at this point in the history
# Conflicts:
#	CHANGES
  • Loading branch information
AA-Turner committed Sep 14, 2023
2 parents 6412bd5 + 024347c commit 3ea99a8
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 35 deletions.
17 changes: 16 additions & 1 deletion CHANGES
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Release 7.2.6 (in development)
Release 7.3.0 (in development)
==============================

Dependencies
Expand All @@ -18,6 +18,21 @@ Bugs fixed

* #11622: Fix ordering inside searchindex.js not being deterministic.

Testing
-------

Release 7.2.6 (released Sep 13, 2023)
=====================================

Bugs fixed
----------

* #11679: Add the :envvar:`!SPHINX_AUTODOC_RELOAD_MODULES` environment variable,
which if set reloads modules when using autodoc with ``TYPE_CHECKING = True``.
Patch by Matt Wozniski and Adam Turner.
* #11679: Use :py:func:`importlib.reload` to reload modules in autodoc.
Patch by Matt Wozniski and Adam Turner.

Release 7.2.5 (released Aug 30, 2023)
=====================================

Expand Down
2 changes: 2 additions & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import sphinx

os.environ['SPHINX_AUTODOC_RELOAD_MODULES'] = '1'

extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo',
'sphinx.ext.autosummary', 'sphinx.ext.extlinks',
'sphinx.ext.intersphinx',
Expand Down
6 changes: 3 additions & 3 deletions sphinx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
warnings.filterwarnings('ignore', 'The frontend.Option class .*',
DeprecationWarning, module='docutils.frontend')

__version__ = '7.2.5'
__version__ = '7.3.0'
__display_version__ = __version__ # used for command line version

#: Version info for better programmatic use.
Expand All @@ -30,11 +30,11 @@
#:
#: .. versionadded:: 1.2
#: Before version 1.2, check the string ``sphinx.__version__``.
version_info = (7, 2, 5, 'final', 0)
version_info = (7, 3, 0, 'beta', 0)

package_dir = path.abspath(path.dirname(__file__))

_in_development = False
_in_development = True
if _in_development:
# Only import subprocess if needed
import subprocess
Expand Down
28 changes: 17 additions & 11 deletions sphinx/cmd/make_mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ def __init__(self, srcdir: str, builddir: str, opts: Sequence[str]) -> None:
self.srcdir = srcdir
self.builddir = builddir
self.opts = [*opts]
self.makecmd = os.environ.get('MAKE', 'make') # refer $MAKE to determine make command

def builddir_join(self, *comps: str) -> str:
return path.join(self.builddir, *comps)
Expand Down Expand Up @@ -105,10 +104,11 @@ def build_latexpdf(self) -> int:
if self.run_generic_build('latex') > 0:
return 1

if sys.platform == 'win32':
makecmd = os.environ.get('MAKE', 'make.bat')
else:
makecmd = self.makecmd
# Use $MAKE to determine the make command
make_fallback = 'make.bat' if sys.platform == 'win32' else 'make'
makecmd = os.environ.get('MAKE', make_fallback)
if not makecmd.lower().startswith('make'):
raise RuntimeError('Invalid $MAKE command: %r' % makecmd)
try:
with chdir(self.builddir_join('latex')):
return subprocess.call([makecmd, 'all-pdf'])
Expand All @@ -120,10 +120,11 @@ def build_latexpdfja(self) -> int:
if self.run_generic_build('latex') > 0:
return 1

if sys.platform == 'win32':
makecmd = os.environ.get('MAKE', 'make.bat')
else:
makecmd = self.makecmd
# Use $MAKE to determine the make command
make_fallback = 'make.bat' if sys.platform == 'win32' else 'make'
makecmd = os.environ.get('MAKE', make_fallback)
if not makecmd.lower().startswith('make'):
raise RuntimeError('Invalid $MAKE command: %r' % makecmd)
try:
with chdir(self.builddir_join('latex')):
return subprocess.call([makecmd, 'all-pdf'])
Expand All @@ -134,11 +135,16 @@ def build_latexpdfja(self) -> int:
def build_info(self) -> int:
if self.run_generic_build('texinfo') > 0:
return 1

# Use $MAKE to determine the make command
makecmd = os.environ.get('MAKE', 'make')
if not makecmd.lower().startswith('make'):
raise RuntimeError('Invalid $MAKE command: %r' % makecmd)
try:
with chdir(self.builddir_join('texinfo')):
return subprocess.call([self.makecmd, 'info'])
return subprocess.call([makecmd, 'info'])
except OSError:
print('Error: Failed to run: %s' % self.makecmd)
print('Error: Failed to run: %s' % makecmd)
return 1

def build_gettext(self) -> int:
Expand Down
48 changes: 31 additions & 17 deletions sphinx/ext/autodoc/importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

from __future__ import annotations

import contextlib
import importlib
import os
import sys
import traceback
import typing
Expand All @@ -21,6 +23,8 @@
)

if TYPE_CHECKING:
from types import ModuleType

from sphinx.ext.autodoc import ObjectMember

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -69,6 +73,19 @@ def import_module(modname: str, warningiserror: bool = False) -> Any:
raise ImportError(exc, traceback.format_exc()) from exc


def _reload_module(module: ModuleType, warningiserror: bool = False) -> Any:
"""
Call importlib.reload(module), convert exceptions to ImportError
"""
try:
with logging.skip_warningiserror(not warningiserror):
return importlib.reload(module)
except BaseException as exc:
# Importing modules may cause any side effects, including
# SystemExit, so we need to catch all errors.
raise ImportError(exc, traceback.format_exc()) from exc


def import_object(modname: str, objpath: list[str], objtype: str = '',
attrgetter: Callable[[Any, str], Any] = safe_getattr,
warningiserror: bool = False) -> Any:
Expand All @@ -83,23 +100,20 @@ 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`` 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:
# ensure ``typing.TYPE_CHECKING == False``
typing.TYPE_CHECKING = False
original_module_names = frozenset(sys.modules)
module = import_module(modname, warningiserror=warningiserror)
if os.environ.get('SPHINX_AUTODOC_RELOAD_MODULES'):
new_modules = [m for m in sys.modules if m not in original_module_names]
# Try reloading modules with ``typing.TYPE_CHECKING == True``.
try:
typing.TYPE_CHECKING = True
# Ignore failures; we've already successfully loaded these modules
with contextlib.suppress(ImportError, KeyError):
for m in new_modules:
_reload_module(sys.modules[m])
finally:
typing.TYPE_CHECKING = False
module = sys.modules[modname]
logger.debug('[autodoc] import %s => %r', modname, module)
except ImportError as exc:
logger.debug('[autodoc] import %s => failed', modname)
Expand Down
3 changes: 3 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
from pathlib import Path

import docutils
Expand All @@ -24,6 +25,8 @@ def _init_console(locale_dir=sphinx.locale._LOCALE_DIR, catalog='sphinx'):
# Exclude 'roots' dirs for pytest test collector
collect_ignore = ['roots']

os.environ['SPHINX_AUTODOC_RELOAD_MODULES'] = '1'


@pytest.fixture(scope='session')
def rootdir():
Expand Down
5 changes: 2 additions & 3 deletions tests/test_ext_autodoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2103,9 +2103,8 @@ def test_singledispatchmethod_automethod(app):
]


@pytest.mark.skipif(sys.version_info[:2] >= (3, 11),
reason=('cython does not support python-3.11 yet. '
'see https://github.com/cython/cython/issues/4365'))
@pytest.mark.skipif(sys.version_info[:2] >= (3, 13),
reason='Cython does not support Python 3.13 yet.')
@pytest.mark.skipif(pyximport is None, reason='cython is not installed')
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_cython(app):
Expand Down

0 comments on commit 3ea99a8

Please sign in to comment.