(root)/
Python-3.12.0/
Tools/
build/
generate_stdlib_module_names.py
       1  # This script lists the names of standard library modules
       2  # to update Python/stdlib_module_names.h
       3  import _imp
       4  import os.path
       5  import re
       6  import subprocess
       7  import sys
       8  import sysconfig
       9  
      10  from check_extension_modules import ModuleChecker
      11  
      12  
      13  SCRIPT_NAME = 'Tools/build/generate_stdlib_module_names.py'
      14  
      15  SRC_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
      16  STDLIB_PATH = os.path.join(SRC_DIR, 'Lib')
      17  
      18  IGNORE = {
      19      '__init__',
      20      '__pycache__',
      21      'site-packages',
      22  
      23      # Test modules and packages
      24      '__hello__',
      25      '__phello__',
      26      '__hello_alias__',
      27      '__phello_alias__',
      28      '__hello_only__',
      29      '_ctypes_test',
      30      '_testbuffer',
      31      '_testcapi',
      32      '_testclinic',
      33      '_testconsole',
      34      '_testimportmultiple',
      35      '_testinternalcapi',
      36      '_testmultiphase',
      37      '_testsinglephase',
      38      '_xxsubinterpreters',
      39      '_xxinterpchannels',
      40      '_xxtestfuzz',
      41      'idlelib.idle_test',
      42      'test',
      43      'xxlimited',
      44      'xxlimited_35',
      45      'xxsubtype',
      46  }
      47  
      48  # Pure Python modules (Lib/*.py)
      49  def list_python_modules(names):
      50      for filename in os.listdir(STDLIB_PATH):
      51          if not filename.endswith(".py"):
      52              continue
      53          name = filename.removesuffix(".py")
      54          names.add(name)
      55  
      56  
      57  # Packages in Lib/
      58  def list_packages(names):
      59      for name in os.listdir(STDLIB_PATH):
      60          if name in IGNORE:
      61              continue
      62          package_path = os.path.join(STDLIB_PATH, name)
      63          if not os.path.isdir(package_path):
      64              continue
      65          if any(package_file.endswith(".py")
      66                 for package_file in os.listdir(package_path)):
      67              names.add(name)
      68  
      69  
      70  # Built-in and extension modules built by Modules/Setup*
      71  # includes Windows and macOS extensions.
      72  def list_modules_setup_extensions(names):
      73      checker = ModuleChecker()
      74      names.update(checker.list_module_names(all=True))
      75  
      76  
      77  # List frozen modules of the PyImport_FrozenModules list (Python/frozen.c).
      78  # Use the "./Programs/_testembed list_frozen" command.
      79  def list_frozen(names):
      80      submodules = set()
      81      for name in _imp._frozen_module_names():
      82          # To skip __hello__, __hello_alias__ and etc.
      83          if name.startswith('__'):
      84              continue
      85          if '.' in name:
      86              submodules.add(name)
      87          else:
      88              names.add(name)
      89      # Make sure all frozen submodules have a known parent.
      90      for name in list(submodules):
      91          if name.partition('.')[0] in names:
      92              submodules.remove(name)
      93      if submodules:
      94          raise Exception(f'unexpected frozen submodules: {sorted(submodules)}')
      95  
      96  
      97  def list_modules():
      98      names = set(sys.builtin_module_names)
      99      list_modules_setup_extensions(names)
     100      list_packages(names)
     101      list_python_modules(names)
     102      list_frozen(names)
     103  
     104      # Remove ignored packages and modules
     105      for name in list(names):
     106          package_name = name.split('.')[0]
     107          # package_name can be equal to name
     108          if package_name in IGNORE:
     109              names.discard(name)
     110  
     111      for name in names:
     112          if "." in name:
     113              raise Exception("sub-modules must not be listed")
     114  
     115      return names
     116  
     117  
     118  def write_modules(fp, names):
     119      print(f"// Auto-generated by {SCRIPT_NAME}.",
     120            file=fp)
     121      print("// List used to create sys.stdlib_module_names.", file=fp)
     122      print(file=fp)
     123      print("static const char* _Py_stdlib_module_names[] = {", file=fp)
     124      for name in sorted(names):
     125          print(f'"{name}",', file=fp)
     126      print("};", file=fp)
     127  
     128  
     129  def main():
     130      if not sysconfig.is_python_build():
     131          print(f"ERROR: {sys.executable} is not a Python build",
     132                file=sys.stderr)
     133          sys.exit(1)
     134  
     135      fp = sys.stdout
     136      names = list_modules()
     137      write_modules(fp, names)
     138  
     139  
     140  if __name__ == "__main__":
     141      main()