xref: /aosp_15_r20/external/grpc-grpc/src/compiler/python_generator.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1*cc02d7e2SAndroid Build Coastguard Worker /*
2*cc02d7e2SAndroid Build Coastguard Worker  *
3*cc02d7e2SAndroid Build Coastguard Worker  * Copyright 2015 gRPC authors.
4*cc02d7e2SAndroid Build Coastguard Worker  *
5*cc02d7e2SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
6*cc02d7e2SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
7*cc02d7e2SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
8*cc02d7e2SAndroid Build Coastguard Worker  *
9*cc02d7e2SAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
10*cc02d7e2SAndroid Build Coastguard Worker  *
11*cc02d7e2SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
12*cc02d7e2SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
13*cc02d7e2SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*cc02d7e2SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
15*cc02d7e2SAndroid Build Coastguard Worker  * limitations under the License.
16*cc02d7e2SAndroid Build Coastguard Worker  *
17*cc02d7e2SAndroid Build Coastguard Worker  */
18*cc02d7e2SAndroid Build Coastguard Worker 
19*cc02d7e2SAndroid Build Coastguard Worker #include "src/compiler/python_generator.h"
20*cc02d7e2SAndroid Build Coastguard Worker 
21*cc02d7e2SAndroid Build Coastguard Worker #include <algorithm>
22*cc02d7e2SAndroid Build Coastguard Worker #include <cassert>
23*cc02d7e2SAndroid Build Coastguard Worker #include <cctype>
24*cc02d7e2SAndroid Build Coastguard Worker #include <cstring>
25*cc02d7e2SAndroid Build Coastguard Worker #include <fstream>
26*cc02d7e2SAndroid Build Coastguard Worker #include <iostream>
27*cc02d7e2SAndroid Build Coastguard Worker #include <map>
28*cc02d7e2SAndroid Build Coastguard Worker #include <memory>
29*cc02d7e2SAndroid Build Coastguard Worker #include <ostream>
30*cc02d7e2SAndroid Build Coastguard Worker #include <set>
31*cc02d7e2SAndroid Build Coastguard Worker #include <sstream>
32*cc02d7e2SAndroid Build Coastguard Worker #include <tuple>
33*cc02d7e2SAndroid Build Coastguard Worker #include <vector>
34*cc02d7e2SAndroid Build Coastguard Worker 
35*cc02d7e2SAndroid Build Coastguard Worker #include "src/compiler/config.h"
36*cc02d7e2SAndroid Build Coastguard Worker #include "src/compiler/generator_helpers.h"
37*cc02d7e2SAndroid Build Coastguard Worker #include "src/compiler/protobuf_plugin.h"
38*cc02d7e2SAndroid Build Coastguard Worker #include "src/compiler/python_generator_helpers.h"
39*cc02d7e2SAndroid Build Coastguard Worker #include "src/compiler/python_private_generator.h"
40*cc02d7e2SAndroid Build Coastguard Worker 
41*cc02d7e2SAndroid Build Coastguard Worker using grpc::protobuf::FileDescriptor;
42*cc02d7e2SAndroid Build Coastguard Worker using grpc::protobuf::compiler::GeneratorContext;
43*cc02d7e2SAndroid Build Coastguard Worker using grpc::protobuf::io::CodedOutputStream;
44*cc02d7e2SAndroid Build Coastguard Worker using grpc::protobuf::io::ZeroCopyOutputStream;
45*cc02d7e2SAndroid Build Coastguard Worker using std::make_pair;
46*cc02d7e2SAndroid Build Coastguard Worker using std::map;
47*cc02d7e2SAndroid Build Coastguard Worker using std::pair;
48*cc02d7e2SAndroid Build Coastguard Worker using std::replace;
49*cc02d7e2SAndroid Build Coastguard Worker using std::set;
50*cc02d7e2SAndroid Build Coastguard Worker using std::tuple;
51*cc02d7e2SAndroid Build Coastguard Worker using std::vector;
52*cc02d7e2SAndroid Build Coastguard Worker 
53*cc02d7e2SAndroid Build Coastguard Worker namespace grpc_python_generator {
54*cc02d7e2SAndroid Build Coastguard Worker 
55*cc02d7e2SAndroid Build Coastguard Worker std::string generator_file_name;
56*cc02d7e2SAndroid Build Coastguard Worker 
57*cc02d7e2SAndroid Build Coastguard Worker namespace {
58*cc02d7e2SAndroid Build Coastguard Worker 
59*cc02d7e2SAndroid Build Coastguard Worker typedef map<std::string, std::string> StringMap;
60*cc02d7e2SAndroid Build Coastguard Worker typedef vector<std::string> StringVector;
61*cc02d7e2SAndroid Build Coastguard Worker typedef tuple<std::string, std::string> StringPair;
62*cc02d7e2SAndroid Build Coastguard Worker typedef set<StringPair> StringPairSet;
63*cc02d7e2SAndroid Build Coastguard Worker 
64*cc02d7e2SAndroid Build Coastguard Worker // Provides RAII indentation handling. Use as:
65*cc02d7e2SAndroid Build Coastguard Worker // {
66*cc02d7e2SAndroid Build Coastguard Worker //   IndentScope raii_my_indent_var_name_here(my_py_printer);
67*cc02d7e2SAndroid Build Coastguard Worker //   // constructor indented my_py_printer
68*cc02d7e2SAndroid Build Coastguard Worker //   ...
69*cc02d7e2SAndroid Build Coastguard Worker //   // destructor called at end of scope, un-indenting my_py_printer
70*cc02d7e2SAndroid Build Coastguard Worker // }
71*cc02d7e2SAndroid Build Coastguard Worker class IndentScope {
72*cc02d7e2SAndroid Build Coastguard Worker  public:
IndentScope(grpc_generator::Printer * printer)73*cc02d7e2SAndroid Build Coastguard Worker   explicit IndentScope(grpc_generator::Printer* printer) : printer_(printer) {
74*cc02d7e2SAndroid Build Coastguard Worker     // NOTE(rbellevi): Two-space tabs are hard-coded in the protocol compiler.
75*cc02d7e2SAndroid Build Coastguard Worker     // Doubling our indents and outdents guarantees compliance with PEP8.
76*cc02d7e2SAndroid Build Coastguard Worker     printer_->Indent();
77*cc02d7e2SAndroid Build Coastguard Worker     printer_->Indent();
78*cc02d7e2SAndroid Build Coastguard Worker   }
79*cc02d7e2SAndroid Build Coastguard Worker 
~IndentScope()80*cc02d7e2SAndroid Build Coastguard Worker   ~IndentScope() {
81*cc02d7e2SAndroid Build Coastguard Worker     printer_->Outdent();
82*cc02d7e2SAndroid Build Coastguard Worker     printer_->Outdent();
83*cc02d7e2SAndroid Build Coastguard Worker   }
84*cc02d7e2SAndroid Build Coastguard Worker 
85*cc02d7e2SAndroid Build Coastguard Worker  private:
86*cc02d7e2SAndroid Build Coastguard Worker   grpc_generator::Printer* printer_;
87*cc02d7e2SAndroid Build Coastguard Worker };
88*cc02d7e2SAndroid Build Coastguard Worker 
PrivateGenerator(const GeneratorConfiguration & config,const grpc_generator::File * file)89*cc02d7e2SAndroid Build Coastguard Worker PrivateGenerator::PrivateGenerator(const GeneratorConfiguration& config,
90*cc02d7e2SAndroid Build Coastguard Worker                                    const grpc_generator::File* file)
91*cc02d7e2SAndroid Build Coastguard Worker     : config(config), file(file) {}
92*cc02d7e2SAndroid Build Coastguard Worker 
PrintAllComments(StringVector comments,grpc_generator::Printer * out)93*cc02d7e2SAndroid Build Coastguard Worker void PrivateGenerator::PrintAllComments(StringVector comments,
94*cc02d7e2SAndroid Build Coastguard Worker                                         grpc_generator::Printer* out) {
95*cc02d7e2SAndroid Build Coastguard Worker   if (comments.empty()) {
96*cc02d7e2SAndroid Build Coastguard Worker     // Python requires code structures like class and def to have
97*cc02d7e2SAndroid Build Coastguard Worker     // a body, even if it is just "pass" or a docstring.  We need
98*cc02d7e2SAndroid Build Coastguard Worker     // to ensure not to generate empty bodies. We could do something
99*cc02d7e2SAndroid Build Coastguard Worker     // smarter and more sophisticated, but at the moment, if there is
100*cc02d7e2SAndroid Build Coastguard Worker     // no docstring to print, we simply emit "pass" to ensure validity
101*cc02d7e2SAndroid Build Coastguard Worker     // of the generated code.
102*cc02d7e2SAndroid Build Coastguard Worker     out->Print(
103*cc02d7e2SAndroid Build Coastguard Worker         "\"\"\"Missing associated documentation comment in .proto "
104*cc02d7e2SAndroid Build Coastguard Worker         "file.\"\"\"\n");
105*cc02d7e2SAndroid Build Coastguard Worker     return;
106*cc02d7e2SAndroid Build Coastguard Worker   }
107*cc02d7e2SAndroid Build Coastguard Worker   out->Print("\"\"\"");
108*cc02d7e2SAndroid Build Coastguard Worker   for (StringVector::iterator it = comments.begin(); it != comments.end();
109*cc02d7e2SAndroid Build Coastguard Worker        ++it) {
110*cc02d7e2SAndroid Build Coastguard Worker     size_t start_pos = it->find_first_not_of(' ');
111*cc02d7e2SAndroid Build Coastguard Worker     if (start_pos != std::string::npos) {
112*cc02d7e2SAndroid Build Coastguard Worker       out->PrintRaw(it->c_str() + start_pos);
113*cc02d7e2SAndroid Build Coastguard Worker     }
114*cc02d7e2SAndroid Build Coastguard Worker     out->Print("\n");
115*cc02d7e2SAndroid Build Coastguard Worker   }
116*cc02d7e2SAndroid Build Coastguard Worker   out->Print("\"\"\"\n");
117*cc02d7e2SAndroid Build Coastguard Worker }
118*cc02d7e2SAndroid Build Coastguard Worker 
PrintBetaServicer(const grpc_generator::Service * service,grpc_generator::Printer * out)119*cc02d7e2SAndroid Build Coastguard Worker bool PrivateGenerator::PrintBetaServicer(const grpc_generator::Service* service,
120*cc02d7e2SAndroid Build Coastguard Worker                                          grpc_generator::Printer* out) {
121*cc02d7e2SAndroid Build Coastguard Worker   StringMap service_dict;
122*cc02d7e2SAndroid Build Coastguard Worker   service_dict["Service"] = service->name();
123*cc02d7e2SAndroid Build Coastguard Worker   out->Print("\n\n");
124*cc02d7e2SAndroid Build Coastguard Worker   out->Print(service_dict, "class Beta$Service$Servicer(object):\n");
125*cc02d7e2SAndroid Build Coastguard Worker   {
126*cc02d7e2SAndroid Build Coastguard Worker     IndentScope raii_class_indent(out);
127*cc02d7e2SAndroid Build Coastguard Worker     out->Print(
128*cc02d7e2SAndroid Build Coastguard Worker         "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
129*cc02d7e2SAndroid Build Coastguard Worker         "\nIt is recommended to use the GA API (classes and functions in this\n"
130*cc02d7e2SAndroid Build Coastguard Worker         "file not marked beta) for all further purposes. This class was "
131*cc02d7e2SAndroid Build Coastguard Worker         "generated\n"
132*cc02d7e2SAndroid Build Coastguard Worker         "only to ease transition from grpcio<0.15.0 to "
133*cc02d7e2SAndroid Build Coastguard Worker         "grpcio>=0.15.0.\"\"\"\n");
134*cc02d7e2SAndroid Build Coastguard Worker     StringVector service_comments = service->GetAllComments();
135*cc02d7e2SAndroid Build Coastguard Worker     PrintAllComments(service_comments, out);
136*cc02d7e2SAndroid Build Coastguard Worker     for (int i = 0; i < service->method_count(); ++i) {
137*cc02d7e2SAndroid Build Coastguard Worker       auto method = service->method(i);
138*cc02d7e2SAndroid Build Coastguard Worker       std::string arg_name =
139*cc02d7e2SAndroid Build Coastguard Worker           method->ClientStreaming() ? "request_iterator" : "request";
140*cc02d7e2SAndroid Build Coastguard Worker       StringMap method_dict;
141*cc02d7e2SAndroid Build Coastguard Worker       method_dict["Method"] = method->name();
142*cc02d7e2SAndroid Build Coastguard Worker       method_dict["ArgName"] = arg_name;
143*cc02d7e2SAndroid Build Coastguard Worker       out->Print(method_dict, "def $Method$(self, $ArgName$, context):\n");
144*cc02d7e2SAndroid Build Coastguard Worker       {
145*cc02d7e2SAndroid Build Coastguard Worker         IndentScope raii_method_indent(out);
146*cc02d7e2SAndroid Build Coastguard Worker         StringVector method_comments = method->GetAllComments();
147*cc02d7e2SAndroid Build Coastguard Worker         PrintAllComments(method_comments, out);
148*cc02d7e2SAndroid Build Coastguard Worker         out->Print("context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)\n");
149*cc02d7e2SAndroid Build Coastguard Worker       }
150*cc02d7e2SAndroid Build Coastguard Worker     }
151*cc02d7e2SAndroid Build Coastguard Worker   }
152*cc02d7e2SAndroid Build Coastguard Worker   return true;
153*cc02d7e2SAndroid Build Coastguard Worker }
154*cc02d7e2SAndroid Build Coastguard Worker 
PrintBetaStub(const grpc_generator::Service * service,grpc_generator::Printer * out)155*cc02d7e2SAndroid Build Coastguard Worker bool PrivateGenerator::PrintBetaStub(const grpc_generator::Service* service,
156*cc02d7e2SAndroid Build Coastguard Worker                                      grpc_generator::Printer* out) {
157*cc02d7e2SAndroid Build Coastguard Worker   StringMap service_dict;
158*cc02d7e2SAndroid Build Coastguard Worker   service_dict["Service"] = service->name();
159*cc02d7e2SAndroid Build Coastguard Worker   out->Print("\n\n");
160*cc02d7e2SAndroid Build Coastguard Worker   out->Print(service_dict, "class Beta$Service$Stub(object):\n");
161*cc02d7e2SAndroid Build Coastguard Worker   {
162*cc02d7e2SAndroid Build Coastguard Worker     IndentScope raii_class_indent(out);
163*cc02d7e2SAndroid Build Coastguard Worker     out->Print(
164*cc02d7e2SAndroid Build Coastguard Worker         "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
165*cc02d7e2SAndroid Build Coastguard Worker         "\nIt is recommended to use the GA API (classes and functions in this\n"
166*cc02d7e2SAndroid Build Coastguard Worker         "file not marked beta) for all further purposes. This class was "
167*cc02d7e2SAndroid Build Coastguard Worker         "generated\n"
168*cc02d7e2SAndroid Build Coastguard Worker         "only to ease transition from grpcio<0.15.0 to "
169*cc02d7e2SAndroid Build Coastguard Worker         "grpcio>=0.15.0.\"\"\"\n");
170*cc02d7e2SAndroid Build Coastguard Worker     StringVector service_comments = service->GetAllComments();
171*cc02d7e2SAndroid Build Coastguard Worker     PrintAllComments(service_comments, out);
172*cc02d7e2SAndroid Build Coastguard Worker     for (int i = 0; i < service->method_count(); ++i) {
173*cc02d7e2SAndroid Build Coastguard Worker       auto method = service->method(i);
174*cc02d7e2SAndroid Build Coastguard Worker       std::string arg_name =
175*cc02d7e2SAndroid Build Coastguard Worker           method->ClientStreaming() ? "request_iterator" : "request";
176*cc02d7e2SAndroid Build Coastguard Worker       StringMap method_dict;
177*cc02d7e2SAndroid Build Coastguard Worker       method_dict["Method"] = method->name();
178*cc02d7e2SAndroid Build Coastguard Worker       method_dict["ArgName"] = arg_name;
179*cc02d7e2SAndroid Build Coastguard Worker       out->Print(method_dict,
180*cc02d7e2SAndroid Build Coastguard Worker                  "def $Method$(self, $ArgName$, timeout, metadata=None, "
181*cc02d7e2SAndroid Build Coastguard Worker                  "with_call=False, protocol_options=None):\n");
182*cc02d7e2SAndroid Build Coastguard Worker       {
183*cc02d7e2SAndroid Build Coastguard Worker         IndentScope raii_method_indent(out);
184*cc02d7e2SAndroid Build Coastguard Worker         StringVector method_comments = method->GetAllComments();
185*cc02d7e2SAndroid Build Coastguard Worker         PrintAllComments(method_comments, out);
186*cc02d7e2SAndroid Build Coastguard Worker         out->Print("raise NotImplementedError()\n");
187*cc02d7e2SAndroid Build Coastguard Worker       }
188*cc02d7e2SAndroid Build Coastguard Worker       if (!method->ServerStreaming()) {
189*cc02d7e2SAndroid Build Coastguard Worker         out->Print(method_dict, "$Method$.future = None\n");
190*cc02d7e2SAndroid Build Coastguard Worker       }
191*cc02d7e2SAndroid Build Coastguard Worker     }
192*cc02d7e2SAndroid Build Coastguard Worker   }
193*cc02d7e2SAndroid Build Coastguard Worker   return true;
194*cc02d7e2SAndroid Build Coastguard Worker }
195*cc02d7e2SAndroid Build Coastguard Worker 
PrintBetaServerFactory(const std::string & package_qualified_service_name,const grpc_generator::Service * service,grpc_generator::Printer * out)196*cc02d7e2SAndroid Build Coastguard Worker bool PrivateGenerator::PrintBetaServerFactory(
197*cc02d7e2SAndroid Build Coastguard Worker     const std::string& package_qualified_service_name,
198*cc02d7e2SAndroid Build Coastguard Worker     const grpc_generator::Service* service, grpc_generator::Printer* out) {
199*cc02d7e2SAndroid Build Coastguard Worker   StringMap service_dict;
200*cc02d7e2SAndroid Build Coastguard Worker   service_dict["Service"] = service->name();
201*cc02d7e2SAndroid Build Coastguard Worker   out->Print("\n\n");
202*cc02d7e2SAndroid Build Coastguard Worker   out->Print(service_dict,
203*cc02d7e2SAndroid Build Coastguard Worker              "def beta_create_$Service$_server(servicer, pool=None, "
204*cc02d7e2SAndroid Build Coastguard Worker              "pool_size=None, default_timeout=None, maximum_timeout=None):\n");
205*cc02d7e2SAndroid Build Coastguard Worker   {
206*cc02d7e2SAndroid Build Coastguard Worker     IndentScope raii_create_server_indent(out);
207*cc02d7e2SAndroid Build Coastguard Worker     out->Print(
208*cc02d7e2SAndroid Build Coastguard Worker         "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
209*cc02d7e2SAndroid Build Coastguard Worker         "\nIt is recommended to use the GA API (classes and functions in this\n"
210*cc02d7e2SAndroid Build Coastguard Worker         "file not marked beta) for all further purposes. This function was\n"
211*cc02d7e2SAndroid Build Coastguard Worker         "generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"
212*cc02d7e2SAndroid Build Coastguard Worker         "\"\"\"\n");
213*cc02d7e2SAndroid Build Coastguard Worker     StringMap method_implementation_constructors;
214*cc02d7e2SAndroid Build Coastguard Worker     StringMap input_message_modules_and_classes;
215*cc02d7e2SAndroid Build Coastguard Worker     StringMap output_message_modules_and_classes;
216*cc02d7e2SAndroid Build Coastguard Worker     for (int i = 0; i < service->method_count(); ++i) {
217*cc02d7e2SAndroid Build Coastguard Worker       auto method = service->method(i);
218*cc02d7e2SAndroid Build Coastguard Worker       const std::string method_implementation_constructor =
219*cc02d7e2SAndroid Build Coastguard Worker           std::string(method->ClientStreaming() ? "stream_" : "unary_") +
220*cc02d7e2SAndroid Build Coastguard Worker           std::string(method->ServerStreaming() ? "stream_" : "unary_") +
221*cc02d7e2SAndroid Build Coastguard Worker           "inline";
222*cc02d7e2SAndroid Build Coastguard Worker       std::string input_message_module_and_class;
223*cc02d7e2SAndroid Build Coastguard Worker       if (!method->get_module_and_message_path_input(
224*cc02d7e2SAndroid Build Coastguard Worker               &input_message_module_and_class, generator_file_name,
225*cc02d7e2SAndroid Build Coastguard Worker               generate_in_pb2_grpc, config.import_prefix,
226*cc02d7e2SAndroid Build Coastguard Worker               config.prefixes_to_filter)) {
227*cc02d7e2SAndroid Build Coastguard Worker         return false;
228*cc02d7e2SAndroid Build Coastguard Worker       }
229*cc02d7e2SAndroid Build Coastguard Worker       std::string output_message_module_and_class;
230*cc02d7e2SAndroid Build Coastguard Worker       if (!method->get_module_and_message_path_output(
231*cc02d7e2SAndroid Build Coastguard Worker               &output_message_module_and_class, generator_file_name,
232*cc02d7e2SAndroid Build Coastguard Worker               generate_in_pb2_grpc, config.import_prefix,
233*cc02d7e2SAndroid Build Coastguard Worker               config.prefixes_to_filter)) {
234*cc02d7e2SAndroid Build Coastguard Worker         return false;
235*cc02d7e2SAndroid Build Coastguard Worker       }
236*cc02d7e2SAndroid Build Coastguard Worker       method_implementation_constructors.insert(
237*cc02d7e2SAndroid Build Coastguard Worker           make_pair(method->name(), method_implementation_constructor));
238*cc02d7e2SAndroid Build Coastguard Worker       input_message_modules_and_classes.insert(
239*cc02d7e2SAndroid Build Coastguard Worker           make_pair(method->name(), input_message_module_and_class));
240*cc02d7e2SAndroid Build Coastguard Worker       output_message_modules_and_classes.insert(
241*cc02d7e2SAndroid Build Coastguard Worker           make_pair(method->name(), output_message_module_and_class));
242*cc02d7e2SAndroid Build Coastguard Worker     }
243*cc02d7e2SAndroid Build Coastguard Worker     StringMap method_dict;
244*cc02d7e2SAndroid Build Coastguard Worker     method_dict["PackageQualifiedServiceName"] = package_qualified_service_name;
245*cc02d7e2SAndroid Build Coastguard Worker     out->Print("request_deserializers = {\n");
246*cc02d7e2SAndroid Build Coastguard Worker     for (StringMap::iterator name_and_input_module_class_pair =
247*cc02d7e2SAndroid Build Coastguard Worker              input_message_modules_and_classes.begin();
248*cc02d7e2SAndroid Build Coastguard Worker          name_and_input_module_class_pair !=
249*cc02d7e2SAndroid Build Coastguard Worker          input_message_modules_and_classes.end();
250*cc02d7e2SAndroid Build Coastguard Worker          name_and_input_module_class_pair++) {
251*cc02d7e2SAndroid Build Coastguard Worker       method_dict["MethodName"] = name_and_input_module_class_pair->first;
252*cc02d7e2SAndroid Build Coastguard Worker       method_dict["InputTypeModuleAndClass"] =
253*cc02d7e2SAndroid Build Coastguard Worker           name_and_input_module_class_pair->second;
254*cc02d7e2SAndroid Build Coastguard Worker       IndentScope raii_indent(out);
255*cc02d7e2SAndroid Build Coastguard Worker       out->Print(method_dict,
256*cc02d7e2SAndroid Build Coastguard Worker                  "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
257*cc02d7e2SAndroid Build Coastguard Worker                  "$InputTypeModuleAndClass$.FromString,\n");
258*cc02d7e2SAndroid Build Coastguard Worker     }
259*cc02d7e2SAndroid Build Coastguard Worker     out->Print("}\n");
260*cc02d7e2SAndroid Build Coastguard Worker     out->Print("response_serializers = {\n");
261*cc02d7e2SAndroid Build Coastguard Worker     for (StringMap::iterator name_and_output_module_class_pair =
262*cc02d7e2SAndroid Build Coastguard Worker              output_message_modules_and_classes.begin();
263*cc02d7e2SAndroid Build Coastguard Worker          name_and_output_module_class_pair !=
264*cc02d7e2SAndroid Build Coastguard Worker          output_message_modules_and_classes.end();
265*cc02d7e2SAndroid Build Coastguard Worker          name_and_output_module_class_pair++) {
266*cc02d7e2SAndroid Build Coastguard Worker       method_dict["MethodName"] = name_and_output_module_class_pair->first;
267*cc02d7e2SAndroid Build Coastguard Worker       method_dict["OutputTypeModuleAndClass"] =
268*cc02d7e2SAndroid Build Coastguard Worker           name_and_output_module_class_pair->second;
269*cc02d7e2SAndroid Build Coastguard Worker       IndentScope raii_indent(out);
270*cc02d7e2SAndroid Build Coastguard Worker       out->Print(method_dict,
271*cc02d7e2SAndroid Build Coastguard Worker                  "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
272*cc02d7e2SAndroid Build Coastguard Worker                  "$OutputTypeModuleAndClass$.SerializeToString,\n");
273*cc02d7e2SAndroid Build Coastguard Worker     }
274*cc02d7e2SAndroid Build Coastguard Worker     out->Print("}\n");
275*cc02d7e2SAndroid Build Coastguard Worker     out->Print("method_implementations = {\n");
276*cc02d7e2SAndroid Build Coastguard Worker     for (StringMap::iterator name_and_implementation_constructor =
277*cc02d7e2SAndroid Build Coastguard Worker              method_implementation_constructors.begin();
278*cc02d7e2SAndroid Build Coastguard Worker          name_and_implementation_constructor !=
279*cc02d7e2SAndroid Build Coastguard Worker          method_implementation_constructors.end();
280*cc02d7e2SAndroid Build Coastguard Worker          name_and_implementation_constructor++) {
281*cc02d7e2SAndroid Build Coastguard Worker       method_dict["Method"] = name_and_implementation_constructor->first;
282*cc02d7e2SAndroid Build Coastguard Worker       method_dict["Constructor"] = name_and_implementation_constructor->second;
283*cc02d7e2SAndroid Build Coastguard Worker       IndentScope raii_descriptions_indent(out);
284*cc02d7e2SAndroid Build Coastguard Worker       const std::string method_name =
285*cc02d7e2SAndroid Build Coastguard Worker           name_and_implementation_constructor->first;
286*cc02d7e2SAndroid Build Coastguard Worker       out->Print(method_dict,
287*cc02d7e2SAndroid Build Coastguard Worker                  "(\'$PackageQualifiedServiceName$\', \'$Method$\'): "
288*cc02d7e2SAndroid Build Coastguard Worker                  "face_utilities.$Constructor$(servicer.$Method$),\n");
289*cc02d7e2SAndroid Build Coastguard Worker     }
290*cc02d7e2SAndroid Build Coastguard Worker     out->Print("}\n");
291*cc02d7e2SAndroid Build Coastguard Worker     out->Print(
292*cc02d7e2SAndroid Build Coastguard Worker         "server_options = beta_implementations.server_options("
293*cc02d7e2SAndroid Build Coastguard Worker         "request_deserializers=request_deserializers, "
294*cc02d7e2SAndroid Build Coastguard Worker         "response_serializers=response_serializers, "
295*cc02d7e2SAndroid Build Coastguard Worker         "thread_pool=pool, thread_pool_size=pool_size, "
296*cc02d7e2SAndroid Build Coastguard Worker         "default_timeout=default_timeout, "
297*cc02d7e2SAndroid Build Coastguard Worker         "maximum_timeout=maximum_timeout)\n");
298*cc02d7e2SAndroid Build Coastguard Worker     out->Print(
299*cc02d7e2SAndroid Build Coastguard Worker         "return beta_implementations.server(method_implementations, "
300*cc02d7e2SAndroid Build Coastguard Worker         "options=server_options)\n");
301*cc02d7e2SAndroid Build Coastguard Worker   }
302*cc02d7e2SAndroid Build Coastguard Worker   return true;
303*cc02d7e2SAndroid Build Coastguard Worker }
304*cc02d7e2SAndroid Build Coastguard Worker 
PrintBetaStubFactory(const std::string & package_qualified_service_name,const grpc_generator::Service * service,grpc_generator::Printer * out)305*cc02d7e2SAndroid Build Coastguard Worker bool PrivateGenerator::PrintBetaStubFactory(
306*cc02d7e2SAndroid Build Coastguard Worker     const std::string& package_qualified_service_name,
307*cc02d7e2SAndroid Build Coastguard Worker     const grpc_generator::Service* service, grpc_generator::Printer* out) {
308*cc02d7e2SAndroid Build Coastguard Worker   StringMap dict;
309*cc02d7e2SAndroid Build Coastguard Worker   dict["Service"] = service->name();
310*cc02d7e2SAndroid Build Coastguard Worker   out->Print("\n\n");
311*cc02d7e2SAndroid Build Coastguard Worker   out->Print(dict,
312*cc02d7e2SAndroid Build Coastguard Worker              "def beta_create_$Service$_stub(channel, host=None,"
313*cc02d7e2SAndroid Build Coastguard Worker              " metadata_transformer=None, pool=None, pool_size=None):\n");
314*cc02d7e2SAndroid Build Coastguard Worker   {
315*cc02d7e2SAndroid Build Coastguard Worker     IndentScope raii_create_server_indent(out);
316*cc02d7e2SAndroid Build Coastguard Worker     out->Print(
317*cc02d7e2SAndroid Build Coastguard Worker         "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
318*cc02d7e2SAndroid Build Coastguard Worker         "\nIt is recommended to use the GA API (classes and functions in this\n"
319*cc02d7e2SAndroid Build Coastguard Worker         "file not marked beta) for all further purposes. This function was\n"
320*cc02d7e2SAndroid Build Coastguard Worker         "generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"
321*cc02d7e2SAndroid Build Coastguard Worker         "\"\"\"\n");
322*cc02d7e2SAndroid Build Coastguard Worker     StringMap method_cardinalities;
323*cc02d7e2SAndroid Build Coastguard Worker     StringMap input_message_modules_and_classes;
324*cc02d7e2SAndroid Build Coastguard Worker     StringMap output_message_modules_and_classes;
325*cc02d7e2SAndroid Build Coastguard Worker     for (int i = 0; i < service->method_count(); ++i) {
326*cc02d7e2SAndroid Build Coastguard Worker       auto method = service->method(i);
327*cc02d7e2SAndroid Build Coastguard Worker       const std::string method_cardinality =
328*cc02d7e2SAndroid Build Coastguard Worker           std::string(method->ClientStreaming() ? "STREAM" : "UNARY") + "_" +
329*cc02d7e2SAndroid Build Coastguard Worker           std::string(method->ServerStreaming() ? "STREAM" : "UNARY");
330*cc02d7e2SAndroid Build Coastguard Worker       std::string input_message_module_and_class;
331*cc02d7e2SAndroid Build Coastguard Worker       if (!method->get_module_and_message_path_input(
332*cc02d7e2SAndroid Build Coastguard Worker               &input_message_module_and_class, generator_file_name,
333*cc02d7e2SAndroid Build Coastguard Worker               generate_in_pb2_grpc, config.import_prefix,
334*cc02d7e2SAndroid Build Coastguard Worker               config.prefixes_to_filter)) {
335*cc02d7e2SAndroid Build Coastguard Worker         return false;
336*cc02d7e2SAndroid Build Coastguard Worker       }
337*cc02d7e2SAndroid Build Coastguard Worker       std::string output_message_module_and_class;
338*cc02d7e2SAndroid Build Coastguard Worker       if (!method->get_module_and_message_path_output(
339*cc02d7e2SAndroid Build Coastguard Worker               &output_message_module_and_class, generator_file_name,
340*cc02d7e2SAndroid Build Coastguard Worker               generate_in_pb2_grpc, config.import_prefix,
341*cc02d7e2SAndroid Build Coastguard Worker               config.prefixes_to_filter)) {
342*cc02d7e2SAndroid Build Coastguard Worker         return false;
343*cc02d7e2SAndroid Build Coastguard Worker       }
344*cc02d7e2SAndroid Build Coastguard Worker       method_cardinalities.insert(
345*cc02d7e2SAndroid Build Coastguard Worker           make_pair(method->name(), method_cardinality));
346*cc02d7e2SAndroid Build Coastguard Worker       input_message_modules_and_classes.insert(
347*cc02d7e2SAndroid Build Coastguard Worker           make_pair(method->name(), input_message_module_and_class));
348*cc02d7e2SAndroid Build Coastguard Worker       output_message_modules_and_classes.insert(
349*cc02d7e2SAndroid Build Coastguard Worker           make_pair(method->name(), output_message_module_and_class));
350*cc02d7e2SAndroid Build Coastguard Worker     }
351*cc02d7e2SAndroid Build Coastguard Worker     StringMap method_dict;
352*cc02d7e2SAndroid Build Coastguard Worker     method_dict["PackageQualifiedServiceName"] = package_qualified_service_name;
353*cc02d7e2SAndroid Build Coastguard Worker     out->Print("request_serializers = {\n");
354*cc02d7e2SAndroid Build Coastguard Worker     for (StringMap::iterator name_and_input_module_class_pair =
355*cc02d7e2SAndroid Build Coastguard Worker              input_message_modules_and_classes.begin();
356*cc02d7e2SAndroid Build Coastguard Worker          name_and_input_module_class_pair !=
357*cc02d7e2SAndroid Build Coastguard Worker          input_message_modules_and_classes.end();
358*cc02d7e2SAndroid Build Coastguard Worker          name_and_input_module_class_pair++) {
359*cc02d7e2SAndroid Build Coastguard Worker       method_dict["MethodName"] = name_and_input_module_class_pair->first;
360*cc02d7e2SAndroid Build Coastguard Worker       method_dict["InputTypeModuleAndClass"] =
361*cc02d7e2SAndroid Build Coastguard Worker           name_and_input_module_class_pair->second;
362*cc02d7e2SAndroid Build Coastguard Worker       IndentScope raii_indent(out);
363*cc02d7e2SAndroid Build Coastguard Worker       out->Print(method_dict,
364*cc02d7e2SAndroid Build Coastguard Worker                  "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
365*cc02d7e2SAndroid Build Coastguard Worker                  "$InputTypeModuleAndClass$.SerializeToString,\n");
366*cc02d7e2SAndroid Build Coastguard Worker     }
367*cc02d7e2SAndroid Build Coastguard Worker     out->Print("}\n");
368*cc02d7e2SAndroid Build Coastguard Worker     out->Print("response_deserializers = {\n");
369*cc02d7e2SAndroid Build Coastguard Worker     for (StringMap::iterator name_and_output_module_class_pair =
370*cc02d7e2SAndroid Build Coastguard Worker              output_message_modules_and_classes.begin();
371*cc02d7e2SAndroid Build Coastguard Worker          name_and_output_module_class_pair !=
372*cc02d7e2SAndroid Build Coastguard Worker          output_message_modules_and_classes.end();
373*cc02d7e2SAndroid Build Coastguard Worker          name_and_output_module_class_pair++) {
374*cc02d7e2SAndroid Build Coastguard Worker       method_dict["MethodName"] = name_and_output_module_class_pair->first;
375*cc02d7e2SAndroid Build Coastguard Worker       method_dict["OutputTypeModuleAndClass"] =
376*cc02d7e2SAndroid Build Coastguard Worker           name_and_output_module_class_pair->second;
377*cc02d7e2SAndroid Build Coastguard Worker       IndentScope raii_indent(out);
378*cc02d7e2SAndroid Build Coastguard Worker       out->Print(method_dict,
379*cc02d7e2SAndroid Build Coastguard Worker                  "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
380*cc02d7e2SAndroid Build Coastguard Worker                  "$OutputTypeModuleAndClass$.FromString,\n");
381*cc02d7e2SAndroid Build Coastguard Worker     }
382*cc02d7e2SAndroid Build Coastguard Worker     out->Print("}\n");
383*cc02d7e2SAndroid Build Coastguard Worker     out->Print("cardinalities = {\n");
384*cc02d7e2SAndroid Build Coastguard Worker     for (StringMap::iterator name_and_cardinality =
385*cc02d7e2SAndroid Build Coastguard Worker              method_cardinalities.begin();
386*cc02d7e2SAndroid Build Coastguard Worker          name_and_cardinality != method_cardinalities.end();
387*cc02d7e2SAndroid Build Coastguard Worker          name_and_cardinality++) {
388*cc02d7e2SAndroid Build Coastguard Worker       method_dict["Method"] = name_and_cardinality->first;
389*cc02d7e2SAndroid Build Coastguard Worker       method_dict["Cardinality"] = name_and_cardinality->second;
390*cc02d7e2SAndroid Build Coastguard Worker       IndentScope raii_descriptions_indent(out);
391*cc02d7e2SAndroid Build Coastguard Worker       out->Print(method_dict,
392*cc02d7e2SAndroid Build Coastguard Worker                  "\'$Method$\': cardinality.Cardinality.$Cardinality$,\n");
393*cc02d7e2SAndroid Build Coastguard Worker     }
394*cc02d7e2SAndroid Build Coastguard Worker     out->Print("}\n");
395*cc02d7e2SAndroid Build Coastguard Worker     out->Print(
396*cc02d7e2SAndroid Build Coastguard Worker         "stub_options = beta_implementations.stub_options("
397*cc02d7e2SAndroid Build Coastguard Worker         "host=host, metadata_transformer=metadata_transformer, "
398*cc02d7e2SAndroid Build Coastguard Worker         "request_serializers=request_serializers, "
399*cc02d7e2SAndroid Build Coastguard Worker         "response_deserializers=response_deserializers, "
400*cc02d7e2SAndroid Build Coastguard Worker         "thread_pool=pool, thread_pool_size=pool_size)\n");
401*cc02d7e2SAndroid Build Coastguard Worker     out->Print(method_dict,
402*cc02d7e2SAndroid Build Coastguard Worker                "return beta_implementations.dynamic_stub(channel, "
403*cc02d7e2SAndroid Build Coastguard Worker                "\'$PackageQualifiedServiceName$\', "
404*cc02d7e2SAndroid Build Coastguard Worker                "cardinalities, options=stub_options)\n");
405*cc02d7e2SAndroid Build Coastguard Worker   }
406*cc02d7e2SAndroid Build Coastguard Worker   return true;
407*cc02d7e2SAndroid Build Coastguard Worker }
408*cc02d7e2SAndroid Build Coastguard Worker 
PrintStub(const std::string & package_qualified_service_name,const grpc_generator::Service * service,grpc_generator::Printer * out)409*cc02d7e2SAndroid Build Coastguard Worker bool PrivateGenerator::PrintStub(
410*cc02d7e2SAndroid Build Coastguard Worker     const std::string& package_qualified_service_name,
411*cc02d7e2SAndroid Build Coastguard Worker     const grpc_generator::Service* service, grpc_generator::Printer* out) {
412*cc02d7e2SAndroid Build Coastguard Worker   StringMap dict;
413*cc02d7e2SAndroid Build Coastguard Worker   dict["Service"] = service->name();
414*cc02d7e2SAndroid Build Coastguard Worker   out->Print("\n\n");
415*cc02d7e2SAndroid Build Coastguard Worker   out->Print(dict, "class $Service$Stub(object):\n");
416*cc02d7e2SAndroid Build Coastguard Worker   {
417*cc02d7e2SAndroid Build Coastguard Worker     IndentScope raii_class_indent(out);
418*cc02d7e2SAndroid Build Coastguard Worker     StringVector service_comments = service->GetAllComments();
419*cc02d7e2SAndroid Build Coastguard Worker     PrintAllComments(service_comments, out);
420*cc02d7e2SAndroid Build Coastguard Worker     out->Print("\n");
421*cc02d7e2SAndroid Build Coastguard Worker     out->Print("def __init__(self, channel):\n");
422*cc02d7e2SAndroid Build Coastguard Worker     {
423*cc02d7e2SAndroid Build Coastguard Worker       IndentScope raii_init_indent(out);
424*cc02d7e2SAndroid Build Coastguard Worker       out->Print("\"\"\"Constructor.\n");
425*cc02d7e2SAndroid Build Coastguard Worker       out->Print("\n");
426*cc02d7e2SAndroid Build Coastguard Worker       out->Print("Args:\n");
427*cc02d7e2SAndroid Build Coastguard Worker       {
428*cc02d7e2SAndroid Build Coastguard Worker         IndentScope raii_args_indent(out);
429*cc02d7e2SAndroid Build Coastguard Worker         out->Print("channel: A grpc.Channel.\n");
430*cc02d7e2SAndroid Build Coastguard Worker       }
431*cc02d7e2SAndroid Build Coastguard Worker       out->Print("\"\"\"\n");
432*cc02d7e2SAndroid Build Coastguard Worker       for (int i = 0; i < service->method_count(); ++i) {
433*cc02d7e2SAndroid Build Coastguard Worker         auto method = service->method(i);
434*cc02d7e2SAndroid Build Coastguard Worker         std::string multi_callable_constructor =
435*cc02d7e2SAndroid Build Coastguard Worker             std::string(method->ClientStreaming() ? "stream" : "unary") + "_" +
436*cc02d7e2SAndroid Build Coastguard Worker             std::string(method->ServerStreaming() ? "stream" : "unary");
437*cc02d7e2SAndroid Build Coastguard Worker         std::string request_module_and_class;
438*cc02d7e2SAndroid Build Coastguard Worker         if (!method->get_module_and_message_path_input(
439*cc02d7e2SAndroid Build Coastguard Worker                 &request_module_and_class, generator_file_name,
440*cc02d7e2SAndroid Build Coastguard Worker                 generate_in_pb2_grpc, config.import_prefix,
441*cc02d7e2SAndroid Build Coastguard Worker                 config.prefixes_to_filter)) {
442*cc02d7e2SAndroid Build Coastguard Worker           return false;
443*cc02d7e2SAndroid Build Coastguard Worker         }
444*cc02d7e2SAndroid Build Coastguard Worker         std::string response_module_and_class;
445*cc02d7e2SAndroid Build Coastguard Worker         if (!method->get_module_and_message_path_output(
446*cc02d7e2SAndroid Build Coastguard Worker                 &response_module_and_class, generator_file_name,
447*cc02d7e2SAndroid Build Coastguard Worker                 generate_in_pb2_grpc, config.import_prefix,
448*cc02d7e2SAndroid Build Coastguard Worker                 config.prefixes_to_filter)) {
449*cc02d7e2SAndroid Build Coastguard Worker           return false;
450*cc02d7e2SAndroid Build Coastguard Worker         }
451*cc02d7e2SAndroid Build Coastguard Worker         StringMap method_dict;
452*cc02d7e2SAndroid Build Coastguard Worker         method_dict["Method"] = method->name();
453*cc02d7e2SAndroid Build Coastguard Worker         method_dict["MultiCallableConstructor"] = multi_callable_constructor;
454*cc02d7e2SAndroid Build Coastguard Worker         out->Print(method_dict,
455*cc02d7e2SAndroid Build Coastguard Worker                    "self.$Method$ = channel.$MultiCallableConstructor$(\n");
456*cc02d7e2SAndroid Build Coastguard Worker         {
457*cc02d7e2SAndroid Build Coastguard Worker           method_dict["PackageQualifiedService"] =
458*cc02d7e2SAndroid Build Coastguard Worker               package_qualified_service_name;
459*cc02d7e2SAndroid Build Coastguard Worker           method_dict["RequestModuleAndClass"] = request_module_and_class;
460*cc02d7e2SAndroid Build Coastguard Worker           method_dict["ResponseModuleAndClass"] = response_module_and_class;
461*cc02d7e2SAndroid Build Coastguard Worker           IndentScope raii_first_attribute_indent(out);
462*cc02d7e2SAndroid Build Coastguard Worker           IndentScope raii_second_attribute_indent(out);
463*cc02d7e2SAndroid Build Coastguard Worker           out->Print(method_dict, "'/$PackageQualifiedService$/$Method$',\n");
464*cc02d7e2SAndroid Build Coastguard Worker           out->Print(method_dict,
465*cc02d7e2SAndroid Build Coastguard Worker                      "request_serializer=$RequestModuleAndClass$."
466*cc02d7e2SAndroid Build Coastguard Worker                      "SerializeToString,\n");
467*cc02d7e2SAndroid Build Coastguard Worker           out->Print(
468*cc02d7e2SAndroid Build Coastguard Worker               method_dict,
469*cc02d7e2SAndroid Build Coastguard Worker               "response_deserializer=$ResponseModuleAndClass$.FromString,\n");
470*cc02d7e2SAndroid Build Coastguard Worker           out->Print("_registered_method=True)\n");
471*cc02d7e2SAndroid Build Coastguard Worker         }
472*cc02d7e2SAndroid Build Coastguard Worker       }
473*cc02d7e2SAndroid Build Coastguard Worker     }
474*cc02d7e2SAndroid Build Coastguard Worker   }
475*cc02d7e2SAndroid Build Coastguard Worker   return true;
476*cc02d7e2SAndroid Build Coastguard Worker }
477*cc02d7e2SAndroid Build Coastguard Worker 
PrintServicer(const grpc_generator::Service * service,grpc_generator::Printer * out)478*cc02d7e2SAndroid Build Coastguard Worker bool PrivateGenerator::PrintServicer(const grpc_generator::Service* service,
479*cc02d7e2SAndroid Build Coastguard Worker                                      grpc_generator::Printer* out) {
480*cc02d7e2SAndroid Build Coastguard Worker   StringMap service_dict;
481*cc02d7e2SAndroid Build Coastguard Worker   service_dict["Service"] = service->name();
482*cc02d7e2SAndroid Build Coastguard Worker   out->Print("\n\n");
483*cc02d7e2SAndroid Build Coastguard Worker   out->Print(service_dict, "class $Service$Servicer(object):\n");
484*cc02d7e2SAndroid Build Coastguard Worker   {
485*cc02d7e2SAndroid Build Coastguard Worker     IndentScope raii_class_indent(out);
486*cc02d7e2SAndroid Build Coastguard Worker     StringVector service_comments = service->GetAllComments();
487*cc02d7e2SAndroid Build Coastguard Worker     PrintAllComments(service_comments, out);
488*cc02d7e2SAndroid Build Coastguard Worker     for (int i = 0; i < service->method_count(); ++i) {
489*cc02d7e2SAndroid Build Coastguard Worker       auto method = service->method(i);
490*cc02d7e2SAndroid Build Coastguard Worker       std::string arg_name =
491*cc02d7e2SAndroid Build Coastguard Worker           method->ClientStreaming() ? "request_iterator" : "request";
492*cc02d7e2SAndroid Build Coastguard Worker       StringMap method_dict;
493*cc02d7e2SAndroid Build Coastguard Worker       method_dict["Method"] = method->name();
494*cc02d7e2SAndroid Build Coastguard Worker       method_dict["ArgName"] = arg_name;
495*cc02d7e2SAndroid Build Coastguard Worker       out->Print("\n");
496*cc02d7e2SAndroid Build Coastguard Worker       out->Print(method_dict, "def $Method$(self, $ArgName$, context):\n");
497*cc02d7e2SAndroid Build Coastguard Worker       {
498*cc02d7e2SAndroid Build Coastguard Worker         IndentScope raii_method_indent(out);
499*cc02d7e2SAndroid Build Coastguard Worker         StringVector method_comments = method->GetAllComments();
500*cc02d7e2SAndroid Build Coastguard Worker         PrintAllComments(method_comments, out);
501*cc02d7e2SAndroid Build Coastguard Worker         out->Print("context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n");
502*cc02d7e2SAndroid Build Coastguard Worker         out->Print("context.set_details('Method not implemented!')\n");
503*cc02d7e2SAndroid Build Coastguard Worker         out->Print("raise NotImplementedError('Method not implemented!')\n");
504*cc02d7e2SAndroid Build Coastguard Worker       }
505*cc02d7e2SAndroid Build Coastguard Worker     }
506*cc02d7e2SAndroid Build Coastguard Worker   }
507*cc02d7e2SAndroid Build Coastguard Worker   return true;
508*cc02d7e2SAndroid Build Coastguard Worker }
509*cc02d7e2SAndroid Build Coastguard Worker 
PrintAddServicerToServer(const std::string & package_qualified_service_name,const grpc_generator::Service * service,grpc_generator::Printer * out)510*cc02d7e2SAndroid Build Coastguard Worker bool PrivateGenerator::PrintAddServicerToServer(
511*cc02d7e2SAndroid Build Coastguard Worker     const std::string& package_qualified_service_name,
512*cc02d7e2SAndroid Build Coastguard Worker     const grpc_generator::Service* service, grpc_generator::Printer* out) {
513*cc02d7e2SAndroid Build Coastguard Worker   StringMap service_dict;
514*cc02d7e2SAndroid Build Coastguard Worker   service_dict["Service"] = service->name();
515*cc02d7e2SAndroid Build Coastguard Worker   out->Print("\n\n");
516*cc02d7e2SAndroid Build Coastguard Worker   out->Print(service_dict,
517*cc02d7e2SAndroid Build Coastguard Worker              "def add_$Service$Servicer_to_server(servicer, server):\n");
518*cc02d7e2SAndroid Build Coastguard Worker   {
519*cc02d7e2SAndroid Build Coastguard Worker     IndentScope raii_class_indent(out);
520*cc02d7e2SAndroid Build Coastguard Worker     out->Print("rpc_method_handlers = {\n");
521*cc02d7e2SAndroid Build Coastguard Worker     {
522*cc02d7e2SAndroid Build Coastguard Worker       IndentScope raii_dict_first_indent(out);
523*cc02d7e2SAndroid Build Coastguard Worker       IndentScope raii_dict_second_indent(out);
524*cc02d7e2SAndroid Build Coastguard Worker       for (int i = 0; i < service->method_count(); ++i) {
525*cc02d7e2SAndroid Build Coastguard Worker         auto method = service->method(i);
526*cc02d7e2SAndroid Build Coastguard Worker         std::string method_handler_constructor =
527*cc02d7e2SAndroid Build Coastguard Worker             std::string(method->ClientStreaming() ? "stream" : "unary") + "_" +
528*cc02d7e2SAndroid Build Coastguard Worker             std::string(method->ServerStreaming() ? "stream" : "unary") +
529*cc02d7e2SAndroid Build Coastguard Worker             "_rpc_method_handler";
530*cc02d7e2SAndroid Build Coastguard Worker         std::string request_module_and_class;
531*cc02d7e2SAndroid Build Coastguard Worker         if (!method->get_module_and_message_path_input(
532*cc02d7e2SAndroid Build Coastguard Worker                 &request_module_and_class, generator_file_name,
533*cc02d7e2SAndroid Build Coastguard Worker                 generate_in_pb2_grpc, config.import_prefix,
534*cc02d7e2SAndroid Build Coastguard Worker                 config.prefixes_to_filter)) {
535*cc02d7e2SAndroid Build Coastguard Worker           return false;
536*cc02d7e2SAndroid Build Coastguard Worker         }
537*cc02d7e2SAndroid Build Coastguard Worker         std::string response_module_and_class;
538*cc02d7e2SAndroid Build Coastguard Worker         if (!method->get_module_and_message_path_output(
539*cc02d7e2SAndroid Build Coastguard Worker                 &response_module_and_class, generator_file_name,
540*cc02d7e2SAndroid Build Coastguard Worker                 generate_in_pb2_grpc, config.import_prefix,
541*cc02d7e2SAndroid Build Coastguard Worker                 config.prefixes_to_filter)) {
542*cc02d7e2SAndroid Build Coastguard Worker           return false;
543*cc02d7e2SAndroid Build Coastguard Worker         }
544*cc02d7e2SAndroid Build Coastguard Worker         StringMap method_dict;
545*cc02d7e2SAndroid Build Coastguard Worker         method_dict["Method"] = method->name();
546*cc02d7e2SAndroid Build Coastguard Worker         method_dict["MethodHandlerConstructor"] = method_handler_constructor;
547*cc02d7e2SAndroid Build Coastguard Worker         method_dict["RequestModuleAndClass"] = request_module_and_class;
548*cc02d7e2SAndroid Build Coastguard Worker         method_dict["ResponseModuleAndClass"] = response_module_and_class;
549*cc02d7e2SAndroid Build Coastguard Worker         out->Print(method_dict,
550*cc02d7e2SAndroid Build Coastguard Worker                    "'$Method$': grpc.$MethodHandlerConstructor$(\n");
551*cc02d7e2SAndroid Build Coastguard Worker         {
552*cc02d7e2SAndroid Build Coastguard Worker           IndentScope raii_call_first_indent(out);
553*cc02d7e2SAndroid Build Coastguard Worker           IndentScope raii_call_second_indent(out);
554*cc02d7e2SAndroid Build Coastguard Worker           out->Print(method_dict, "servicer.$Method$,\n");
555*cc02d7e2SAndroid Build Coastguard Worker           out->Print(
556*cc02d7e2SAndroid Build Coastguard Worker               method_dict,
557*cc02d7e2SAndroid Build Coastguard Worker               "request_deserializer=$RequestModuleAndClass$.FromString,\n");
558*cc02d7e2SAndroid Build Coastguard Worker           out->Print(
559*cc02d7e2SAndroid Build Coastguard Worker               method_dict,
560*cc02d7e2SAndroid Build Coastguard Worker               "response_serializer=$ResponseModuleAndClass$.SerializeToString,"
561*cc02d7e2SAndroid Build Coastguard Worker               "\n");
562*cc02d7e2SAndroid Build Coastguard Worker         }
563*cc02d7e2SAndroid Build Coastguard Worker         out->Print("),\n");
564*cc02d7e2SAndroid Build Coastguard Worker       }
565*cc02d7e2SAndroid Build Coastguard Worker     }
566*cc02d7e2SAndroid Build Coastguard Worker     StringMap method_dict;
567*cc02d7e2SAndroid Build Coastguard Worker     method_dict["PackageQualifiedServiceName"] = package_qualified_service_name;
568*cc02d7e2SAndroid Build Coastguard Worker     out->Print("}\n");
569*cc02d7e2SAndroid Build Coastguard Worker     out->Print("generic_handler = grpc.method_handlers_generic_handler(\n");
570*cc02d7e2SAndroid Build Coastguard Worker     {
571*cc02d7e2SAndroid Build Coastguard Worker       IndentScope raii_call_first_indent(out);
572*cc02d7e2SAndroid Build Coastguard Worker       IndentScope raii_call_second_indent(out);
573*cc02d7e2SAndroid Build Coastguard Worker       out->Print(method_dict,
574*cc02d7e2SAndroid Build Coastguard Worker                  "'$PackageQualifiedServiceName$', rpc_method_handlers)\n");
575*cc02d7e2SAndroid Build Coastguard Worker     }
576*cc02d7e2SAndroid Build Coastguard Worker     out->Print("server.add_generic_rpc_handlers((generic_handler,))\n");
577*cc02d7e2SAndroid Build Coastguard Worker   }
578*cc02d7e2SAndroid Build Coastguard Worker   return true;
579*cc02d7e2SAndroid Build Coastguard Worker }
580*cc02d7e2SAndroid Build Coastguard Worker 
581*cc02d7e2SAndroid Build Coastguard Worker /* Prints out a service class used as a container for static methods pertaining
582*cc02d7e2SAndroid Build Coastguard Worker  * to a class. This class has the exact name of service written in the ".proto"
583*cc02d7e2SAndroid Build Coastguard Worker  * file, with no suffixes. Since this class merely acts as a namespace, it
584*cc02d7e2SAndroid Build Coastguard Worker  * should never be instantiated.
585*cc02d7e2SAndroid Build Coastguard Worker  */
PrintServiceClass(const std::string & package_qualified_service_name,const grpc_generator::Service * service,grpc_generator::Printer * out)586*cc02d7e2SAndroid Build Coastguard Worker bool PrivateGenerator::PrintServiceClass(
587*cc02d7e2SAndroid Build Coastguard Worker     const std::string& package_qualified_service_name,
588*cc02d7e2SAndroid Build Coastguard Worker     const grpc_generator::Service* service, grpc_generator::Printer* out) {
589*cc02d7e2SAndroid Build Coastguard Worker   StringMap dict;
590*cc02d7e2SAndroid Build Coastguard Worker   dict["Service"] = service->name();
591*cc02d7e2SAndroid Build Coastguard Worker   out->Print("\n\n");
592*cc02d7e2SAndroid Build Coastguard Worker   out->Print(" # This class is part of an EXPERIMENTAL API.\n");
593*cc02d7e2SAndroid Build Coastguard Worker   out->Print(dict, "class $Service$(object):\n");
594*cc02d7e2SAndroid Build Coastguard Worker   {
595*cc02d7e2SAndroid Build Coastguard Worker     IndentScope class_indent(out);
596*cc02d7e2SAndroid Build Coastguard Worker     StringVector service_comments = service->GetAllComments();
597*cc02d7e2SAndroid Build Coastguard Worker     PrintAllComments(service_comments, out);
598*cc02d7e2SAndroid Build Coastguard Worker     for (int i = 0; i < service->method_count(); ++i) {
599*cc02d7e2SAndroid Build Coastguard Worker       const auto& method = service->method(i);
600*cc02d7e2SAndroid Build Coastguard Worker       std::string request_module_and_class;
601*cc02d7e2SAndroid Build Coastguard Worker       if (!method->get_module_and_message_path_input(
602*cc02d7e2SAndroid Build Coastguard Worker               &request_module_and_class, generator_file_name,
603*cc02d7e2SAndroid Build Coastguard Worker               generate_in_pb2_grpc, config.import_prefix,
604*cc02d7e2SAndroid Build Coastguard Worker               config.prefixes_to_filter)) {
605*cc02d7e2SAndroid Build Coastguard Worker         return false;
606*cc02d7e2SAndroid Build Coastguard Worker       }
607*cc02d7e2SAndroid Build Coastguard Worker       std::string response_module_and_class;
608*cc02d7e2SAndroid Build Coastguard Worker       if (!method->get_module_and_message_path_output(
609*cc02d7e2SAndroid Build Coastguard Worker               &response_module_and_class, generator_file_name,
610*cc02d7e2SAndroid Build Coastguard Worker               generate_in_pb2_grpc, config.import_prefix,
611*cc02d7e2SAndroid Build Coastguard Worker               config.prefixes_to_filter)) {
612*cc02d7e2SAndroid Build Coastguard Worker         return false;
613*cc02d7e2SAndroid Build Coastguard Worker       }
614*cc02d7e2SAndroid Build Coastguard Worker       out->Print("\n");
615*cc02d7e2SAndroid Build Coastguard Worker       StringMap method_dict;
616*cc02d7e2SAndroid Build Coastguard Worker       method_dict["Method"] = method->name();
617*cc02d7e2SAndroid Build Coastguard Worker       out->Print("@staticmethod\n");
618*cc02d7e2SAndroid Build Coastguard Worker       out->Print(method_dict, "def $Method$(");
619*cc02d7e2SAndroid Build Coastguard Worker       std::string request_parameter(
620*cc02d7e2SAndroid Build Coastguard Worker           method->ClientStreaming() ? "request_iterator" : "request");
621*cc02d7e2SAndroid Build Coastguard Worker       StringMap args_dict;
622*cc02d7e2SAndroid Build Coastguard Worker       args_dict["RequestParameter"] = request_parameter;
623*cc02d7e2SAndroid Build Coastguard Worker       {
624*cc02d7e2SAndroid Build Coastguard Worker         IndentScope args_indent(out);
625*cc02d7e2SAndroid Build Coastguard Worker         IndentScope args_double_indent(out);
626*cc02d7e2SAndroid Build Coastguard Worker         out->Print(args_dict, "$RequestParameter$,\n");
627*cc02d7e2SAndroid Build Coastguard Worker         out->Print("target,\n");
628*cc02d7e2SAndroid Build Coastguard Worker         out->Print("options=(),\n");
629*cc02d7e2SAndroid Build Coastguard Worker         out->Print("channel_credentials=None,\n");
630*cc02d7e2SAndroid Build Coastguard Worker         out->Print("call_credentials=None,\n");
631*cc02d7e2SAndroid Build Coastguard Worker         out->Print("insecure=False,\n");
632*cc02d7e2SAndroid Build Coastguard Worker         out->Print("compression=None,\n");
633*cc02d7e2SAndroid Build Coastguard Worker         out->Print("wait_for_ready=None,\n");
634*cc02d7e2SAndroid Build Coastguard Worker         out->Print("timeout=None,\n");
635*cc02d7e2SAndroid Build Coastguard Worker         out->Print("metadata=None):\n");
636*cc02d7e2SAndroid Build Coastguard Worker       }
637*cc02d7e2SAndroid Build Coastguard Worker       {
638*cc02d7e2SAndroid Build Coastguard Worker         IndentScope method_indent(out);
639*cc02d7e2SAndroid Build Coastguard Worker         std::string arity_method_name =
640*cc02d7e2SAndroid Build Coastguard Worker             std::string(method->ClientStreaming() ? "stream" : "unary") + "_" +
641*cc02d7e2SAndroid Build Coastguard Worker             std::string(method->ServerStreaming() ? "stream" : "unary");
642*cc02d7e2SAndroid Build Coastguard Worker         args_dict["ArityMethodName"] = arity_method_name;
643*cc02d7e2SAndroid Build Coastguard Worker         args_dict["PackageQualifiedService"] = package_qualified_service_name;
644*cc02d7e2SAndroid Build Coastguard Worker         args_dict["Method"] = method->name();
645*cc02d7e2SAndroid Build Coastguard Worker         out->Print(args_dict, "return grpc.experimental.$ArityMethodName$(\n");
646*cc02d7e2SAndroid Build Coastguard Worker         {
647*cc02d7e2SAndroid Build Coastguard Worker           IndentScope continuation_indent(out);
648*cc02d7e2SAndroid Build Coastguard Worker           StringMap serializer_dict;
649*cc02d7e2SAndroid Build Coastguard Worker           out->Print(args_dict, "$RequestParameter$,\n");
650*cc02d7e2SAndroid Build Coastguard Worker           out->Print("target,\n");
651*cc02d7e2SAndroid Build Coastguard Worker           out->Print(args_dict, "'/$PackageQualifiedService$/$Method$',\n");
652*cc02d7e2SAndroid Build Coastguard Worker           serializer_dict["RequestModuleAndClass"] = request_module_and_class;
653*cc02d7e2SAndroid Build Coastguard Worker           serializer_dict["ResponseModuleAndClass"] = response_module_and_class;
654*cc02d7e2SAndroid Build Coastguard Worker           out->Print(serializer_dict,
655*cc02d7e2SAndroid Build Coastguard Worker                      "$RequestModuleAndClass$.SerializeToString,\n");
656*cc02d7e2SAndroid Build Coastguard Worker           out->Print(serializer_dict, "$ResponseModuleAndClass$.FromString,\n");
657*cc02d7e2SAndroid Build Coastguard Worker           out->Print("options,\n");
658*cc02d7e2SAndroid Build Coastguard Worker           out->Print("channel_credentials,\n");
659*cc02d7e2SAndroid Build Coastguard Worker           out->Print("insecure,\n");
660*cc02d7e2SAndroid Build Coastguard Worker           out->Print("call_credentials,\n");
661*cc02d7e2SAndroid Build Coastguard Worker           out->Print("compression,\n");
662*cc02d7e2SAndroid Build Coastguard Worker           out->Print("wait_for_ready,\n");
663*cc02d7e2SAndroid Build Coastguard Worker           out->Print("timeout,\n");
664*cc02d7e2SAndroid Build Coastguard Worker           out->Print("metadata,\n");
665*cc02d7e2SAndroid Build Coastguard Worker           out->Print("_registered_method=True)\n");
666*cc02d7e2SAndroid Build Coastguard Worker         }
667*cc02d7e2SAndroid Build Coastguard Worker       }
668*cc02d7e2SAndroid Build Coastguard Worker     }
669*cc02d7e2SAndroid Build Coastguard Worker   }
670*cc02d7e2SAndroid Build Coastguard Worker   // TODO(rbellevi): Add methods pertinent to the server side as well.
671*cc02d7e2SAndroid Build Coastguard Worker   return true;
672*cc02d7e2SAndroid Build Coastguard Worker }
673*cc02d7e2SAndroid Build Coastguard Worker 
PrintBetaPreamble(grpc_generator::Printer * out)674*cc02d7e2SAndroid Build Coastguard Worker bool PrivateGenerator::PrintBetaPreamble(grpc_generator::Printer* out) {
675*cc02d7e2SAndroid Build Coastguard Worker   StringMap var;
676*cc02d7e2SAndroid Build Coastguard Worker   var["Package"] = config.beta_package_root;
677*cc02d7e2SAndroid Build Coastguard Worker   out->Print(var,
678*cc02d7e2SAndroid Build Coastguard Worker              "from $Package$ import implementations as beta_implementations\n");
679*cc02d7e2SAndroid Build Coastguard Worker   out->Print(var, "from $Package$ import interfaces as beta_interfaces\n");
680*cc02d7e2SAndroid Build Coastguard Worker   out->Print("from grpc.framework.common import cardinality\n");
681*cc02d7e2SAndroid Build Coastguard Worker   out->Print(
682*cc02d7e2SAndroid Build Coastguard Worker       "from grpc.framework.interfaces.face import utilities as "
683*cc02d7e2SAndroid Build Coastguard Worker       "face_utilities\n");
684*cc02d7e2SAndroid Build Coastguard Worker   return true;
685*cc02d7e2SAndroid Build Coastguard Worker }
686*cc02d7e2SAndroid Build Coastguard Worker 
PrintPreamble(grpc_generator::Printer * out)687*cc02d7e2SAndroid Build Coastguard Worker bool PrivateGenerator::PrintPreamble(grpc_generator::Printer* out) {
688*cc02d7e2SAndroid Build Coastguard Worker   StringMap var;
689*cc02d7e2SAndroid Build Coastguard Worker   var["Package"] = config.grpc_package_root;
690*cc02d7e2SAndroid Build Coastguard Worker   out->Print(var, "import $Package$\n");
691*cc02d7e2SAndroid Build Coastguard Worker   if (config.grpc_tools_version.size() > 0) {
692*cc02d7e2SAndroid Build Coastguard Worker     out->Print(var, "import warnings\n");
693*cc02d7e2SAndroid Build Coastguard Worker   }
694*cc02d7e2SAndroid Build Coastguard Worker   if (generate_in_pb2_grpc) {
695*cc02d7e2SAndroid Build Coastguard Worker     out->Print("\n");
696*cc02d7e2SAndroid Build Coastguard Worker     StringPairSet imports_set;
697*cc02d7e2SAndroid Build Coastguard Worker     for (int i = 0; i < file->service_count(); ++i) {
698*cc02d7e2SAndroid Build Coastguard Worker       auto service = file->service(i);
699*cc02d7e2SAndroid Build Coastguard Worker       for (int j = 0; j < service->method_count(); ++j) {
700*cc02d7e2SAndroid Build Coastguard Worker         auto method = service.get()->method(j);
701*cc02d7e2SAndroid Build Coastguard Worker 
702*cc02d7e2SAndroid Build Coastguard Worker         std::string input_type_file_name = method->get_input_type_name();
703*cc02d7e2SAndroid Build Coastguard Worker         std::string input_module_name =
704*cc02d7e2SAndroid Build Coastguard Worker             ModuleName(input_type_file_name, config.import_prefix,
705*cc02d7e2SAndroid Build Coastguard Worker                        config.prefixes_to_filter);
706*cc02d7e2SAndroid Build Coastguard Worker         std::string input_module_alias =
707*cc02d7e2SAndroid Build Coastguard Worker             ModuleAlias(input_type_file_name, config.import_prefix,
708*cc02d7e2SAndroid Build Coastguard Worker                         config.prefixes_to_filter);
709*cc02d7e2SAndroid Build Coastguard Worker         imports_set.insert(
710*cc02d7e2SAndroid Build Coastguard Worker             std::make_tuple(input_module_name, input_module_alias));
711*cc02d7e2SAndroid Build Coastguard Worker 
712*cc02d7e2SAndroid Build Coastguard Worker         std::string output_type_file_name = method->get_output_type_name();
713*cc02d7e2SAndroid Build Coastguard Worker         std::string output_module_name =
714*cc02d7e2SAndroid Build Coastguard Worker             ModuleName(output_type_file_name, config.import_prefix,
715*cc02d7e2SAndroid Build Coastguard Worker                        config.prefixes_to_filter);
716*cc02d7e2SAndroid Build Coastguard Worker         std::string output_module_alias =
717*cc02d7e2SAndroid Build Coastguard Worker             ModuleAlias(output_type_file_name, config.import_prefix,
718*cc02d7e2SAndroid Build Coastguard Worker                         config.prefixes_to_filter);
719*cc02d7e2SAndroid Build Coastguard Worker         imports_set.insert(
720*cc02d7e2SAndroid Build Coastguard Worker             std::make_tuple(output_module_name, output_module_alias));
721*cc02d7e2SAndroid Build Coastguard Worker       }
722*cc02d7e2SAndroid Build Coastguard Worker     }
723*cc02d7e2SAndroid Build Coastguard Worker 
724*cc02d7e2SAndroid Build Coastguard Worker     for (StringPairSet::iterator it = imports_set.begin();
725*cc02d7e2SAndroid Build Coastguard Worker          it != imports_set.end(); ++it) {
726*cc02d7e2SAndroid Build Coastguard Worker       auto module_name = std::get<0>(*it);
727*cc02d7e2SAndroid Build Coastguard Worker       var["ModuleAlias"] = std::get<1>(*it);
728*cc02d7e2SAndroid Build Coastguard Worker       const size_t last_dot_pos = module_name.rfind('.');
729*cc02d7e2SAndroid Build Coastguard Worker       if (last_dot_pos == std::string::npos) {
730*cc02d7e2SAndroid Build Coastguard Worker         var["ImportStatement"] = "import " + module_name;
731*cc02d7e2SAndroid Build Coastguard Worker       } else {
732*cc02d7e2SAndroid Build Coastguard Worker         var["ImportStatement"] = "from " + module_name.substr(0, last_dot_pos) +
733*cc02d7e2SAndroid Build Coastguard Worker                                  " import " +
734*cc02d7e2SAndroid Build Coastguard Worker                                  module_name.substr(last_dot_pos + 1);
735*cc02d7e2SAndroid Build Coastguard Worker       }
736*cc02d7e2SAndroid Build Coastguard Worker       out->Print(var, "$ImportStatement$ as $ModuleAlias$\n");
737*cc02d7e2SAndroid Build Coastguard Worker     }
738*cc02d7e2SAndroid Build Coastguard Worker 
739*cc02d7e2SAndroid Build Coastguard Worker     // Checks if generate code is used with a supported grpcio version.
740*cc02d7e2SAndroid Build Coastguard Worker     if (config.grpc_tools_version.size() > 0) {
741*cc02d7e2SAndroid Build Coastguard Worker       var["ToolsVersion"] = config.grpc_tools_version;
742*cc02d7e2SAndroid Build Coastguard Worker       out->Print(var, "\nGRPC_GENERATED_VERSION = '$ToolsVersion$'\n");
743*cc02d7e2SAndroid Build Coastguard Worker       out->Print("GRPC_VERSION = grpc.__version__\n");
744*cc02d7e2SAndroid Build Coastguard Worker       out->Print("EXPECTED_ERROR_RELEASE = '1.65.0'\n");
745*cc02d7e2SAndroid Build Coastguard Worker       out->Print("SCHEDULED_RELEASE_DATE = 'June 25, 2024'\n");
746*cc02d7e2SAndroid Build Coastguard Worker       out->Print("_version_not_supported = False\n\n");
747*cc02d7e2SAndroid Build Coastguard Worker       out->Print("try:\n");
748*cc02d7e2SAndroid Build Coastguard Worker       {
749*cc02d7e2SAndroid Build Coastguard Worker         IndentScope raii_import_indent(out);
750*cc02d7e2SAndroid Build Coastguard Worker         out->Print(
751*cc02d7e2SAndroid Build Coastguard Worker             "from grpc._utilities import first_version_is_lower\n"
752*cc02d7e2SAndroid Build Coastguard Worker             "_version_not_supported = first_version_is_lower(GRPC_VERSION, "
753*cc02d7e2SAndroid Build Coastguard Worker             "GRPC_GENERATED_VERSION)\n");
754*cc02d7e2SAndroid Build Coastguard Worker       }
755*cc02d7e2SAndroid Build Coastguard Worker       out->Print("except ImportError:\n");
756*cc02d7e2SAndroid Build Coastguard Worker       {
757*cc02d7e2SAndroid Build Coastguard Worker         IndentScope raii_import_error_indent(out);
758*cc02d7e2SAndroid Build Coastguard Worker         out->Print("_version_not_supported = True\n");
759*cc02d7e2SAndroid Build Coastguard Worker       }
760*cc02d7e2SAndroid Build Coastguard Worker       out->Print("\nif _version_not_supported:\n");
761*cc02d7e2SAndroid Build Coastguard Worker       {
762*cc02d7e2SAndroid Build Coastguard Worker         IndentScope raii_warning_indent(out);
763*cc02d7e2SAndroid Build Coastguard Worker         out->Print("warnings.warn(\n");
764*cc02d7e2SAndroid Build Coastguard Worker         {
765*cc02d7e2SAndroid Build Coastguard Worker           IndentScope raii_warning_string_indent(out);
766*cc02d7e2SAndroid Build Coastguard Worker           std::string filename_without_ext = file->filename_without_ext();
767*cc02d7e2SAndroid Build Coastguard Worker           std::replace(filename_without_ext.begin(), filename_without_ext.end(),
768*cc02d7e2SAndroid Build Coastguard Worker                        '-', '_');
769*cc02d7e2SAndroid Build Coastguard Worker           var["Pb2GrpcFileName"] = filename_without_ext;
770*cc02d7e2SAndroid Build Coastguard Worker           out->Print(
771*cc02d7e2SAndroid Build Coastguard Worker               var,
772*cc02d7e2SAndroid Build Coastguard Worker               "f'The grpc package installed is at version {GRPC_VERSION},'\n"
773*cc02d7e2SAndroid Build Coastguard Worker               "+ f' but the generated code in $Pb2GrpcFileName$_pb2_grpc.py "
774*cc02d7e2SAndroid Build Coastguard Worker               "depends on'\n"
775*cc02d7e2SAndroid Build Coastguard Worker               "+ f' grpcio>={GRPC_GENERATED_VERSION}.'\n"
776*cc02d7e2SAndroid Build Coastguard Worker               "+ f' Please upgrade your grpc module to "
777*cc02d7e2SAndroid Build Coastguard Worker               "grpcio>={GRPC_GENERATED_VERSION}'\n"
778*cc02d7e2SAndroid Build Coastguard Worker               "+ f' or downgrade your generated code using "
779*cc02d7e2SAndroid Build Coastguard Worker               "grpcio-tools<={GRPC_VERSION}.'\n"
780*cc02d7e2SAndroid Build Coastguard Worker               "+ f' This warning will become an error in "
781*cc02d7e2SAndroid Build Coastguard Worker               "{EXPECTED_ERROR_RELEASE},'\n"
782*cc02d7e2SAndroid Build Coastguard Worker               "+ f' scheduled for release on {SCHEDULED_RELEASE_DATE}.',\n"
783*cc02d7e2SAndroid Build Coastguard Worker               "RuntimeWarning\n");
784*cc02d7e2SAndroid Build Coastguard Worker         }
785*cc02d7e2SAndroid Build Coastguard Worker         out->Print(")\n");
786*cc02d7e2SAndroid Build Coastguard Worker       }
787*cc02d7e2SAndroid Build Coastguard Worker     }
788*cc02d7e2SAndroid Build Coastguard Worker   }
789*cc02d7e2SAndroid Build Coastguard Worker   return true;
790*cc02d7e2SAndroid Build Coastguard Worker }
791*cc02d7e2SAndroid Build Coastguard Worker 
PrintGAServices(grpc_generator::Printer * out)792*cc02d7e2SAndroid Build Coastguard Worker bool PrivateGenerator::PrintGAServices(grpc_generator::Printer* out) {
793*cc02d7e2SAndroid Build Coastguard Worker   std::string package = file->package();
794*cc02d7e2SAndroid Build Coastguard Worker   if (!package.empty()) {
795*cc02d7e2SAndroid Build Coastguard Worker     package = package.append(".");
796*cc02d7e2SAndroid Build Coastguard Worker   }
797*cc02d7e2SAndroid Build Coastguard Worker   for (int i = 0; i < file->service_count(); ++i) {
798*cc02d7e2SAndroid Build Coastguard Worker     auto service = file->service(i);
799*cc02d7e2SAndroid Build Coastguard Worker     std::string package_qualified_service_name = package + service->name();
800*cc02d7e2SAndroid Build Coastguard Worker     if (!(PrintStub(package_qualified_service_name, service.get(), out) &&
801*cc02d7e2SAndroid Build Coastguard Worker           PrintServicer(service.get(), out) &&
802*cc02d7e2SAndroid Build Coastguard Worker           PrintAddServicerToServer(package_qualified_service_name,
803*cc02d7e2SAndroid Build Coastguard Worker                                    service.get(), out) &&
804*cc02d7e2SAndroid Build Coastguard Worker           PrintServiceClass(package_qualified_service_name, service.get(),
805*cc02d7e2SAndroid Build Coastguard Worker                             out))) {
806*cc02d7e2SAndroid Build Coastguard Worker       return false;
807*cc02d7e2SAndroid Build Coastguard Worker     }
808*cc02d7e2SAndroid Build Coastguard Worker   }
809*cc02d7e2SAndroid Build Coastguard Worker   return true;
810*cc02d7e2SAndroid Build Coastguard Worker }
811*cc02d7e2SAndroid Build Coastguard Worker 
PrintBetaServices(grpc_generator::Printer * out)812*cc02d7e2SAndroid Build Coastguard Worker bool PrivateGenerator::PrintBetaServices(grpc_generator::Printer* out) {
813*cc02d7e2SAndroid Build Coastguard Worker   std::string package = file->package();
814*cc02d7e2SAndroid Build Coastguard Worker   if (!package.empty()) {
815*cc02d7e2SAndroid Build Coastguard Worker     package = package.append(".");
816*cc02d7e2SAndroid Build Coastguard Worker   }
817*cc02d7e2SAndroid Build Coastguard Worker   for (int i = 0; i < file->service_count(); ++i) {
818*cc02d7e2SAndroid Build Coastguard Worker     auto service = file->service(i);
819*cc02d7e2SAndroid Build Coastguard Worker     std::string package_qualified_service_name = package + service->name();
820*cc02d7e2SAndroid Build Coastguard Worker     if (!(PrintBetaServicer(service.get(), out) &&
821*cc02d7e2SAndroid Build Coastguard Worker           PrintBetaStub(service.get(), out) &&
822*cc02d7e2SAndroid Build Coastguard Worker           PrintBetaServerFactory(package_qualified_service_name, service.get(),
823*cc02d7e2SAndroid Build Coastguard Worker                                  out) &&
824*cc02d7e2SAndroid Build Coastguard Worker           PrintBetaStubFactory(package_qualified_service_name, service.get(),
825*cc02d7e2SAndroid Build Coastguard Worker                                out))) {
826*cc02d7e2SAndroid Build Coastguard Worker       return false;
827*cc02d7e2SAndroid Build Coastguard Worker     }
828*cc02d7e2SAndroid Build Coastguard Worker   }
829*cc02d7e2SAndroid Build Coastguard Worker   return true;
830*cc02d7e2SAndroid Build Coastguard Worker }
831*cc02d7e2SAndroid Build Coastguard Worker 
GetGrpcServices()832*cc02d7e2SAndroid Build Coastguard Worker pair<bool, std::string> PrivateGenerator::GetGrpcServices() {
833*cc02d7e2SAndroid Build Coastguard Worker   std::string output;
834*cc02d7e2SAndroid Build Coastguard Worker   {
835*cc02d7e2SAndroid Build Coastguard Worker     // Scope the output stream so it closes and finalizes output to the string.
836*cc02d7e2SAndroid Build Coastguard Worker     auto out = file->CreatePrinter(&output);
837*cc02d7e2SAndroid Build Coastguard Worker     if (generate_in_pb2_grpc) {
838*cc02d7e2SAndroid Build Coastguard Worker       out->Print(
839*cc02d7e2SAndroid Build Coastguard Worker           "# Generated by the gRPC Python protocol compiler plugin. "
840*cc02d7e2SAndroid Build Coastguard Worker           "DO NOT EDIT!\n\"\"\""
841*cc02d7e2SAndroid Build Coastguard Worker           "Client and server classes corresponding to protobuf-defined "
842*cc02d7e2SAndroid Build Coastguard Worker           "services.\"\"\"\n");
843*cc02d7e2SAndroid Build Coastguard Worker       if (!PrintPreamble(out.get())) {
844*cc02d7e2SAndroid Build Coastguard Worker         return make_pair(false, "");
845*cc02d7e2SAndroid Build Coastguard Worker       }
846*cc02d7e2SAndroid Build Coastguard Worker       if (!PrintGAServices(out.get())) {
847*cc02d7e2SAndroid Build Coastguard Worker         return make_pair(false, "");
848*cc02d7e2SAndroid Build Coastguard Worker       }
849*cc02d7e2SAndroid Build Coastguard Worker     } else {
850*cc02d7e2SAndroid Build Coastguard Worker       out->Print("try:\n");
851*cc02d7e2SAndroid Build Coastguard Worker       {
852*cc02d7e2SAndroid Build Coastguard Worker         IndentScope raii_dict_try_indent(out.get());
853*cc02d7e2SAndroid Build Coastguard Worker         out->Print(
854*cc02d7e2SAndroid Build Coastguard Worker             "# THESE ELEMENTS WILL BE DEPRECATED.\n"
855*cc02d7e2SAndroid Build Coastguard Worker             "# Please use the generated *_pb2_grpc.py files instead.\n");
856*cc02d7e2SAndroid Build Coastguard Worker         if (!PrintPreamble(out.get())) {
857*cc02d7e2SAndroid Build Coastguard Worker           return make_pair(false, "");
858*cc02d7e2SAndroid Build Coastguard Worker         }
859*cc02d7e2SAndroid Build Coastguard Worker         if (!PrintBetaPreamble(out.get())) {
860*cc02d7e2SAndroid Build Coastguard Worker           return make_pair(false, "");
861*cc02d7e2SAndroid Build Coastguard Worker         }
862*cc02d7e2SAndroid Build Coastguard Worker         if (!PrintGAServices(out.get())) {
863*cc02d7e2SAndroid Build Coastguard Worker           return make_pair(false, "");
864*cc02d7e2SAndroid Build Coastguard Worker         }
865*cc02d7e2SAndroid Build Coastguard Worker         if (!PrintBetaServices(out.get())) {
866*cc02d7e2SAndroid Build Coastguard Worker           return make_pair(false, "");
867*cc02d7e2SAndroid Build Coastguard Worker         }
868*cc02d7e2SAndroid Build Coastguard Worker       }
869*cc02d7e2SAndroid Build Coastguard Worker       out->Print("except ImportError:\n");
870*cc02d7e2SAndroid Build Coastguard Worker       {
871*cc02d7e2SAndroid Build Coastguard Worker         IndentScope raii_dict_except_indent(out.get());
872*cc02d7e2SAndroid Build Coastguard Worker         out->Print("pass");
873*cc02d7e2SAndroid Build Coastguard Worker       }
874*cc02d7e2SAndroid Build Coastguard Worker     }
875*cc02d7e2SAndroid Build Coastguard Worker   }
876*cc02d7e2SAndroid Build Coastguard Worker   return make_pair(true, std::move(output));
877*cc02d7e2SAndroid Build Coastguard Worker }
878*cc02d7e2SAndroid Build Coastguard Worker 
879*cc02d7e2SAndroid Build Coastguard Worker }  // namespace
880*cc02d7e2SAndroid Build Coastguard Worker 
GeneratorConfiguration()881*cc02d7e2SAndroid Build Coastguard Worker GeneratorConfiguration::GeneratorConfiguration()
882*cc02d7e2SAndroid Build Coastguard Worker     : grpc_package_root("grpc"),
883*cc02d7e2SAndroid Build Coastguard Worker       beta_package_root("grpc.beta"),
884*cc02d7e2SAndroid Build Coastguard Worker       import_prefix(""),
885*cc02d7e2SAndroid Build Coastguard Worker       grpc_tools_version("") {}
886*cc02d7e2SAndroid Build Coastguard Worker 
GeneratorConfiguration(std::string version)887*cc02d7e2SAndroid Build Coastguard Worker GeneratorConfiguration::GeneratorConfiguration(std::string version)
888*cc02d7e2SAndroid Build Coastguard Worker     : grpc_package_root("grpc"),
889*cc02d7e2SAndroid Build Coastguard Worker       beta_package_root("grpc.beta"),
890*cc02d7e2SAndroid Build Coastguard Worker       import_prefix(""),
891*cc02d7e2SAndroid Build Coastguard Worker       grpc_tools_version(version) {}
892*cc02d7e2SAndroid Build Coastguard Worker 
PythonGrpcGenerator(const GeneratorConfiguration & config)893*cc02d7e2SAndroid Build Coastguard Worker PythonGrpcGenerator::PythonGrpcGenerator(const GeneratorConfiguration& config)
894*cc02d7e2SAndroid Build Coastguard Worker     : config_(config) {}
895*cc02d7e2SAndroid Build Coastguard Worker 
~PythonGrpcGenerator()896*cc02d7e2SAndroid Build Coastguard Worker PythonGrpcGenerator::~PythonGrpcGenerator() {}
897*cc02d7e2SAndroid Build Coastguard Worker 
GenerateGrpc(GeneratorContext * context,PrivateGenerator & generator,std::string file_name,bool generate_in_pb2_grpc)898*cc02d7e2SAndroid Build Coastguard Worker static bool GenerateGrpc(GeneratorContext* context, PrivateGenerator& generator,
899*cc02d7e2SAndroid Build Coastguard Worker                          std::string file_name, bool generate_in_pb2_grpc) {
900*cc02d7e2SAndroid Build Coastguard Worker   bool success;
901*cc02d7e2SAndroid Build Coastguard Worker   std::unique_ptr<ZeroCopyOutputStream> output;
902*cc02d7e2SAndroid Build Coastguard Worker   std::unique_ptr<CodedOutputStream> coded_output;
903*cc02d7e2SAndroid Build Coastguard Worker   std::string grpc_code;
904*cc02d7e2SAndroid Build Coastguard Worker 
905*cc02d7e2SAndroid Build Coastguard Worker   if (generate_in_pb2_grpc) {
906*cc02d7e2SAndroid Build Coastguard Worker     output.reset(context->Open(file_name));
907*cc02d7e2SAndroid Build Coastguard Worker     generator.generate_in_pb2_grpc = true;
908*cc02d7e2SAndroid Build Coastguard Worker   } else {
909*cc02d7e2SAndroid Build Coastguard Worker     output.reset(context->OpenForInsert(file_name, "module_scope"));
910*cc02d7e2SAndroid Build Coastguard Worker     generator.generate_in_pb2_grpc = false;
911*cc02d7e2SAndroid Build Coastguard Worker   }
912*cc02d7e2SAndroid Build Coastguard Worker 
913*cc02d7e2SAndroid Build Coastguard Worker   coded_output.reset(new CodedOutputStream(output.get()));
914*cc02d7e2SAndroid Build Coastguard Worker   tie(success, grpc_code) = generator.GetGrpcServices();
915*cc02d7e2SAndroid Build Coastguard Worker 
916*cc02d7e2SAndroid Build Coastguard Worker   if (success) {
917*cc02d7e2SAndroid Build Coastguard Worker     coded_output->WriteRaw(grpc_code.data(), grpc_code.size());
918*cc02d7e2SAndroid Build Coastguard Worker     return true;
919*cc02d7e2SAndroid Build Coastguard Worker   } else {
920*cc02d7e2SAndroid Build Coastguard Worker     return false;
921*cc02d7e2SAndroid Build Coastguard Worker   }
922*cc02d7e2SAndroid Build Coastguard Worker }
923*cc02d7e2SAndroid Build Coastguard Worker 
ParseParameters(const std::string & parameter,std::string * grpc_version,std::vector<std::string> * strip_prefixes,std::string * error)924*cc02d7e2SAndroid Build Coastguard Worker static bool ParseParameters(const std::string& parameter,
925*cc02d7e2SAndroid Build Coastguard Worker                             std::string* grpc_version,
926*cc02d7e2SAndroid Build Coastguard Worker                             std::vector<std::string>* strip_prefixes,
927*cc02d7e2SAndroid Build Coastguard Worker                             std::string* error) {
928*cc02d7e2SAndroid Build Coastguard Worker   std::vector<std::string> comma_delimited_parameters;
929*cc02d7e2SAndroid Build Coastguard Worker   grpc_python_generator::Split(parameter, ',', &comma_delimited_parameters);
930*cc02d7e2SAndroid Build Coastguard Worker   if (comma_delimited_parameters.size() == 1 &&
931*cc02d7e2SAndroid Build Coastguard Worker       comma_delimited_parameters[0].empty()) {
932*cc02d7e2SAndroid Build Coastguard Worker     *grpc_version = "grpc_2_0";
933*cc02d7e2SAndroid Build Coastguard Worker   } else if (comma_delimited_parameters.size() == 1) {
934*cc02d7e2SAndroid Build Coastguard Worker     *grpc_version = comma_delimited_parameters[0];
935*cc02d7e2SAndroid Build Coastguard Worker   } else if (comma_delimited_parameters.size() == 2) {
936*cc02d7e2SAndroid Build Coastguard Worker     *grpc_version = comma_delimited_parameters[0];
937*cc02d7e2SAndroid Build Coastguard Worker     std::copy(comma_delimited_parameters.begin() + 1,
938*cc02d7e2SAndroid Build Coastguard Worker               comma_delimited_parameters.end(),
939*cc02d7e2SAndroid Build Coastguard Worker               std::back_inserter(*strip_prefixes));
940*cc02d7e2SAndroid Build Coastguard Worker   } else {
941*cc02d7e2SAndroid Build Coastguard Worker     *error = "--grpc_python_out received too many comma-delimited parameters.";
942*cc02d7e2SAndroid Build Coastguard Worker     return false;
943*cc02d7e2SAndroid Build Coastguard Worker   }
944*cc02d7e2SAndroid Build Coastguard Worker   return true;
945*cc02d7e2SAndroid Build Coastguard Worker }
946*cc02d7e2SAndroid Build Coastguard Worker 
Generate(const FileDescriptor * file,const std::string & parameter,GeneratorContext * context,std::string * error) const947*cc02d7e2SAndroid Build Coastguard Worker bool PythonGrpcGenerator::Generate(const FileDescriptor* file,
948*cc02d7e2SAndroid Build Coastguard Worker                                    const std::string& parameter,
949*cc02d7e2SAndroid Build Coastguard Worker                                    GeneratorContext* context,
950*cc02d7e2SAndroid Build Coastguard Worker                                    std::string* error) const {
951*cc02d7e2SAndroid Build Coastguard Worker   // Get output file name.
952*cc02d7e2SAndroid Build Coastguard Worker   std::string pb2_file_name;
953*cc02d7e2SAndroid Build Coastguard Worker   std::string pb2_grpc_file_name;
954*cc02d7e2SAndroid Build Coastguard Worker   static const int proto_suffix_length = strlen(".proto");
955*cc02d7e2SAndroid Build Coastguard Worker   if (file->name().size() > static_cast<size_t>(proto_suffix_length) &&
956*cc02d7e2SAndroid Build Coastguard Worker       file->name().find_last_of(".proto") == file->name().size() - 1) {
957*cc02d7e2SAndroid Build Coastguard Worker     std::string base =
958*cc02d7e2SAndroid Build Coastguard Worker         file->name().substr(0, file->name().size() - proto_suffix_length);
959*cc02d7e2SAndroid Build Coastguard Worker     std::replace(base.begin(), base.end(), '-', '_');
960*cc02d7e2SAndroid Build Coastguard Worker     pb2_file_name = base + "_pb2.py";
961*cc02d7e2SAndroid Build Coastguard Worker     pb2_grpc_file_name = base + "_pb2_grpc.py";
962*cc02d7e2SAndroid Build Coastguard Worker   } else {
963*cc02d7e2SAndroid Build Coastguard Worker     *error = "Invalid proto file name. Proto file must end with .proto";
964*cc02d7e2SAndroid Build Coastguard Worker     return false;
965*cc02d7e2SAndroid Build Coastguard Worker   }
966*cc02d7e2SAndroid Build Coastguard Worker   generator_file_name = file->name();
967*cc02d7e2SAndroid Build Coastguard Worker 
968*cc02d7e2SAndroid Build Coastguard Worker   ProtoBufFile pbfile(file);
969*cc02d7e2SAndroid Build Coastguard Worker   std::string grpc_version;
970*cc02d7e2SAndroid Build Coastguard Worker   GeneratorConfiguration extended_config(config_);
971*cc02d7e2SAndroid Build Coastguard Worker   bool success = ParseParameters(parameter, &grpc_version,
972*cc02d7e2SAndroid Build Coastguard Worker                                  &(extended_config.prefixes_to_filter), error);
973*cc02d7e2SAndroid Build Coastguard Worker   PrivateGenerator generator(extended_config, &pbfile);
974*cc02d7e2SAndroid Build Coastguard Worker   if (!success) return false;
975*cc02d7e2SAndroid Build Coastguard Worker   if (grpc_version == "grpc_2_0") {
976*cc02d7e2SAndroid Build Coastguard Worker     return GenerateGrpc(context, generator, pb2_grpc_file_name, true);
977*cc02d7e2SAndroid Build Coastguard Worker   } else if (grpc_version == "grpc_1_0") {
978*cc02d7e2SAndroid Build Coastguard Worker     return GenerateGrpc(context, generator, pb2_grpc_file_name, true) &&
979*cc02d7e2SAndroid Build Coastguard Worker            GenerateGrpc(context, generator, pb2_file_name, false);
980*cc02d7e2SAndroid Build Coastguard Worker   } else {
981*cc02d7e2SAndroid Build Coastguard Worker     *error = "Invalid grpc version '" + grpc_version + "'.";
982*cc02d7e2SAndroid Build Coastguard Worker     return false;
983*cc02d7e2SAndroid Build Coastguard Worker   }
984*cc02d7e2SAndroid Build Coastguard Worker }
985*cc02d7e2SAndroid Build Coastguard Worker 
986*cc02d7e2SAndroid Build Coastguard Worker }  // namespace grpc_python_generator
987