cpython/Tools/build/generate_stdlib_module_names.py
Victor Stinner 0faa0ba240
gh-92584: Remove the distutils package (#99061)
Remove the distutils package. It was deprecated in Python 3.10 by PEP
632 "Deprecate distutils module". For projects still using distutils
and cannot be updated to something else, the setuptools project can
be installed: it still provides distutils.

* Remove Lib/distutils/ directory
* Remove test_distutils
* Remove references to distutils
* Skip test_check_c_globals and test_peg_generator since they use
  distutils
2022-11-03 19:27:27 +01:00

138 lines
3.6 KiB
Python

# This script lists the names of standard library modules
# to update Python/stdlib_mod_names.h
import _imp
import os.path
import re
import subprocess
import sys
import sysconfig
from check_extension_modules import ModuleChecker
SCRIPT_NAME = 'Tools/build/generate_stdlib_module_names.py'
SRC_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
STDLIB_PATH = os.path.join(SRC_DIR, 'Lib')
IGNORE = {
'__init__',
'__pycache__',
'site-packages',
# Test modules and packages
'__hello__',
'__phello__',
'__hello_alias__',
'__phello_alias__',
'__hello_only__',
'_ctypes_test',
'_testbuffer',
'_testcapi',
'_testconsole',
'_testimportmultiple',
'_testinternalcapi',
'_testmultiphase',
'_xxsubinterpreters',
'_xxtestfuzz',
'idlelib.idle_test',
'test',
'xxlimited',
'xxlimited_35',
'xxsubtype',
}
# Pure Python modules (Lib/*.py)
def list_python_modules(names):
for filename in os.listdir(STDLIB_PATH):
if not filename.endswith(".py"):
continue
name = filename.removesuffix(".py")
names.add(name)
# Packages in Lib/
def list_packages(names):
for name in os.listdir(STDLIB_PATH):
if name in IGNORE:
continue
package_path = os.path.join(STDLIB_PATH, name)
if not os.path.isdir(package_path):
continue
if any(package_file.endswith(".py")
for package_file in os.listdir(package_path)):
names.add(name)
# Built-in and extension modules built by Modules/Setup*
# includes Windows and macOS extensions.
def list_modules_setup_extensions(names):
checker = ModuleChecker()
names.update(checker.list_module_names(all=True))
# List frozen modules of the PyImport_FrozenModules list (Python/frozen.c).
# Use the "./Programs/_testembed list_frozen" command.
def list_frozen(names):
submodules = set()
for name in _imp._frozen_module_names():
# To skip __hello__, __hello_alias__ and etc.
if name.startswith('__'):
continue
if '.' in name:
submodules.add(name)
else:
names.add(name)
# Make sure all frozen submodules have a known parent.
for name in list(submodules):
if name.partition('.')[0] in names:
submodules.remove(name)
if submodules:
raise Exception(f'unexpected frozen submodules: {sorted(submodules)}')
def list_modules():
names = set(sys.builtin_module_names)
list_modules_setup_extensions(names)
list_packages(names)
list_python_modules(names)
list_frozen(names)
# Remove ignored packages and modules
for name in list(names):
package_name = name.split('.')[0]
# package_name can be equal to name
if package_name in IGNORE:
names.discard(name)
for name in names:
if "." in name:
raise Exception("sub-modules must not be listed")
return names
def write_modules(fp, names):
print(f"// Auto-generated by {SCRIPT_NAME}.",
file=fp)
print("// List used to create sys.stdlib_module_names.", file=fp)
print(file=fp)
print("static const char* _Py_stdlib_module_names[] = {", file=fp)
for name in sorted(names):
print(f'"{name}",', file=fp)
print("};", file=fp)
def main():
if not sysconfig.is_python_build():
print(f"ERROR: {sys.executable} is not a Python build",
file=sys.stderr)
sys.exit(1)
fp = sys.stdout
names = list_modules()
write_modules(fp, names)
if __name__ == "__main__":
main()