GH-134872: add ModuleNotFoundError suggestions (#142512)

* gh-134872: Add traceback suggestions for ModuleNotFoundError

Signed-off-by: Filipe Laíns <lains@riseup.net>

* Add news

Signed-off-by: Filipe Laíns <lains@riseup.net>

---------

Signed-off-by: Filipe Laíns <lains@riseup.net>
This commit is contained in:
Filipe Laíns 2026-02-19 16:10:58 +00:00 committed by GitHub
parent 157f271de3
commit f282f7aed9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 18 additions and 0 deletions

View file

@ -11,6 +11,7 @@
import keyword
import tokenize
import io
import importlib.util
import _colorize
from contextlib import suppress
@ -1128,6 +1129,10 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None,
self._str += (". Site initialization is disabled, did you forget to "
+ "add the site-packages directory to sys.path "
+ "or to enable your virtual environment?")
else:
suggestion = _compute_suggestion_error(exc_value, exc_traceback, module_name)
if suggestion:
self._str += f". Did you mean: '{suggestion}'?"
elif exc_type and issubclass(exc_type, AttributeError) and \
getattr(exc_value, "name", None) is not None:
wrong_name = getattr(exc_value, "name", None)
@ -1717,6 +1722,18 @@ def _compute_suggestion_error(exc_value, tb, wrong_name):
d = [x for x in d if x[:1] != '_']
except Exception:
return None
elif isinstance(exc_value, ModuleNotFoundError):
try:
if parent_name := wrong_name.rpartition('.')[0]:
parent = importlib.util.find_spec(parent_name)
else:
parent = None
d = []
for finder in sys.meta_path:
if discover := getattr(finder, 'discover', None):
d += [spec.name for spec in discover(parent)]
except Exception:
return None
elif isinstance(exc_value, ImportError):
try:
mod = __import__(exc_value.name)

View file

@ -0,0 +1 @@
Add valid import name suggestions on :exc:`ModuleNotFoundError`.