1import os.path 2 3from c_common.fsutil import expand_filenames, iter_files_by_suffix 4from . import REPO_ROOT, INCLUDE_DIRS, SOURCE_DIRS 5 6 7GLOBS = [ 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] 21LEVEL_GLOBS = { 22 'stable': 'Include/*.h', 23 'cpython': 'Include/cpython/*.h', 24 'internal': 'Include/internal/*.h', 25} 26 27 28def 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 39def 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 48def 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}') 72