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}')