From 843ff15650a0a4d5881280a13090b94fdfbb01eb Mon Sep 17 00:00:00 2001 From: "Philipp A." Date: Thu, 20 Nov 2025 12:30:29 +0100 Subject: [PATCH 1/4] fix: use exception group --- sphinx/ext/autosummary/__init__.py | 20 +++++++------------- sphinx/ext/autosummary/generate.py | 2 +- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index dedc203d919..4e23131e091 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -275,7 +275,7 @@ def import_by_name( return import_ivar_by_name(name, prefixes) except ImportError as exc2: if exc2.__cause__: - errors: list[BaseException] = [*exc.exceptions, exc2.__cause__] + errors: list[Exception] = [*exc.exceptions, exc2.__cause__] else: errors = [*exc.exceptions, exc2] @@ -609,19 +609,12 @@ def limited_join( # -- Importing items ----------------------------------------------------------- - -class ImportExceptionGroup(Exception): +class ImportExceptionGroup(ExceptionGroup): """Exceptions raised during importing the target objects. - It contains an error messages and a list of exceptions as its arguments. + It contains an error message and a list of exceptions as its arguments. """ - def __init__( - self, message: str | None, exceptions: Sequence[BaseException] - ) -> None: - super().__init__(message) - self.exceptions = list(exceptions) - def get_import_prefixes_from_env(env: BuildEnvironment) -> list[str | None]: """Obtain current Python import prefixes (for `import_by_name`) @@ -681,15 +674,16 @@ def import_by_name( tried.append(prefixed_name) errors.append(exc) - exceptions: list[BaseException] = functools.reduce( + exceptions: list[Exception] = functools.reduce( operator.iadd, (e.exceptions for e in errors), [] ) - raise ImportExceptionGroup('no module named %s' % ' or '.join(tried), exceptions) + msg = f'could not import {" or ".join(tried)}' + raise ImportExceptionGroup(msg, exceptions) def _import_by_name(name: str, grouped_exception: bool = True) -> tuple[Any, Any, str]: """Import a Python object given its full name.""" - errors: list[BaseException] = [] + errors: list[Exception] = [] try: name_parts = name.split('.') diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index 1e8055bf73e..bf43f17c09a 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -670,7 +670,7 @@ def generate_autosummary_docs( qualname = name.replace(modname + '.', '') except ImportError as exc2: if exc2.__cause__: - exceptions: list[BaseException] = [*exc.exceptions, exc2.__cause__] + exceptions: list[Exception] = [*exc.exceptions, exc2.__cause__] else: exceptions = [*exc.exceptions, exc2] From b7d52aa74a4fbff5ffbb331a7d6a885b25d3f1ed Mon Sep 17 00:00:00 2001 From: "Philipp A." Date: Fri, 21 Nov 2025 11:11:23 +0100 Subject: [PATCH 2/4] Use BaseExceptionGroup --- sphinx/ext/autosummary/__init__.py | 8 ++++---- sphinx/ext/autosummary/generate.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 4e23131e091..69b0297906b 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -275,7 +275,7 @@ def import_by_name( return import_ivar_by_name(name, prefixes) except ImportError as exc2: if exc2.__cause__: - errors: list[Exception] = [*exc.exceptions, exc2.__cause__] + errors: list[BaseException] = [*exc.exceptions, exc2.__cause__] else: errors = [*exc.exceptions, exc2] @@ -609,7 +609,7 @@ def limited_join( # -- Importing items ----------------------------------------------------------- -class ImportExceptionGroup(ExceptionGroup): +class ImportExceptionGroup(BaseExceptionGroup): """Exceptions raised during importing the target objects. It contains an error message and a list of exceptions as its arguments. @@ -674,7 +674,7 @@ def import_by_name( tried.append(prefixed_name) errors.append(exc) - exceptions: list[Exception] = functools.reduce( + exceptions: list[BaseException] = functools.reduce( operator.iadd, (e.exceptions for e in errors), [] ) msg = f'could not import {" or ".join(tried)}' @@ -683,7 +683,7 @@ def import_by_name( def _import_by_name(name: str, grouped_exception: bool = True) -> tuple[Any, Any, str]: """Import a Python object given its full name.""" - errors: list[Exception] = [] + errors: list[BaseException] = [] try: name_parts = name.split('.') diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index bf43f17c09a..1e8055bf73e 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -670,7 +670,7 @@ def generate_autosummary_docs( qualname = name.replace(modname + '.', '') except ImportError as exc2: if exc2.__cause__: - exceptions: list[Exception] = [*exc.exceptions, exc2.__cause__] + exceptions: list[BaseException] = [*exc.exceptions, exc2.__cause__] else: exceptions = [*exc.exceptions, exc2] From 718a49712ef60ce276b14531ea3a7522817ebe5e Mon Sep 17 00:00:00 2001 From: "Philipp A." Date: Fri, 21 Nov 2025 11:14:59 +0100 Subject: [PATCH 3/4] relnote --- CHANGES.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index cd36d83957b..97d222527b7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -68,6 +68,8 @@ Features added Patch by Jean-François B. * #13508: Initial support for :pep:`695` type aliases. Patch by Martin Matouš, Jeremy Maitin-Shepard, and Adam Turner. +* #14075: autosummary: Provide more context in import exception stack traces. + Patch by Philipp A. Bugs fixed ---------- From cdae172a43dabae2ec59f4d17bf983df9bb5284e Mon Sep 17 00:00:00 2001 From: "Philipp A." Date: Fri, 21 Nov 2025 11:17:59 +0100 Subject: [PATCH 4/4] fmt --- sphinx/ext/autosummary/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 69b0297906b..d4b822d46ff 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -609,6 +609,7 @@ def limited_join( # -- Importing items ----------------------------------------------------------- + class ImportExceptionGroup(BaseExceptionGroup): """Exceptions raised during importing the target objects.