|
11 | 11 | import keyword |
12 | 12 | import tokenize |
13 | 13 | import io |
| 14 | +import importlib.util |
14 | 15 | import _colorize |
15 | 16 |
|
16 | 17 | from contextlib import suppress |
@@ -1128,6 +1129,10 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None, |
1128 | 1129 | self._str += (". Site initialization is disabled, did you forget to " |
1129 | 1130 | + "add the site-packages directory to sys.path " |
1130 | 1131 | + "or to enable your virtual environment?") |
| 1132 | + else: |
| 1133 | + suggestion = _compute_suggestion_error(exc_value, exc_traceback, module_name) |
| 1134 | + if suggestion: |
| 1135 | + self._str += f". Did you mean: '{suggestion}'?" |
1131 | 1136 | elif exc_type and issubclass(exc_type, AttributeError) and \ |
1132 | 1137 | getattr(exc_value, "name", None) is not None: |
1133 | 1138 | wrong_name = getattr(exc_value, "name", None) |
@@ -1717,6 +1722,18 @@ def _compute_suggestion_error(exc_value, tb, wrong_name): |
1717 | 1722 | d = [x for x in d if x[:1] != '_'] |
1718 | 1723 | except Exception: |
1719 | 1724 | return None |
| 1725 | + elif isinstance(exc_value, ModuleNotFoundError): |
| 1726 | + try: |
| 1727 | + if parent_name := wrong_name.rpartition('.')[0]: |
| 1728 | + parent = importlib.util.find_spec(parent_name) |
| 1729 | + else: |
| 1730 | + parent = None |
| 1731 | + d = [] |
| 1732 | + for finder in sys.meta_path: |
| 1733 | + if discover := getattr(finder, 'discover', None): |
| 1734 | + d += [spec.name for spec in discover(parent)] |
| 1735 | + except Exception: |
| 1736 | + return None |
1720 | 1737 | elif isinstance(exc_value, ImportError): |
1721 | 1738 | try: |
1722 | 1739 | mod = __import__(exc_value.name) |
|
0 commit comments