#include <map>
#include <sstream>
#include "flatbuffers/util.h"
#include "src/compiler/python_generator.h"
namespace grpc_python_generator {
namespace {
static grpc::string GenerateMethodType(const grpc_generator::Method *method) {
if (method->NoStreaming())
return "unary_unary";
if (method->ServerStreaming())
return "unary_stream";
if (method->ClientStreaming())
return "stream_unary";
return "stream_stream";
}
grpc::string GenerateMethodInput(const grpc_generator::Method *method) {
if (method->NoStreaming() || method->ServerStreaming())
return "self, request, context";
return "self, request_iterator, context";
}
void GenerateStub(const grpc_generator::Service *service,
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> *dictonary) {
auto vars = *dictonary;
printer->Print(vars, "class $ServiceName$Stub(object):\n");
printer->Indent();
printer->Print("\"\"\" Interface exported by the server. \"\"\"");
printer->Print("\n\n");
printer->Print("def __init__(self, channel):\n");
printer->Indent();
printer->Print("\"\"\" Constructor. \n\n");
printer->Print("Args: \n");
printer->Print("channel: A grpc.Channel. \n");
printer->Print("\"\"\"\n\n");
for (int j = 0; j < service->method_count(); j++) {
auto method = service->method(j);
vars["MethodName"] = method->name();
vars["MethodType"] = GenerateMethodType(&*method);
printer->Print(vars, "self.$MethodName$ = channel.$MethodType$(\n");
printer->Indent();
printer->Print(vars, "\"/$PATH$$ServiceName$/$MethodName$\"\n");
printer->Print(")\n");
printer->Outdent();
printer->Print("\n");
}
printer->Outdent();
printer->Outdent();
printer->Print("\n");
}
void GenerateServicer(const grpc_generator::Service *service,
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> *dictonary) {
auto vars = *dictonary;
printer->Print(vars, "class $ServiceName$Servicer(object):\n");
printer->Indent();
printer->Print("\"\"\" Interface exported by the server. \"\"\"");
printer->Print("\n\n");
for (int j = 0; j < service->method_count(); j++) {
auto method = service->method(j);
vars["MethodName"] = method->name();
vars["MethodInput"] = GenerateMethodInput(&*method);
printer->Print(vars, "def $MethodName$($MethodInput$):\n");
printer->Indent();
printer->Print("context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n");
printer->Print("context.set_details('Method not implemented!')\n");
printer->Print("raise NotImplementedError('Method not implemented!')\n");
printer->Outdent();
printer->Print("\n\n");
}
printer->Outdent();
printer->Print("\n");
}
void GenerateRegister(const grpc_generator::Service *service,
grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> *dictonary) {
auto vars = *dictonary;
printer->Print(vars, "def add_$ServiceName$Servicer_to_server(servicer, server):\n");
printer->Indent();
printer->Print("rpc_method_handlers = {\n");
printer->Indent();
for (int j = 0; j < service->method_count(); j++) {
auto method = service->method(j);
vars["MethodName"] = method->name();
vars["MethodType"] = GenerateMethodType(&*method);
printer->Print(vars, "'$MethodName$': grpc.$MethodType$_rpc_method_handler(\n");
printer->Indent();
printer->Print(vars, "servicer.$MethodName$\n");
printer->Outdent();
printer->Print("),\n");
}
printer->Outdent();
printer->Print("}\n");
printer->Print(vars, "generic_handler = grpc.method_handlers_generic_handler(\n");
printer->Indent();
printer->Print(vars, "'$PATH$$ServiceName$', rpc_method_handlers)\n");
printer->Outdent();
printer->Print("server.add_generic_rpc_handlers((generic_handler,))");
printer->Outdent();
printer->Print("\n");
}
}
grpc::string Generate(grpc_generator::File *file,
const grpc_generator::Service *service) {
grpc::string output;
std::map<grpc::string, grpc::string> vars;
vars["PATH"] = file->package();
if (!file->package().empty()) { vars["PATH"].append("."); }
vars["ServiceName"] = service->name();
auto printer = file->CreatePrinter(&output);
GenerateStub(service, &*printer, &vars);
GenerateServicer(service, &*printer, &vars);
GenerateRegister(service, &*printer, &vars);
return output;
}
}