blob: 2214f59316f9e084b99cba7ae203a14722d15e63 [file] [log] [blame]
# SPDX-FileCopyrightText: 2020 The Magma Authors.
# SPDX-FileCopyrightText: 2022 Open Networking Foundation <support@opennetworking.org>
#
# SPDX-License-Identifier: BSD-3-Clause
import os
import shutil
import sys
from typing import Iterable, List
from grpc.tools import protoc
def find_all_proto_files_in_dir(input_dir: str) -> List[str]:
"""
Returns a list of filenames of .proto files in the given directory
Args:
input_dir: Directory to search in
Returns:
list(str): List of .proto filenames in the directory
"""
proto_files = []
for root, _, names in os.walk(input_dir):
for name in names:
full_filename = os.path.join(root, name)
extn = os.path.splitext(name)[1]
# Recurse into subdirectories
if os.path.isdir(full_filename):
proto_files += find_all_proto_files_in_dir(full_filename)
if os.path.isfile(full_filename) and extn == '.proto':
# TODO: find a better way to exclude the prometheus proto
if not full_filename.endswith('prometheus/metrics.proto'):
proto_files.append(full_filename)
return proto_files
def gen_bindings(
input_dir: str,
include_paths: Iterable[str],
proto_path: str,
output_dir: str,
) -> None:
"""
Generates python and Go bindings for all .proto files in input dir
@input_dir - input directory with .proto files to generate code for
@include_paths - a list of include paths to resolve relative imports in .protos
@output_dir - output directory to put generated code in
"""
protofiles = find_all_proto_files_in_dir(input_dir)
inouts = [
'-I' + proto_path,
'--python_out=' + output_dir,
'--grpc_python_out=' + output_dir,
]
# Only run mypy (dev dependency) when the protoc-consumed executable exists
if shutil.which('protoc-gen-mypy') is not None:
inouts.append('--mypy_out=' + output_dir)
protoc.main(
('',) +
tuple('-I' + path for path in include_paths) +
tuple(inouts) +
tuple(f for f in protofiles),
)
def main():
"""
Default main module. Generates .py code for all proto files
specified by the arguments
"""
if len(sys.argv) != 5:
print(
"Usage: ./gen_protos.py <dir containing .proto's> <include paths CSV> <proto_path for imports> <output dir>",
)
exit(1)
input_dir = sys.argv[1]
include_paths = sys.argv[2].split(',')
# The deprecated vagrant box image amarpad/magma_dev has grpc installed
# from source, with header files located at /usr/local/include. In the new
# box image amarpad/debian_jessie, grpc is installed from deb package, with
# headers located at /usr/include. Currently, only the magma_test vm uses
# amarpad/magma_dev.
#
# TODO: Migrate magma_test to amarpad/debian_jessie to to remove the
# '/usr/local/include'
include_paths.append('/usr/local/include')
proto_path = sys.argv[3]
output_dir = sys.argv[4]
gen_bindings(input_dir, include_paths, proto_path, output_dir)
if __name__ == "__main__":
main()