summaryrefslogtreecommitdiffstats
path: root/Tools/c-analyzer/cpython/_files.py
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/c-analyzer/cpython/_files.py')
-rw-r--r--Tools/c-analyzer/cpython/_files.py69
1 files changed, 69 insertions, 0 deletions
diff --git a/Tools/c-analyzer/cpython/_files.py b/Tools/c-analyzer/cpython/_files.py
new file mode 100644
index 0000000..3e39788
--- /dev/null
+++ b/Tools/c-analyzer/cpython/_files.py
@@ -0,0 +1,69 @@
+import os.path
+
+from c_common.fsutil import expand_filenames, iter_files_by_suffix
+from . import REPO_ROOT, INCLUDE_DIRS, SOURCE_DIRS
+
+
+GLOBS = [
+ 'Include/*.h',
+ 'Include/internal/*.h',
+ 'Modules/**/*.h',
+ 'Modules/**/*.c',
+ 'Objects/**/*.h',
+ 'Objects/**/*.c',
+ 'Python/**/*.h',
+ 'Parser/**/*.c',
+ 'Python/**/*.h',
+ 'Parser/**/*.c',
+]
+LEVEL_GLOBS = {
+ 'stable': 'Include/*.h',
+ 'cpython': 'Include/cpython/*.h',
+ 'internal': 'Include/internal/*.h',
+}
+
+
+def resolve_filename(filename):
+ orig = filename
+ filename = os.path.normcase(os.path.normpath(filename))
+ if os.path.isabs(filename):
+ if os.path.relpath(filename, REPO_ROOT).startswith('.'):
+ raise Exception(f'{orig!r} is outside the repo ({REPO_ROOT})')
+ return filename
+ else:
+ return os.path.join(REPO_ROOT, filename)
+
+
+def iter_filenames(*, search=False):
+ if search:
+ yield from iter_files_by_suffix(INCLUDE_DIRS, ('.h',))
+ yield from iter_files_by_suffix(SOURCE_DIRS, ('.c',))
+ else:
+ globs = (os.path.join(REPO_ROOT, file) for file in GLOBS)
+ yield from expand_filenames(globs)
+
+
+def iter_header_files(filenames=None, *, levels=None):
+ if not filenames:
+ if levels:
+ levels = set(levels)
+ if 'private' in levels:
+ levels.add('stable')
+ levels.add('cpython')
+ for level, glob in LEVEL_GLOBS.items():
+ if level in levels:
+ yield from expand_filenames([glob])
+ else:
+ yield from iter_files_by_suffix(INCLUDE_DIRS, ('.h',))
+ return
+
+ for filename in filenames:
+ orig = filename
+ filename = resolve_filename(filename)
+ if filename.endswith(os.path.sep):
+ yield from iter_files_by_suffix(INCLUDE_DIRS, ('.h',))
+ elif filename.endswith('.h'):
+ yield filename
+ else:
+ # XXX Log it and continue instead?
+ raise ValueError(f'expected .h file, got {orig!r}')