Skip to content

Commit 7f10e66

Browse files
Rework
1 parent 6b2d934 commit 7f10e66

File tree

3 files changed

+56
-14
lines changed

3 files changed

+56
-14
lines changed

Lib/traceback.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414

1515
from contextlib import suppress
1616

17+
try:
18+
from _stdlib_modules_info import MISSING_STDLIB_MODULE_MESSAGES
19+
except ImportError:
20+
MISSING_STDLIB_MODULE_MESSAGES = None
21+
1722
__all__ = ['extract_stack', 'extract_tb', 'format_exception',
1823
'format_exception_only', 'format_list', 'format_stack',
1924
'format_tb', 'print_exc', 'format_exc', 'print_exception',
@@ -1110,11 +1115,14 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None,
11101115
elif exc_type and issubclass(exc_type, ModuleNotFoundError):
11111116
module_name = getattr(exc_value, "name", None)
11121117
if module_name in sys.stdlib_module_names:
1113-
message = _missing_stdlib_module.get(
1114-
module_name,
1115-
f"Standard library module '{module_name}' was not found"
1116-
)
1117-
self._str = message
1118+
if MISSING_STDLIB_MODULE_MESSAGES is not None:
1119+
message = MISSING_STDLIB_MODULE_MESSAGES.get(
1120+
module_name,
1121+
f"Standard library module '{module_name}' was not found"
1122+
)
1123+
self._str = message
1124+
else:
1125+
self._str = f"Standard library module '{module_name}' was not found"
11181126
elif sys.flags.no_site:
11191127
self._str += (". Site initialization is disabled, did you forget to "
11201128
+ "add the site-packages directory to sys.path "
@@ -1798,12 +1806,3 @@ def _levenshtein_distance(a, b, max_cost):
17981806
# Everything in this row is too big, so bail early.
17991807
return max_cost + 1
18001808
return result
1801-
1802-
_windows_only_modules = ["winreg", "msvcrt", "winsound", "nt", "_winapi", "_msi"]
1803-
1804-
_missing_stdlib_module = {
1805-
name: f"Windows-only standard library module '{name}' not found"
1806-
for name in _windows_only_modules
1807-
} | {
1808-
# Distributors can patch this dictionary to provide installation suggestions.
1809-
}

Makefile.pre.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,6 +1601,7 @@ sharedmods: $(SHAREDMODS) pybuilddir.txt
16011601
# dependency on BUILDPYTHON ensures that the target is run last
16021602
.PHONY: checksharedmods
16031603
checksharedmods: sharedmods $(PYTHON_FOR_BUILD_DEPS) $(BUILDPYTHON)
1604+
@$(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/Tools/build/check_extension_modules.py --generate-stdlib-info
16041605
@$(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/Tools/build/check_extension_modules.py
16051606

16061607
.PHONY: rundsymutil
@@ -2815,6 +2816,7 @@ libinstall: all $(srcdir)/Modules/xxmodule.c
28152816
$(INSTALL_DATA) `cat pybuilddir.txt`/_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH).py $(DESTDIR)$(LIBDEST); \
28162817
$(INSTALL_DATA) `cat pybuilddir.txt`/_sysconfig_vars_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH).json $(DESTDIR)$(LIBDEST); \
28172818
$(INSTALL_DATA) `cat pybuilddir.txt`/build-details.json $(DESTDIR)$(LIBDEST); \
2819+
$(INSTALL_DATA) `cat pybuilddir.txt`/_stdlib_modules_info.py $(DESTDIR)$(LIBDEST); \
28182820
$(INSTALL_DATA) $(srcdir)/LICENSE $(DESTDIR)$(LIBDEST)/LICENSE.txt
28192821
@ # If app store compliance has been configured, apply the patch to the
28202822
@ # installed library code. The patch has been previously validated against

Tools/build/check_extension_modules.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@
116116
help="Print a list of module names to stdout and exit",
117117
)
118118

119+
parser.add_argument(
120+
"--generate-stdlib-info",
121+
action="store_true",
122+
help="Generate file with stdlib module info",
123+
)
124+
119125

120126
@enum.unique
121127
class ModuleState(enum.Enum):
@@ -281,6 +287,38 @@ def list_module_names(self, *, all: bool = False) -> set[str]:
281287
names.update(WINDOWS_MODULES)
282288
return names
283289

290+
def generate_stdlib_info(self) -> None:
291+
292+
disabled_modules = {modinfo.name for modinfo in self.modules
293+
if modinfo.state in (ModuleState.DISABLED, ModuleState.DISABLED_SETUP)}
294+
missing_modules = {modinfo.name for modinfo in self.modules
295+
if modinfo.state == ModuleState.MISSING}
296+
na_modules = {modinfo.name for modinfo in self.modules
297+
if modinfo.state == ModuleState.NA}
298+
299+
content = f'''\
300+
# Standard library information used by the traceback module for more informative
301+
# ModuleNotFound error messages.
302+
303+
DISABLED_MODULES = {sorted(disabled_modules)!r}
304+
MISSING_MODULES = {sorted(missing_modules)!r}
305+
NOT_AVAILABLE_MODULES = {sorted(na_modules)!r}
306+
WINDOWS_ONLY_MODULES = {sorted(WINDOWS_MODULES)!r}
307+
308+
MISSING_STDLIB_MODULE_MESSAGES = {{
309+
**{{name: f"Windows-only standard library module '{{name}}' was not found"
310+
for name in WINDOWS_ONLY_MODULES}},
311+
**{{name: f"Standard library module disabled during build '{{name}}' was not found"
312+
for name in DISABLED_MODULES}},
313+
**{{name: f"Unsupported platform for standard library module '{{name}}'"
314+
for name in NOT_AVAILABLE_MODULES}},
315+
}}
316+
'''
317+
318+
output_path = self.builddir / "_stdlib_modules_info.py"
319+
with open(output_path, "w", encoding="utf-8") as f:
320+
f.write(content)
321+
284322
def get_builddir(self) -> pathlib.Path:
285323
try:
286324
with open(self.pybuilddir_txt, encoding="utf-8") as f:
@@ -499,6 +537,9 @@ def main() -> None:
499537
names = checker.list_module_names(all=True)
500538
for name in sorted(names):
501539
print(name)
540+
elif args.generate_stdlib_info:
541+
checker.check()
542+
checker.generate_stdlib_info()
502543
else:
503544
checker.check()
504545
checker.summary(verbose=args.verbose)

0 commit comments

Comments
 (0)