mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	 d45cc80452
			
		
	
	
		d45cc80452
		
			
		
	
	
	
	
		
			
			This makes it more clear that a given test is definitely testing against a single-phase init (legacy) extension module. The new module is a companion to _testmultiphase. https://github.com/python/cpython/issues/98627
		
			
				
	
	
		
			139 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			139 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',
 | |
|     '_testsinglephase',
 | |
|     '_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()
 |