import pathlib
import os
import sys
import subprocess
import configparser
import dataclasses
from typing import List
CONFIG_PATH: pathlib.Path = pathlib.Path("./setup.cfg").absolute()
@dataclasses.dataclass
class Options:
proto_root_dir: pathlib.Path
go_module_root: pathlib.Path
def load_cfg() -> Options:
config = configparser.ConfigParser()
config.read(str(CONFIG_PATH))
options = Options(
proto_root_dir=pathlib.Path(config["proto"]["root_source_path"]),
go_module_root=pathlib.Path(config["proto"]["root_go_package"]),
)
return options
def main() -> None:
options = load_cfg()
generate_golang_source(options)
add_bson_tags()
def generate_golang_source(options: Options) -> None:
proto_files = find_proto_files(options)
run_protoc_command(proto_files, options)
def find_proto_files(options: Options) -> List[str]:
proto_file_list: List[str] = list()
for proto_path in options.proto_root_dir.rglob("./**/*.proto"):
if "google" in str(proto_path):
continue
path_str = str(proto_path)
path_str = path_str.replace(str(os.getcwd()), ".")
proto_file_list.append(path_str)
return proto_file_list
def run_protoc_command(proto_files: List[str], options: Options) -> None:
command = build_protoc_command(proto_files, options)
proc = subprocess.Popen(command)
_, _ = proc.communicate()
if proc.returncode != 0:
sys.exit(proc.returncode)
def build_protoc_command(protoc_files: List[str], options: Options) -> List[str]:
command = [
"protoc",
"--experimental_allow_proto3_optional",
"--go_out=plugins=grpc:.",
f"--go_opt=module={options.go_module_root}",
]
command.extend(protoc_files)
return command
def add_bson_tags() -> None:
directory = pathlib.Path(os.getcwd())
for source_code_file_path in directory.rglob("./**/*.pb.go"):
run_tag_command(source_code_file_path)
def build_tag_command(source_code_file_path: pathlib.Path) -> List[str]:
return [
"protoc-go-inject-tag",
f"-input={source_code_file_path}",
"-XXX_skip=bson",
]
def run_tag_command(source_code_path: pathlib.Path) -> None:
command = build_tag_command(source_code_path)
proc = subprocess.Popen(command)
_, _ = proc.communicate()
if proc.returncode != 0:
sys.exit(proc.returncode)
if __name__ == "__main__":
main()