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 <algorithm>
20 #include <cassert>
21 #include <cctype>
22 #include <cstring>
23 #include <fstream>
24 #include <iostream>
25 #include <map>
26 #include <memory>
27 #include <ostream>
28 #include <set>
29 #include <sstream>
30 #include <tuple>
31 #include <vector>
32 
33 #include "flatbuffers/util.h"
34 #include "src/compiler/python_generator.h"
35 #include "src/compiler/python_private_generator.h"
36 
37 using std::make_pair;
38 using std::map;
39 using std::pair;
40 using std::replace;
41 using std::tuple;
42 using std::vector;
43 using std::set;
44 
45 namespace grpc_python_generator {
46 
47 grpc::string generator_file_name;
48 
49 typedef map<grpc::string, grpc::string> StringMap;
50 typedef vector<grpc::string> StringVector;
51 typedef tuple<grpc::string, grpc::string> StringPair;
52 typedef set<StringPair> StringPairSet;
53 
54 // Provides RAII indentation handling. Use as:
55 // {
56 //   IndentScope raii_my_indent_var_name_here(my_py_printer);
57 //   // constructor indented my_py_printer
58 //   ...
59 //   // destructor called at end of scope, un-indenting my_py_printer
60 // }
61 class IndentScope {
62  public:
IndentScope(grpc_generator::Printer * printer)63   explicit IndentScope(grpc_generator::Printer* printer) : printer_(printer) {
64     printer_->Indent();
65   }
66 
~IndentScope()67   ~IndentScope() { printer_->Outdent(); }
68 
69  private:
70   grpc_generator::Printer* printer_;
71 };
72 
StringReplace(grpc::string str,const grpc::string & from,const grpc::string & to,bool replace_all)73 inline grpc::string StringReplace(grpc::string str, const grpc::string& from,
74                                   const grpc::string& to, bool replace_all) {
75   size_t pos = 0;
76 
77   do {
78     pos = str.find(from, pos);
79     if (pos == grpc::string::npos) {
80       break;
81     }
82     str.replace(pos, from.length(), to);
83     pos += to.length();
84   } while (replace_all);
85 
86   return str;
87 }
88 
StringReplace(grpc::string str,const grpc::string & from,const grpc::string & to)89 inline grpc::string StringReplace(grpc::string str, const grpc::string& from,
90                                   const grpc::string& to) {
91   return StringReplace(str, from, to, true);
92 }
93 
ModuleName(const grpc::string & filename,const grpc::string & import_prefix)94 grpc::string ModuleName(const grpc::string& filename,
95                         const grpc::string& import_prefix) {
96   grpc::string basename = flatbuffers::StripExtension(filename);
97   basename = StringReplace(basename, "-", "_");
98   basename = StringReplace(basename, "/", ".");
99   return import_prefix + basename + "_fb";
100 }
101 
ModuleAlias(const grpc::string & filename,const grpc::string & import_prefix)102 grpc::string ModuleAlias(const grpc::string& filename,
103                          const grpc::string& import_prefix) {
104   grpc::string module_name = ModuleName(filename, import_prefix);
105   // We can't have dots in the module name, so we replace each with _dot_.
106   // But that could lead to a collision between a.b and a_dot_b, so we also
107   // duplicate each underscore.
108   module_name = StringReplace(module_name, "_", "__");
109   module_name = StringReplace(module_name, ".", "_dot_");
110   return module_name;
111 }
112 
PrivateGenerator(const GeneratorConfiguration & config_,const grpc_generator::File * file_)113 PrivateGenerator::PrivateGenerator(const GeneratorConfiguration& config_,
114                                    const grpc_generator::File* file_)
115     : config(config_), file(file_) {}
116 
PrintBetaServicer(const grpc_generator::Service * service,grpc_generator::Printer * out)117 void PrivateGenerator::PrintBetaServicer(const grpc_generator::Service* service,
118                                          grpc_generator::Printer* out) {
119   StringMap service_dict;
120   service_dict["Service"] = service->name();
121   out->Print("\n\n");
122   out->Print(service_dict, "class Beta$Service$Servicer(object):\n");
123   {
124     IndentScope raii_class_indent(out);
125     out->Print(
126         "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
127         "\nIt is recommended to use the GA API (classes and functions in this\n"
128         "file not marked beta) for all further purposes. This class was "
129         "generated\n"
130         "only to ease transition from grpcio<0.15.0 to "
131         "grpcio>=0.15.0.\"\"\"\n");
132     for (int i = 0; i < service->method_count(); ++i) {
133       auto method = service->method(i);
134       grpc::string arg_name =
135           method->ClientStreaming() ? "request_iterator" : "request";
136       StringMap method_dict;
137       method_dict["Method"] = method->name();
138       method_dict["ArgName"] = arg_name;
139       out->Print(method_dict, "def $Method$(self, $ArgName$, context):\n");
140       {
141         IndentScope raii_method_indent(out);
142         out->Print("context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)\n");
143       }
144     }
145   }
146 }
147 
PrintBetaStub(const grpc_generator::Service * service,grpc_generator::Printer * out)148 void PrivateGenerator::PrintBetaStub(const grpc_generator::Service* service,
149                                      grpc_generator::Printer* out) {
150   StringMap service_dict;
151   service_dict["Service"] = service->name();
152   out->Print("\n\n");
153   out->Print(service_dict, "class Beta$Service$Stub(object):\n");
154   {
155     IndentScope raii_class_indent(out);
156     out->Print(
157         "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
158         "\nIt is recommended to use the GA API (classes and functions in this\n"
159         "file not marked beta) for all further purposes. This class was "
160         "generated\n"
161         "only to ease transition from grpcio<0.15.0 to "
162         "grpcio>=0.15.0.\"\"\"\n");
163     for (int i = 0; i < service->method_count(); ++i) {
164       auto method = service->method(i);
165       grpc::string arg_name =
166           method->ClientStreaming() ? "request_iterator" : "request";
167       StringMap method_dict;
168       method_dict["Method"] = method->name();
169       method_dict["ArgName"] = arg_name;
170       out->Print(method_dict,
171                  "def $Method$(self, $ArgName$, timeout, metadata=None, "
172                  "with_call=False, protocol_options=None):\n");
173       {
174         IndentScope raii_method_indent(out);
175         out->Print("raise NotImplementedError()\n");
176       }
177       if (!method->ServerStreaming()) {
178         out->Print(method_dict, "$Method$.future = None\n");
179       }
180     }
181   }
182 }
183 
PrintBetaServerFactory(const grpc::string & package_qualified_service_name,const grpc_generator::Service * service,grpc_generator::Printer * out)184 void PrivateGenerator::PrintBetaServerFactory(
185     const grpc::string& package_qualified_service_name,
186     const grpc_generator::Service* service, grpc_generator::Printer* out) {
187   StringMap service_dict;
188   service_dict["Service"] = service->name();
189   out->Print("\n\n");
190   out->Print(service_dict,
191              "def beta_create_$Service$_server(servicer, pool=None, "
192              "pool_size=None, default_timeout=None, maximum_timeout=None):\n");
193   {
194     IndentScope raii_create_server_indent(out);
195     out->Print(
196         "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
197         "\nIt is recommended to use the GA API (classes and functions in this\n"
198         "file not marked beta) for all further purposes. This function was\n"
199         "generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"
200         "\"\"\"\n");
201     StringMap method_implementation_constructors;
202     StringMap input_message_modules_and_classes;
203     StringMap output_message_modules_and_classes;
204     for (int i = 0; i < service->method_count(); ++i) {
205       auto method = service->method(i);
206       const grpc::string method_implementation_constructor =
207           grpc::string(method->ClientStreaming() ? "stream_" : "unary_") +
208           grpc::string(method->ServerStreaming() ? "stream_" : "unary_") +
209           "inline";
210       grpc::string input_message_module_and_class = method->get_fb_builder();
211       grpc::string output_message_module_and_class = method->get_fb_builder();
212       method_implementation_constructors.insert(
213           make_pair(method->name(), method_implementation_constructor));
214       input_message_modules_and_classes.insert(
215           make_pair(method->name(), input_message_module_and_class));
216       output_message_modules_and_classes.insert(
217           make_pair(method->name(), output_message_module_and_class));
218     }
219     StringMap method_dict;
220     method_dict["PackageQualifiedServiceName"] = package_qualified_service_name;
221 //    out->Print("request_deserializers = {\n");
222 //    for (StringMap::iterator name_and_input_module_class_pair =
223 //             input_message_modules_and_classes.begin();
224 //         name_and_input_module_class_pair !=
225 //         input_message_modules_and_classes.end();
226 //         name_and_input_module_class_pair++) {
227 //      method_dict["MethodName"] = name_and_input_module_class_pair->first;
228 //      method_dict["InputTypeModuleAndClass"] =
229 //          name_and_input_module_class_pair->second;
230 //      IndentScope raii_indent(out);
231 //      out->Print(method_dict,
232 //                 "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
233 //                 "$InputTypeModuleAndClass$.FromString,\n");
234 //    }
235 //    out->Print("}\n");
236 //    out->Print("response_serializers = {\n");
237 //    for (StringMap::iterator name_and_output_module_class_pair =
238 //             output_message_modules_and_classes.begin();
239 //         name_and_output_module_class_pair !=
240 //         output_message_modules_and_classes.end();
241 //         name_and_output_module_class_pair++) {
242 //      method_dict["MethodName"] = name_and_output_module_class_pair->first;
243 //      method_dict["OutputTypeModuleAndClass"] =
244 //          name_and_output_module_class_pair->second;
245 //      IndentScope raii_indent(out);
246 //      out->Print(method_dict,
247 //                 "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
248 //                 "$OutputTypeModuleAndClass$.SerializeToString,\n");
249 //    }
250 //    out->Print("}\n");
251     out->Print("method_implementations = {\n");
252     for (StringMap::iterator name_and_implementation_constructor =
253              method_implementation_constructors.begin();
254          name_and_implementation_constructor !=
255          method_implementation_constructors.end();
256          name_and_implementation_constructor++) {
257       method_dict["Method"] = name_and_implementation_constructor->first;
258       method_dict["Constructor"] = name_and_implementation_constructor->second;
259       IndentScope raii_descriptions_indent(out);
260       const grpc::string method_name =
261           name_and_implementation_constructor->first;
262       out->Print(method_dict,
263                  "(\'$PackageQualifiedServiceName$\', \'$Method$\'): "
264                  "face_utilities.$Constructor$(servicer.$Method$),\n");
265     }
266     out->Print("}\n");
267     out->Print(
268         "server_options = beta_implementations.server_options("
269         "thread_pool=pool, thread_pool_size=pool_size, "
270         "default_timeout=default_timeout, "
271         "maximum_timeout=maximum_timeout)\n");
272     out->Print(
273         "return beta_implementations.server(method_implementations, "
274         "options=server_options)\n");
275         //"request_deserializers=request_deserializers, "
276         //"response_serializers=response_serializers, "
277   }
278 }
279 
PrintBetaStubFactory(const grpc::string & package_qualified_service_name,const grpc_generator::Service * service,grpc_generator::Printer * out)280 void PrivateGenerator::PrintBetaStubFactory(
281     const grpc::string& package_qualified_service_name,
282     const grpc_generator::Service* service, grpc_generator::Printer* out) {
283   StringMap dict;
284   dict["Service"] = service->name();
285   out->Print("\n\n");
286   out->Print(dict,
287              "def beta_create_$Service$_stub(channel, host=None,"
288              " metadata_transformer=None, pool=None, pool_size=None):\n");
289   {
290     IndentScope raii_create_server_indent(out);
291     out->Print(
292         "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
293         "\nIt is recommended to use the GA API (classes and functions in this\n"
294         "file not marked beta) for all further purposes. This function was\n"
295         "generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"
296         "\"\"\"\n");
297     StringMap method_cardinalities;
298     StringMap input_message_modules_and_classes;
299     StringMap output_message_modules_and_classes;
300     for (int i = 0; i < service->method_count(); ++i) {
301       auto method = service->method(i);
302       const grpc::string method_cardinality =
303           grpc::string(method->ClientStreaming() ? "STREAM" : "UNARY") +
304           "_" +
305           grpc::string(method->ServerStreaming() ? "STREAM" : "UNARY");
306       grpc::string input_message_module_and_class = method->get_fb_builder();
307       grpc::string output_message_module_and_class = method->get_fb_builder();
308       method_cardinalities.insert(
309           make_pair(method->name(), method_cardinality));
310       input_message_modules_and_classes.insert(
311           make_pair(method->name(), input_message_module_and_class));
312       output_message_modules_and_classes.insert(
313           make_pair(method->name(), output_message_module_and_class));
314     }
315     StringMap method_dict;
316     method_dict["PackageQualifiedServiceName"] = package_qualified_service_name;
317 //    out->Print("request_serializers = {\n");
318 //    for (StringMap::iterator name_and_input_module_class_pair =
319 //             input_message_modules_and_classes.begin();
320 //         name_and_input_module_class_pair !=
321 //         input_message_modules_and_classes.end();
322 //         name_and_input_module_class_pair++) {
323 //      method_dict["MethodName"] = name_and_input_module_class_pair->first;
324 //      method_dict["InputTypeModuleAndClass"] =
325 //          name_and_input_module_class_pair->second;
326 //      IndentScope raii_indent(out);
327 //      out->Print(method_dict,
328 //                 "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
329 //                 "$InputTypeModuleAndClass$.SerializeToString,\n");
330 //    }
331 //    out->Print("}\n");
332 //    out->Print("response_deserializers = {\n");
333 //    for (StringMap::iterator name_and_output_module_class_pair =
334 //             output_message_modules_and_classes.begin();
335 //         name_and_output_module_class_pair !=
336 //         output_message_modules_and_classes.end();
337 //         name_and_output_module_class_pair++) {
338 //      method_dict["MethodName"] = name_and_output_module_class_pair->first;
339 //      method_dict["OutputTypeModuleAndClass"] =
340 //          name_and_output_module_class_pair->second;
341 //      IndentScope raii_indent(out);
342 //      out->Print(method_dict,
343 //                 "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
344 //                 "$OutputTypeModuleAndClass$.FromString,\n");
345 //    }
346 //    out->Print("}\n");
347     out->Print("cardinalities = {\n");
348     for (StringMap::iterator name_and_cardinality =
349              method_cardinalities.begin();
350          name_and_cardinality != method_cardinalities.end();
351          name_and_cardinality++) {
352       method_dict["Method"] = name_and_cardinality->first;
353       method_dict["Cardinality"] = name_and_cardinality->second;
354       IndentScope raii_descriptions_indent(out);
355       out->Print(method_dict,
356                  "\'$Method$\': cardinality.Cardinality.$Cardinality$,\n");
357     }
358     out->Print("}\n");
359     out->Print(
360         "stub_options = beta_implementations.stub_options("
361         "host=host, metadata_transformer=metadata_transformer, "
362         "thread_pool=pool, thread_pool_size=pool_size)\n");
363     out->Print(method_dict,
364                "return beta_implementations.dynamic_stub(channel, "
365                "\'$PackageQualifiedServiceName$\', "
366                "cardinalities, options=stub_options)\n");
367         // "request_serializers=request_serializers, "
368         //"response_deserializers=response_deserializers, "
369   }
370 }
371 
PrintStub(const grpc::string & package_qualified_service_name,const grpc_generator::Service * service,grpc_generator::Printer * out)372 void PrivateGenerator::PrintStub(
373     const grpc::string& package_qualified_service_name,
374     const grpc_generator::Service* service, grpc_generator::Printer* out) {
375   StringMap dict;
376   dict["Service"] = service->name();
377   out->Print("\n\n");
378   out->Print(dict, "class $Service$Stub(object):\n");
379   {
380     IndentScope raii_class_indent(out);
381     out->Print("\n");
382     out->Print("def __init__(self, channel):\n");
383     {
384       IndentScope raii_init_indent(out);
385       out->Print("\"\"\"Constructor.\n");
386       out->Print("\n");
387       out->Print("Args:\n");
388       {
389         IndentScope raii_args_indent(out);
390         out->Print("channel: A grpc.Channel.\n");
391       }
392       out->Print("\"\"\"\n");
393       for (int i = 0; i < service->method_count(); ++i) {
394         auto method = service->method(i);
395         grpc::string multi_callable_constructor =
396             grpc::string(method->ClientStreaming() ? "stream" : "unary") +
397             "_" +
398             grpc::string(method->ServerStreaming() ? "stream" : "unary");
399         grpc::string request_module_and_class = method->get_fb_builder();
400         grpc::string response_module_and_class = method->get_fb_builder();
401         StringMap method_dict;
402         method_dict["Method"] = method->name();
403         method_dict["MultiCallableConstructor"] = multi_callable_constructor;
404         out->Print(method_dict,
405                    "self.$Method$ = channel.$MultiCallableConstructor$(\n");
406         {
407           method_dict["PackageQualifiedService"] =
408               package_qualified_service_name;
409           method_dict["RequestModuleAndClass"] = request_module_and_class;
410           method_dict["ResponseModuleAndClass"] = response_module_and_class;
411           IndentScope raii_first_attribute_indent(out);
412           IndentScope raii_second_attribute_indent(out);
413           out->Print(method_dict, "'/$PackageQualifiedService$/$Method$',\n");
414           out->Print(method_dict,"\n");
415           out->Print(
416               method_dict,"\n");
417           out->Print(")\n");
418         }
419       }
420     }
421   }
422 }
423 
PrintServicer(const grpc_generator::Service * service,grpc_generator::Printer * out)424 void PrivateGenerator::PrintServicer(const grpc_generator::Service* service,
425                                      grpc_generator::Printer* out) {
426   StringMap service_dict;
427   service_dict["Service"] = service->name();
428   out->Print("\n\n");
429   out->Print(service_dict, "class $Service$Servicer(object):\n");
430   {
431     IndentScope raii_class_indent(out);
432     for (int i = 0; i < service->method_count(); ++i) {
433       auto method = service->method(i);
434       grpc::string arg_name =
435           method->ClientStreaming() ? "request_iterator" : "request";
436       StringMap method_dict;
437       method_dict["Method"] = method->name();
438       method_dict["ArgName"] = arg_name;
439       out->Print("\n");
440       out->Print(method_dict, "def $Method$(self, $ArgName$, context):\n");
441       {
442         IndentScope raii_method_indent(out);
443         out->Print("context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n");
444         out->Print("context.set_details('Method not implemented!')\n");
445         out->Print("raise NotImplementedError('Method not implemented!')\n");
446       }
447     }
448   }
449 }
450 
PrintAddServicerToServer(const grpc::string & package_qualified_service_name,const grpc_generator::Service * service,grpc_generator::Printer * out)451 void PrivateGenerator::PrintAddServicerToServer(
452     const grpc::string& package_qualified_service_name,
453     const grpc_generator::Service* service, grpc_generator::Printer* out) {
454   StringMap service_dict;
455   service_dict["Service"] = service->name();
456   out->Print("\n\n");
457   out->Print(service_dict,
458              "def add_$Service$Servicer_to_server(servicer, server):\n");
459   {
460     IndentScope raii_class_indent(out);
461     out->Print("rpc_method_handlers = {\n");
462     {
463       IndentScope raii_dict_first_indent(out);
464       IndentScope raii_dict_second_indent(out);
465       for (int i = 0; i < service->method_count(); ++i) {
466         auto method = service->method(i);
467         grpc::string method_handler_constructor =
468             grpc::string(method->ClientStreaming() ? "stream" : "unary") +
469             "_" +
470             grpc::string(method->ServerStreaming() ? "stream" : "unary") +
471             "_rpc_method_handler";
472         grpc::string request_module_and_class = method->get_fb_builder();
473         grpc::string response_module_and_class = method->get_fb_builder();
474         StringMap method_dict;
475         method_dict["Method"] = method->name();
476         method_dict["MethodHandlerConstructor"] = method_handler_constructor;
477         method_dict["RequestModuleAndClass"] = request_module_and_class;
478         method_dict["ResponseModuleAndClass"] = response_module_and_class;
479         out->Print(method_dict,
480                    "'$Method$': grpc.$MethodHandlerConstructor$(\n");
481         {
482           IndentScope raii_call_first_indent(out);
483           IndentScope raii_call_second_indent(out);
484           out->Print(method_dict, "servicer.$Method$,\n");
485           out->Print(
486               method_dict,"\n");
487           out->Print(
488               method_dict,
489               "\n");
490         }
491         out->Print("),\n");
492       }
493     }
494     StringMap method_dict;
495     method_dict["PackageQualifiedServiceName"] = package_qualified_service_name;
496     out->Print("}\n");
497     out->Print("generic_handler = grpc.method_handlers_generic_handler(\n");
498     {
499       IndentScope raii_call_first_indent(out);
500       IndentScope raii_call_second_indent(out);
501       out->Print(method_dict,
502                  "'$PackageQualifiedServiceName$', rpc_method_handlers)\n");
503     }
504     out->Print("server.add_generic_rpc_handlers((generic_handler,))\n");
505   }
506 }
507 
PrintBetaPreamble(grpc_generator::Printer * out)508 void PrivateGenerator::PrintBetaPreamble(grpc_generator::Printer* out) {
509   StringMap var;
510   var["Package"] = config.beta_package_root;
511   out->Print(var,
512              "from $Package$ import implementations as beta_implementations\n");
513   out->Print(var, "from $Package$ import interfaces as beta_interfaces\n");
514   out->Print("from grpc.framework.common import cardinality\n");
515   out->Print(
516       "from grpc.framework.interfaces.face import utilities as "
517       "face_utilities\n");
518 }
519 
PrintPreamble(grpc_generator::Printer * out)520 void PrivateGenerator::PrintPreamble(grpc_generator::Printer* out) {
521   StringMap var;
522   var["Package"] = config.grpc_package_root;
523   out->Print(var, "import $Package$\n");
524   out->Print("\n");
525   StringPairSet imports_set;
526   for (int i = 0; i < file->service_count(); ++i) {
527     auto service = file->service(i);
528     for (int j = 0; j < service->method_count(); ++j) {
529       auto method = service.get()->method(j);
530 
531       grpc::string input_type_file_name = method->get_fb_builder();
532       grpc::string input_module_name =
533           ModuleName(input_type_file_name, config.import_prefix);
534       grpc::string input_module_alias =
535           ModuleAlias(input_type_file_name, config.import_prefix);
536       imports_set.insert(
537           std::make_tuple(input_module_name, input_module_alias));
538 
539       grpc::string output_type_file_name = method->get_fb_builder();
540       grpc::string output_module_name =
541           ModuleName(output_type_file_name, config.import_prefix);
542       grpc::string output_module_alias =
543           ModuleAlias(output_type_file_name, config.import_prefix);
544       imports_set.insert(
545           std::make_tuple(output_module_name, output_module_alias));
546     }
547   }
548 
549   for (StringPairSet::iterator it = imports_set.begin();
550        it != imports_set.end(); ++it) {
551     var["ModuleName"] = std::get<0>(*it);
552     var["ModuleAlias"] = std::get<1>(*it);
553     out->Print(var, "import $ModuleName$ as $ModuleAlias$\n");
554   }
555 }
556 
PrintGAServices(grpc_generator::Printer * out)557 void PrivateGenerator::PrintGAServices(grpc_generator::Printer* out) {
558   grpc::string package = file->package();
559   if (!package.empty()) {
560     package = package.append(".");
561   }
562 
563   out->Print(file->additional_headers().c_str());
564 
565   for (int i = 0; i < file->service_count(); ++i) {
566     auto service = file->service(i);
567 
568     grpc::string package_qualified_service_name = package + service->name();
569     PrintStub(package_qualified_service_name, service.get(), out);
570     PrintServicer(service.get(), out);
571     PrintAddServicerToServer(package_qualified_service_name, service.get(),
572                              out);
573   }
574 }
575 
PrintBetaServices(grpc_generator::Printer * out)576 void PrivateGenerator::PrintBetaServices(grpc_generator::Printer* out) {
577   grpc::string package = file->package();
578   if (!package.empty()) {
579     package = package.append(".");
580   }
581   for (int i = 0; i < file->service_count(); ++i) {
582     auto service = file->service(i);
583 
584     grpc::string package_qualified_service_name = package + service->name();
585     PrintBetaServicer(service.get(), out);
586     PrintBetaStub(service.get(), out);
587     PrintBetaServerFactory(package_qualified_service_name, service.get(), out);
588     PrintBetaStubFactory(package_qualified_service_name, service.get(), out);
589   }
590 }
591 
GetGrpcServices()592 grpc::string PrivateGenerator::GetGrpcServices() {
593   grpc::string output;
594   {
595     // Scope the output stream so it closes and finalizes output to the string.
596     auto out = file->CreatePrinter(&output);
597     out->Print(
598         "# Generated by the gRPC Python protocol compiler plugin. "
599         "DO NOT EDIT!\n");
600     StringMap var;
601     var["Package"] = config.grpc_package_root;
602     out->Print(var, "import $Package$\n");
603     PrintGAServices(out.get());
604     out->Print("try:\n");
605     {
606       IndentScope raii_dict_try_indent(out.get());
607       out->Print(
608           "# THESE ELEMENTS WILL BE DEPRECATED.\n"
609           "# Please use the generated *_pb2_grpc.py files instead.\n");
610       out->Print(var, "import $Package$\n");
611       PrintBetaPreamble(out.get());
612       PrintGAServices(out.get());
613       PrintBetaServices(out.get());
614     }
615     out->Print("except ImportError:\n");
616     {
617       IndentScope raii_dict_except_indent(out.get());
618       out->Print("pass");
619     }
620   }
621   return output;
622 }
623 
624 }  // namespace grpc_python_generator
625