blob: 2214f59316f9e084b99cba7ae203a14722d15e63 [file] [log] [blame]
Wei-Yu Chenad55cb82022-02-15 20:07:01 +08001# SPDX-FileCopyrightText: 2020 The Magma Authors.
2# SPDX-FileCopyrightText: 2022 Open Networking Foundation <support@opennetworking.org>
3#
4# SPDX-License-Identifier: BSD-3-Clause
Wei-Yu Chen49950b92021-11-08 19:19:18 +08005
Wei-Yu Chen49950b92021-11-08 19:19:18 +08006import os
7import shutil
8import sys
9from typing import Iterable, List
10
11from grpc.tools import protoc
12
13
14def find_all_proto_files_in_dir(input_dir: str) -> List[str]:
15 """
16 Returns a list of filenames of .proto files in the given directory
17
18 Args:
19 input_dir: Directory to search in
20
21 Returns:
22 list(str): List of .proto filenames in the directory
23 """
24 proto_files = []
25 for root, _, names in os.walk(input_dir):
26 for name in names:
27 full_filename = os.path.join(root, name)
28 extn = os.path.splitext(name)[1]
29
30 # Recurse into subdirectories
31 if os.path.isdir(full_filename):
32 proto_files += find_all_proto_files_in_dir(full_filename)
33 if os.path.isfile(full_filename) and extn == '.proto':
34 # TODO: find a better way to exclude the prometheus proto
35 if not full_filename.endswith('prometheus/metrics.proto'):
36 proto_files.append(full_filename)
37 return proto_files
38
39
40def gen_bindings(
41 input_dir: str,
42 include_paths: Iterable[str],
43 proto_path: str,
44 output_dir: str,
45) -> None:
46 """
47 Generates python and Go bindings for all .proto files in input dir
48 @input_dir - input directory with .proto files to generate code for
49 @include_paths - a list of include paths to resolve relative imports in .protos
50 @output_dir - output directory to put generated code in
51 """
52 protofiles = find_all_proto_files_in_dir(input_dir)
53
54 inouts = [
55 '-I' + proto_path,
56 '--python_out=' + output_dir,
57 '--grpc_python_out=' + output_dir,
58 ]
59 # Only run mypy (dev dependency) when the protoc-consumed executable exists
60 if shutil.which('protoc-gen-mypy') is not None:
61 inouts.append('--mypy_out=' + output_dir)
62
63 protoc.main(
64 ('',) +
65 tuple('-I' + path for path in include_paths) +
66 tuple(inouts) +
67 tuple(f for f in protofiles),
68 )
69
70
71def main():
72 """
73 Default main module. Generates .py code for all proto files
74 specified by the arguments
75 """
76 if len(sys.argv) != 5:
77 print(
78 "Usage: ./gen_protos.py <dir containing .proto's> <include paths CSV> <proto_path for imports> <output dir>",
79 )
80 exit(1)
81 input_dir = sys.argv[1]
82 include_paths = sys.argv[2].split(',')
83 # The deprecated vagrant box image amarpad/magma_dev has grpc installed
84 # from source, with header files located at /usr/local/include. In the new
85 # box image amarpad/debian_jessie, grpc is installed from deb package, with
86 # headers located at /usr/include. Currently, only the magma_test vm uses
87 # amarpad/magma_dev.
88 #
89 # TODO: Migrate magma_test to amarpad/debian_jessie to to remove the
90 # '/usr/local/include'
91 include_paths.append('/usr/local/include')
92 proto_path = sys.argv[3]
93 output_dir = sys.argv[4]
94 gen_bindings(input_dir, include_paths, proto_path, output_dir)
95
96
97if __name__ == "__main__":
98 main()
99