1 /*
2 *
3 * Copyright 2015 gRPC authors.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 */
18
19 #include <map>
20 #include <sstream>
21
22 #include "flatbuffers/util.h"
23 #include "src/compiler/python_generator.h"
24
25 namespace grpc_python_generator {
26 namespace {
27
GenerateMethodType(const grpc_generator::Method * method)28 static grpc::string GenerateMethodType(const grpc_generator::Method *method) {
29
30 if (method->NoStreaming())
31 return "unary_unary";
32
33 if (method->ServerStreaming())
34 return "unary_stream";
35
36 if (method->ClientStreaming())
37 return "stream_unary";
38
39 return "stream_stream";
40 }
41
GenerateMethodInput(const grpc_generator::Method * method)42 grpc::string GenerateMethodInput(const grpc_generator::Method *method) {
43
44 if (method->NoStreaming() || method->ServerStreaming())
45 return "self, request, context";
46
47 return "self, request_iterator, context";
48 }
49
GenerateStub(const grpc_generator::Service * service,grpc_generator::Printer * printer,std::map<grpc::string,grpc::string> * dictonary)50 void GenerateStub(const grpc_generator::Service *service,
51 grpc_generator::Printer *printer,
52 std::map<grpc::string, grpc::string> *dictonary) {
53 auto vars = *dictonary;
54 printer->Print(vars, "class $ServiceName$Stub(object):\n");
55 printer->Indent();
56 printer->Print("\"\"\" Interface exported by the server. \"\"\"");
57 printer->Print("\n\n");
58 printer->Print("def __init__(self, channel):\n");
59 printer->Indent();
60 printer->Print("\"\"\" Constructor. \n\n");
61 printer->Print("Args: \n");
62 printer->Print("channel: A grpc.Channel. \n");
63 printer->Print("\"\"\"\n\n");
64
65 for (int j = 0; j < service->method_count(); j++) {
66 auto method = service->method(j);
67 vars["MethodName"] = method->name();
68 vars["MethodType"] = GenerateMethodType(&*method);
69 printer->Print(vars, "self.$MethodName$ = channel.$MethodType$(\n");
70 printer->Indent();
71 printer->Print(vars, "\"/$PATH$$ServiceName$/$MethodName$\"\n");
72 printer->Print(")\n");
73 printer->Outdent();
74 printer->Print("\n");
75 }
76 printer->Outdent();
77 printer->Outdent();
78 printer->Print("\n");
79 }
80
GenerateServicer(const grpc_generator::Service * service,grpc_generator::Printer * printer,std::map<grpc::string,grpc::string> * dictonary)81 void GenerateServicer(const grpc_generator::Service *service,
82 grpc_generator::Printer *printer,
83 std::map<grpc::string, grpc::string> *dictonary) {
84 auto vars = *dictonary;
85 printer->Print(vars, "class $ServiceName$Servicer(object):\n");
86 printer->Indent();
87 printer->Print("\"\"\" Interface exported by the server. \"\"\"");
88 printer->Print("\n\n");
89
90 for (int j = 0; j < service->method_count(); j++) {
91 auto method = service->method(j);
92 vars["MethodName"] = method->name();
93 vars["MethodInput"] = GenerateMethodInput(&*method);
94 printer->Print(vars, "def $MethodName$($MethodInput$):\n");
95 printer->Indent();
96 printer->Print("context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n");
97 printer->Print("context.set_details('Method not implemented!')\n");
98 printer->Print("raise NotImplementedError('Method not implemented!')\n");
99 printer->Outdent();
100 printer->Print("\n\n");
101 }
102 printer->Outdent();
103 printer->Print("\n");
104
105 }
106
GenerateRegister(const grpc_generator::Service * service,grpc_generator::Printer * printer,std::map<grpc::string,grpc::string> * dictonary)107 void GenerateRegister(const grpc_generator::Service *service,
108 grpc_generator::Printer *printer,
109 std::map<grpc::string, grpc::string> *dictonary) {
110 auto vars = *dictonary;
111 printer->Print(vars, "def add_$ServiceName$Servicer_to_server(servicer, server):\n");
112 printer->Indent();
113 printer->Print("rpc_method_handlers = {\n");
114 printer->Indent();
115 for (int j = 0; j < service->method_count(); j++) {
116 auto method = service->method(j);
117 vars["MethodName"] = method->name();
118 vars["MethodType"] = GenerateMethodType(&*method);
119 printer->Print(vars, "'$MethodName$': grpc.$MethodType$_rpc_method_handler(\n");
120 printer->Indent();
121 printer->Print(vars, "servicer.$MethodName$\n");
122 printer->Outdent();
123 printer->Print("),\n");
124 }
125 printer->Outdent();
126 printer->Print("}\n");
127 printer->Print(vars, "generic_handler = grpc.method_handlers_generic_handler(\n");
128 printer->Indent();
129 printer->Print(vars, "'$PATH$$ServiceName$', rpc_method_handlers)\n");
130 printer->Outdent();
131 printer->Print("server.add_generic_rpc_handlers((generic_handler,))");
132 printer->Outdent();
133 printer->Print("\n");
134 }
135 } // namespace
136
Generate(grpc_generator::File * file,const grpc_generator::Service * service)137 grpc::string Generate(grpc_generator::File *file,
138 const grpc_generator::Service *service) {
139 grpc::string output;
140 std::map<grpc::string, grpc::string> vars;
141 vars["PATH"] = file->package();
142 if (!file->package().empty()) { vars["PATH"].append("."); }
143 vars["ServiceName"] = service->name();
144 auto printer = file->CreatePrinter(&output);
145 GenerateStub(service, &*printer, &vars);
146 GenerateServicer(service, &*printer, &vars);
147 GenerateRegister(service, &*printer, &vars);
148 return output;
149 }
150
151 } // namespace grpc_python_generator
152