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