File
Blob: src/workerd/server/tests/python/vendor_pkg_tests/generate_modules.py
| 1 | # This script reads the list of files from a zip file and outputs a list of Cap'n Proto module |
| 2 | # definitions to be used in a .wd-test for Python tests. |
| 3 | import argparse |
| 4 | from pathlib import Path |
| 5 | |
| 6 | |
| 7 | class MyArgumentParser(argparse.ArgumentParser): |
| 8 | def convert_arg_line_to_args(self, arg_line): |
| 9 | return arg_line.split() |
| 10 | |
| 11 | |
| 12 | def get_parser(): |
| 13 | parser = MyArgumentParser( |
| 14 | description="Generate Cap'n Proto module definitions for Python tests", |
| 15 | fromfile_prefix_chars="@", |
| 16 | ) |
| 17 | parser.add_argument( |
| 18 | "--level", |
| 19 | type=int, |
| 20 | default=1, |
| 21 | help="Directory level for relative path calculation (default: 1)", |
| 22 | ) |
| 23 | parser.add_argument( |
| 24 | "--template", |
| 25 | type=str, |
| 26 | help="Template file", |
| 27 | ) |
| 28 | parser.add_argument( |
| 29 | "--out", |
| 30 | type=str, |
| 31 | help="Output file", |
| 32 | ) |
| 33 | parser.add_argument( |
| 34 | "file_paths", |
| 35 | nargs="*", |
| 36 | help="List of file paths or @response_file containing space-separated paths", |
| 37 | ) |
| 38 | return parser |
| 39 | |
| 40 | |
| 41 | def make_module_list(file_paths, level=1): |
| 42 | modules = [] |
| 43 | for f_path in file_paths: |
| 44 | if Path(f_path).is_dir(): |
| 45 | continue |
| 46 | # The path from bazel is relative to the exec root, e.g.: |
| 47 | # external/fastapi_src/fastapi/__init__.py |
| 48 | # We need to strip the prefix to get the module path. |
| 49 | # |
| 50 | # On Windows, we replace windows-style path separators with standard posix path separators. |
| 51 | components = Path(f_path).parts |
| 52 | # without `external/` prefix |
| 53 | parents = 6 + level |
| 54 | embed_path = ("../" * parents) + str(Path(*components[1:])).replace( |
| 55 | "\\", "\\\\" |
| 56 | ) |
| 57 | # without `external/fastapi_src/` prefix |
| 58 | module_path = str(Path("python_modules", *components[2:])).replace("\\", "/") |
| 59 | |
| 60 | # Format as a Cap'n Proto module definition. |
| 61 | if f_path.endswith(".py"): |
| 62 | modules.append( |
| 63 | f'(name = "{module_path}", pythonModule = embed "{embed_path}")' |
| 64 | ) |
| 65 | else: |
| 66 | modules.append(f'(name = "{module_path}", data = embed "{embed_path}")') |
| 67 | return ",\n".join(modules) + ",\n" |
| 68 | |
| 69 | |
| 70 | def write_output(modules, template_path, outfile): |
| 71 | template = Path(template_path).read_text() |
| 72 | result = template.replace("%PYTHON_VENDORED_MODULES%", modules) |
| 73 | Path(outfile).write_text(result) |
| 74 | |
| 75 | |
| 76 | def main(): |
| 77 | parser = get_parser() |
| 78 | args = parser.parse_args() |
| 79 | level = args.level |
| 80 | file_paths = args.file_paths |
| 81 | outfile = args.out |
| 82 | template = args.template |
| 83 | modules = make_module_list(file_paths, level) |
| 84 | write_output(modules, template, outfile) |
| 85 | |
| 86 | |
| 87 | if __name__ == "__main__": |
| 88 | main() |