(root)/
Python-3.12.0/
Tools/
c-analyzer/
cpython/
_files.py
       1  import os.path
       2  
       3  from c_common.fsutil import expand_filenames, iter_files_by_suffix
       4  from . import REPO_ROOT, INCLUDE_DIRS, SOURCE_DIRS
       5  
       6  
       7  GLOBS = [
       8      'Include/*.h',
       9      # Technically, this is covered by "Include/*.h":
      10      #'Include/cpython/*.h',
      11      'Include/internal/*.h',
      12      'Modules/**/*.h',
      13      'Modules/**/*.c',
      14      'Objects/**/*.h',
      15      'Objects/**/*.c',
      16      'Parser/**/*.h',
      17      'Parser/**/*.c',
      18      'Python/**/*.h',
      19      'Python/**/*.c',
      20  ]
      21  LEVEL_GLOBS = {
      22      'stable': 'Include/*.h',
      23      'cpython': 'Include/cpython/*.h',
      24      'internal': 'Include/internal/*.h',
      25  }
      26  
      27  
      28  def resolve_filename(filename):
      29      orig = filename
      30      filename = os.path.normcase(os.path.normpath(filename))
      31      if os.path.isabs(filename):
      32          if os.path.relpath(filename, REPO_ROOT).startswith('.'):
      33              raise Exception(f'{orig!r} is outside the repo ({REPO_ROOT})')
      34          return filename
      35      else:
      36          return os.path.join(REPO_ROOT, filename)
      37  
      38  
      39  def iter_filenames(*, search=False):
      40      if search:
      41          yield from iter_files_by_suffix(INCLUDE_DIRS, ('.h',))
      42          yield from iter_files_by_suffix(SOURCE_DIRS, ('.c',))
      43      else:
      44          globs = (os.path.join(REPO_ROOT, file) for file in GLOBS)
      45          yield from expand_filenames(globs)
      46  
      47  
      48  def iter_header_files(filenames=None, *, levels=None):
      49      if not filenames:
      50          if levels:
      51              levels = set(levels)
      52              if 'private' in levels:
      53                  levels.add('stable')
      54                  levels.add('cpython')
      55              for level, glob in LEVEL_GLOBS.items():
      56                  if level in levels:
      57                      yield from expand_filenames([glob])
      58          else:
      59              yield from iter_files_by_suffix(INCLUDE_DIRS, ('.h',))
      60          return
      61  
      62      for filename in filenames:
      63          orig = filename
      64          filename = resolve_filename(filename)
      65          if filename.endswith(os.path.sep):
      66              yield from iter_files_by_suffix(INCLUDE_DIRS, ('.h',))
      67          elif filename.endswith('.h'):
      68              yield filename
      69          else:
      70              # XXX Log it and continue instead?
      71              raise ValueError(f'expected .h file, got {orig!r}')