| #!/usr/bin/env python |
| |
| import contextlib |
| import glob |
| import io |
| import os |
| import pathlib |
| import re |
| |
| import libcxx.test.header_information |
| |
| |
| def find_script(file): |
| """Finds the script used to generate a file inside the file itself. The script is delimited by |
| BEGIN-SCRIPT and END-SCRIPT markers. |
| """ |
| with open(file, "r") as f: |
| content = f.read() |
| |
| match = re.search( |
| r"^BEGIN-SCRIPT$(.+)^END-SCRIPT$", content, flags=re.MULTILINE | re.DOTALL |
| ) |
| if not match: |
| raise RuntimeError( |
| "Was unable to find a script delimited with BEGIN-SCRIPT/END-SCRIPT markers in {}".format( |
| test_file |
| ) |
| ) |
| return match.group(1) |
| |
| |
| def execute_script(script, variables): |
| """Executes the provided Mako template with the given variables available during the |
| evaluation of the script, and returns the result. |
| """ |
| code = compile(script, "fake-filename", "exec") |
| output = io.StringIO() |
| with contextlib.redirect_stdout(output): |
| exec(code, variables) |
| output = output.getvalue() |
| return output |
| |
| |
| def generate_new_file(file, new_content): |
| """Generates the new content of the file by inserting the new content in-between |
| two '// GENERATED-MARKER' markers located in the file. |
| """ |
| with open(file, "r") as f: |
| old_content = f.read() |
| |
| try: |
| before, begin_marker, _, end_marker, after = re.split( |
| r"(// GENERATED-MARKER\n)", old_content, flags=re.MULTILINE | re.DOTALL |
| ) |
| except ValueError: |
| raise RuntimeError( |
| "Failed to split {} based on markers, please make sure the file has exactly two '// GENERATED-MARKER' occurrences".format( |
| file |
| ) |
| ) |
| |
| return before + begin_marker + new_content + end_marker + after |
| |
| |
| def produce(test_file, variables): |
| script = find_script(test_file) |
| result = execute_script(script, variables) |
| new_content = generate_new_file(test_file, result) |
| with open(test_file, "w", newline="\n") as f: |
| f.write(new_content) |
| |
| |
| def main(): |
| monorepo_root = pathlib.Path( |
| os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) |
| ) |
| test = pathlib.Path(os.path.join(monorepo_root, "libcxx", "test")) |
| assert monorepo_root.exists() |
| |
| produce(test.joinpath("libcxx/transitive_includes.sh.cpp"), libcxx.test.header_information.variables) |
| |
| |
| if __name__ == "__main__": |
| main() |