From 12c08f35356664df600a827812fa8336ba77ebcc Mon Sep 17 00:00:00 2001 From: tan Date: Fri, 2 Apr 2021 12:47:31 +0530 Subject: [PATCH] code generation updates Julia protoc codegen looks for option `generic_services` to be turned on for at least one of `c++`, python or Java. I think that is unnecessary, but until it is updated, added a check here to check and warn. Also added instructions to readme. Package names with `.` are not handled well, needs some updates at protobuf code generation end. Have made the necessary changes needed here for now. And added instructions in readme to change package name to one without `.` before code generation. --- README.md | 10 ++++++++++ src/generate.jl | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ad11b32..5319665 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,16 @@ gRPC services are declared in `.proto` files. Use `gRPCClient.generate` to gener gRPC code generation uses `protoc` and the `ProtoBuf.jl` package. To be able to generate gRPC client code, `ProtoBuf` package must be installed along with `gRPCClient`. +The `protoc` file must have service generation turned on for at least one of C++, python or Java, e.g. one of: + +``` +option cc_generic_services = true; +option py_generic_services = true; +option java_generic_services = true; +``` + +The Julia code generated can be improper if the `package` name declared in the proto specification has `.`. Set a suitable `package` name without `.`. + ```julia julia> using Pkg diff --git a/src/generate.jl b/src/generate.jl index dd781af..5d16a37 100644 --- a/src/generate.jl +++ b/src/generate.jl @@ -1,5 +1,6 @@ const package_regex = r"package\s(\S*)[\s]*;.*" const service_regex = r"service\s(\S*)[\s]*{.*" +const services_option_regex = r"option\s[a-z]*_generic_services[\s]*=[\s]*true[\s]*;" function write_header(io, package, client_module_name) print(io, """module $(client_module_name) @@ -88,6 +89,19 @@ function write_service_method(io, package, service, method) """) end +function has_services_enabled(proto::String) + enabled = false + for line in readlines(proto) + line = strip(line) + regexmatches = match(services_option_regex, line) + if (regexmatches !== nothing) + enabled = true + break + end + end + enabled +end + function detect_services(proto::String) package = "" services = String[] @@ -110,6 +124,14 @@ function detect_services(proto::String) package, services end +function get_generated_method_table(s::String) + T = Main + for t in split(s, ".") + T = Base.eval(T, Symbol(t)) + end + T +end + """ generate(proto::String; outdir::String=pwd()) @@ -127,6 +149,11 @@ function generate(proto::String; outdir::String=pwd()) @info("Generating gRPC client", proto, outdir) + # ensure services are enabled in proto file + if !has_services_enabled(proto) + throw(ArgumentError("Service generation must be enabled in $proto, e.g. option py_generic_services = true;")) + end + # determine the package name and service name package, services = detect_services(proto) protodir = dirname(proto) @@ -141,19 +168,20 @@ function generate(proto::String; outdir::String=pwd()) end # include the generated code and detect service method names - generated_module = joinpath(outdir, "$(package).jl") - Main.eval(:(include($generated_module))) + generated_module = first(split(package, '.'; limit=2)) + generated_module_file = joinpath(outdir, string(generated_module, ".jl")) + Main.eval(:(include($generated_module_file))) # generate the gRPC client code - client_module_name = string(titlecase(package), "Clients") + client_module_name = string(titlecase(package; strict=false), "Clients") open(joinpath(outdir, "$(client_module_name).jl"), "w") do grpcservice write_header(grpcservice, package, client_module_name) for service in services - methods = Base.eval(Base.eval(Main, Symbol(package)), Symbol(string("_", service, "_methods"))) + methods = get_generated_method_table(string(package, "._", service, "_methods")) write_service(grpcservice, package, service, methods) end write_trailer(grpcservice, client_module_name) end @info("Generated", outdir) -end \ No newline at end of file +end