|
1 | 1 | #!/usr/bin/env python
|
2 |
| -import glob |
| 2 | +import asyncio |
3 | 3 | import os
|
| 4 | +from pathlib import Path |
4 | 5 | import shutil
|
5 | 6 | import subprocess
|
6 | 7 | import sys
|
|
20 | 21 | os.environ["PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION"] = "python"
|
21 | 22 |
|
22 | 23 |
|
23 |
| -def clear_directory(path: str): |
24 |
| - for file_or_directory in glob.glob(os.path.join(path, "*")): |
25 |
| - if os.path.isdir(file_or_directory): |
| 24 | +def clear_directory(dir_path: Path): |
| 25 | + for file_or_directory in dir_path.glob("*"): |
| 26 | + if file_or_directory.is_dir(): |
26 | 27 | shutil.rmtree(file_or_directory)
|
27 | 28 | else:
|
28 |
| - os.remove(file_or_directory) |
| 29 | + file_or_directory.unlink() |
29 | 30 |
|
30 | 31 |
|
31 |
| -def generate(whitelist: Set[str]): |
32 |
| - path_whitelist = {os.path.realpath(e) for e in whitelist if os.path.exists(e)} |
33 |
| - name_whitelist = {e for e in whitelist if not os.path.exists(e)} |
| 32 | +async def generate(whitelist: Set[str], verbose: bool): |
| 33 | + test_case_names = set(get_directories(inputs_path)) - {"__pycache__"} |
34 | 34 |
|
35 |
| - test_case_names = set(get_directories(inputs_path)) |
36 |
| - |
37 |
| - failed_test_cases = [] |
| 35 | + path_whitelist = set() |
| 36 | + name_whitelist = set() |
| 37 | + for item in whitelist: |
| 38 | + if item in test_case_names: |
| 39 | + name_whitelist.add(item) |
| 40 | + continue |
| 41 | + path_whitelist.add(item) |
38 | 42 |
|
| 43 | + generation_tasks = [] |
39 | 44 | for test_case_name in sorted(test_case_names):
|
40 |
| - test_case_input_path = os.path.realpath( |
41 |
| - os.path.join(inputs_path, test_case_name) |
42 |
| - ) |
43 |
| - |
| 45 | + test_case_input_path = inputs_path.joinpath(test_case_name).resolve() |
44 | 46 | if (
|
45 | 47 | whitelist
|
46 |
| - and test_case_input_path not in path_whitelist |
| 48 | + and str(test_case_input_path) not in path_whitelist |
47 | 49 | and test_case_name not in name_whitelist
|
48 | 50 | ):
|
49 | 51 | continue
|
| 52 | + generation_tasks.append( |
| 53 | + generate_test_case_output(test_case_input_path, test_case_name, verbose) |
| 54 | + ) |
50 | 55 |
|
51 |
| - print(f"Generating output for {test_case_name}") |
52 |
| - try: |
53 |
| - generate_test_case_output(test_case_name, test_case_input_path) |
54 |
| - except subprocess.CalledProcessError as e: |
55 |
| - failed_test_cases.append(test_case_name) |
56 |
| - |
57 |
| - if failed_test_cases: |
58 |
| - sys.stderr.write("\nFailed to generate the following test cases:\n") |
59 |
| - for failed_test_case in failed_test_cases: |
60 |
| - sys.stderr.write(f"- {failed_test_case}\n") |
| 56 | + # Wait for all subprocs and match any failures to names to report |
| 57 | + for test_case_name, result in zip( |
| 58 | + sorted(test_case_names), await asyncio.gather(*generation_tasks) |
| 59 | + ): |
| 60 | + if result != 0: |
| 61 | + sys.stderr.write(f"\nFailed to generate test case: {test_case_name}\n") |
61 | 62 |
|
62 | 63 |
|
63 |
| -def generate_test_case_output(test_case_name, test_case_input_path=None): |
64 |
| - if not test_case_input_path: |
65 |
| - test_case_input_path = os.path.realpath( |
66 |
| - os.path.join(inputs_path, test_case_name) |
67 |
| - ) |
| 64 | +async def generate_test_case_output( |
| 65 | + test_case_input_path: Path, test_case_name: str, verbose: bool |
| 66 | +) -> int: |
| 67 | + """ |
| 68 | + Returns the max of the subprocess return values |
| 69 | + """ |
68 | 70 |
|
69 |
| - test_case_output_path_reference = os.path.join( |
70 |
| - output_path_reference, test_case_name |
71 |
| - ) |
72 |
| - test_case_output_path_betterproto = os.path.join( |
73 |
| - output_path_betterproto, test_case_name |
74 |
| - ) |
| 71 | + test_case_output_path_reference = output_path_reference.joinpath(test_case_name) |
| 72 | + test_case_output_path_betterproto = output_path_betterproto.joinpath(test_case_name) |
75 | 73 |
|
| 74 | + print(f"Generating output for {test_case_name!r}") |
76 | 75 | os.makedirs(test_case_output_path_reference, exist_ok=True)
|
77 | 76 | os.makedirs(test_case_output_path_betterproto, exist_ok=True)
|
78 | 77 |
|
79 | 78 | clear_directory(test_case_output_path_reference)
|
80 | 79 | clear_directory(test_case_output_path_betterproto)
|
81 | 80 |
|
82 |
| - protoc_reference(test_case_input_path, test_case_output_path_reference) |
83 |
| - protoc_plugin(test_case_input_path, test_case_output_path_betterproto) |
| 81 | + subproc_out = None if verbose else open(os.devnull, "w") |
| 82 | + return_values = await asyncio.gather( |
| 83 | + ( |
| 84 | + await protoc_reference( |
| 85 | + test_case_input_path, test_case_output_path_reference, out=subproc_out, |
| 86 | + ) |
| 87 | + ).wait(), |
| 88 | + ( |
| 89 | + await protoc_plugin( |
| 90 | + test_case_input_path, |
| 91 | + test_case_output_path_betterproto, |
| 92 | + out=subproc_out, |
| 93 | + ) |
| 94 | + ).wait(), |
| 95 | + ) |
| 96 | + return max(return_values) |
84 | 97 |
|
85 | 98 |
|
86 | 99 | HELP = "\n".join(
|
87 |
| - [ |
88 |
| - "Usage: python generate.py", |
89 |
| - " python generate.py [DIRECTORIES or NAMES]", |
| 100 | + ( |
| 101 | + "Usage: python generate.py [-h] [-v] [DIRECTORIES or NAMES]", |
90 | 102 | "Generate python classes for standard tests.",
|
91 | 103 | "",
|
92 | 104 | "DIRECTORIES One or more relative or absolute directories of test-cases to generate classes for.",
|
93 | 105 | " python generate.py inputs/bool inputs/double inputs/enum",
|
94 | 106 | "",
|
95 | 107 | "NAMES One or more test-case names to generate classes for.",
|
96 | 108 | " python generate.py bool double enums",
|
97 |
| - ] |
| 109 | + ) |
98 | 110 | )
|
99 | 111 |
|
100 | 112 |
|
101 | 113 | def main():
|
102 | 114 | if set(sys.argv).intersection({"-h", "--help"}):
|
103 | 115 | print(HELP)
|
104 | 116 | return
|
105 |
| - whitelist = set(sys.argv[1:]) |
106 |
| - |
107 |
| - generate(whitelist) |
| 117 | + if sys.argv[1:2] == ["-v"]: |
| 118 | + verbose = True |
| 119 | + whitelist = set(sys.argv[2:]) |
| 120 | + else: |
| 121 | + verbose = False |
| 122 | + whitelist = set(sys.argv[1:]) |
| 123 | + asyncio.get_event_loop().run_until_complete(generate(whitelist, verbose)) |
108 | 124 |
|
109 | 125 |
|
110 | 126 | if __name__ == "__main__":
|
|
0 commit comments