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