Line data Source code
1 : /*
2 : *
3 : * Copyright 2015, Google Inc.
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions are
8 : * met:
9 : *
10 : * * Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * * Redistributions in binary form must reproduce the above
13 : * copyright notice, this list of conditions and the following disclaimer
14 : * in the documentation and/or other materials provided with the
15 : * distribution.
16 : * * Neither the name of Google Inc. nor the names of its
17 : * contributors may be used to endorse or promote products derived from
18 : * this software without specific prior written permission.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 : * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 : * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 : * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 : *
32 : */
33 :
34 : #include <algorithm>
35 : #include <cassert>
36 : #include <cctype>
37 : #include <cstring>
38 : #include <map>
39 : #include <memory>
40 : #include <ostream>
41 : #include <sstream>
42 : #include <tuple>
43 : #include <vector>
44 :
45 : #include <grpc++/support/config.h>
46 : #include "src/compiler/config.h"
47 : #include "src/compiler/generator_helpers.h"
48 : #include "src/compiler/python_generator.h"
49 :
50 : using grpc_generator::StringReplace;
51 : using grpc_generator::StripProto;
52 : using grpc::protobuf::Descriptor;
53 : using grpc::protobuf::FileDescriptor;
54 : using grpc::protobuf::MethodDescriptor;
55 : using grpc::protobuf::ServiceDescriptor;
56 : using grpc::protobuf::compiler::GeneratorContext;
57 : using grpc::protobuf::io::CodedOutputStream;
58 : using grpc::protobuf::io::Printer;
59 : using grpc::protobuf::io::StringOutputStream;
60 : using grpc::protobuf::io::ZeroCopyOutputStream;
61 : using std::initializer_list;
62 : using std::make_pair;
63 : using std::map;
64 : using std::pair;
65 : using std::replace;
66 : using std::vector;
67 :
68 : namespace grpc_python_generator {
69 :
70 23 : PythonGrpcGenerator::PythonGrpcGenerator(const GeneratorConfiguration& config)
71 23 : : config_(config) {}
72 :
73 23 : PythonGrpcGenerator::~PythonGrpcGenerator() {}
74 :
75 27 : bool PythonGrpcGenerator::Generate(
76 : const FileDescriptor* file, const grpc::string& parameter,
77 : GeneratorContext* context, grpc::string* error) const {
78 : // Get output file name.
79 27 : grpc::string file_name;
80 : static const int proto_suffix_length = strlen(".proto");
81 54 : if (file->name().size() > static_cast<size_t>(proto_suffix_length) &&
82 27 : file->name().find_last_of(".proto") == file->name().size() - 1) {
83 27 : file_name = file->name().substr(
84 54 : 0, file->name().size() - proto_suffix_length) + "_pb2.py";
85 : } else {
86 0 : *error = "Invalid proto file name. Proto file must end with .proto";
87 0 : return false;
88 : }
89 :
90 : std::unique_ptr<ZeroCopyOutputStream> output(
91 54 : context->OpenForInsert(file_name, "module_scope"));
92 54 : CodedOutputStream coded_out(output.get());
93 27 : bool success = false;
94 54 : grpc::string code = "";
95 27 : tie(success, code) = grpc_python_generator::GetServices(file, config_);
96 27 : if (success) {
97 27 : coded_out.WriteRaw(code.data(), code.size());
98 27 : return true;
99 : } else {
100 0 : return false;
101 27 : }
102 : }
103 :
104 : namespace {
105 : //////////////////////////////////
106 : // BEGIN FORMATTING BOILERPLATE //
107 : //////////////////////////////////
108 :
109 : // Converts an initializer list of the form { key0, value0, key1, value1, ... }
110 : // into a map of key* to value*. Is merely a readability helper for later code.
111 435 : map<grpc::string, grpc::string> ListToDict(
112 : const initializer_list<grpc::string>& values) {
113 435 : assert(values.size() % 2 == 0);
114 435 : map<grpc::string, grpc::string> value_map;
115 435 : auto value_iter = values.begin();
116 1251 : for (unsigned i = 0; i < values.size()/2; ++i) {
117 816 : grpc::string key = *value_iter;
118 816 : ++value_iter;
119 1632 : grpc::string value = *value_iter;
120 816 : value_map[key] = value;
121 816 : ++value_iter;
122 816 : }
123 435 : return value_map;
124 : }
125 :
126 : // Provides RAII indentation handling. Use as:
127 : // {
128 : // IndentScope raii_my_indent_var_name_here(my_py_printer);
129 : // // constructor indented my_py_printer
130 : // ...
131 : // // destructor called at end of scope, un-indenting my_py_printer
132 : // }
133 : class IndentScope {
134 : public:
135 2019 : explicit IndentScope(Printer* printer) : printer_(printer) {
136 2019 : printer_->Indent();
137 2019 : }
138 :
139 2019 : ~IndentScope() {
140 2019 : printer_->Outdent();
141 2019 : }
142 :
143 : private:
144 : Printer* printer_;
145 : };
146 :
147 : ////////////////////////////////
148 : // END FORMATTING BOILERPLATE //
149 : ////////////////////////////////
150 :
151 27 : bool PrintAlphaServicer(const ServiceDescriptor* service,
152 : Printer* out) {
153 27 : grpc::string doc = "<fill me in later!>";
154 : map<grpc::string, grpc::string> dict = ListToDict({
155 27 : "Service", service->name(),
156 : "Documentation", doc,
157 81 : });
158 27 : out->Print(dict, "class EarlyAdopter$Service$Servicer(object):\n");
159 : {
160 27 : IndentScope raii_class_indent(out);
161 27 : out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
162 27 : out->Print("__metaclass__ = abc.ABCMeta\n");
163 150 : for (int i = 0; i < service->method_count(); ++i) {
164 123 : auto meth = service->method(i);
165 123 : grpc::string arg_name = meth->client_streaming() ?
166 246 : "request_iterator" : "request";
167 123 : out->Print("@abc.abstractmethod\n");
168 : out->Print("def $Method$(self, $ArgName$, context):\n",
169 123 : "Method", meth->name(), "ArgName", arg_name);
170 : {
171 123 : IndentScope raii_method_indent(out);
172 123 : out->Print("raise NotImplementedError()\n");
173 : }
174 150 : }
175 : }
176 54 : return true;
177 : }
178 :
179 27 : bool PrintAlphaServer(const ServiceDescriptor* service, Printer* out) {
180 27 : grpc::string doc = "<fill me in later!>";
181 : map<grpc::string, grpc::string> dict = ListToDict({
182 27 : "Service", service->name(),
183 : "Documentation", doc,
184 81 : });
185 27 : out->Print(dict, "class EarlyAdopter$Service$Server(object):\n");
186 : {
187 27 : IndentScope raii_class_indent(out);
188 27 : out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
189 27 : out->Print("__metaclass__ = abc.ABCMeta\n");
190 27 : out->Print("@abc.abstractmethod\n");
191 27 : out->Print("def start(self):\n");
192 : {
193 27 : IndentScope raii_method_indent(out);
194 27 : out->Print("raise NotImplementedError()\n");
195 : }
196 :
197 27 : out->Print("@abc.abstractmethod\n");
198 27 : out->Print("def stop(self):\n");
199 : {
200 27 : IndentScope raii_method_indent(out);
201 27 : out->Print("raise NotImplementedError()\n");
202 27 : }
203 : }
204 54 : return true;
205 : }
206 :
207 27 : bool PrintAlphaStub(const ServiceDescriptor* service,
208 : Printer* out) {
209 27 : grpc::string doc = "<fill me in later!>";
210 : map<grpc::string, grpc::string> dict = ListToDict({
211 27 : "Service", service->name(),
212 : "Documentation", doc,
213 81 : });
214 27 : out->Print(dict, "class EarlyAdopter$Service$Stub(object):\n");
215 : {
216 27 : IndentScope raii_class_indent(out);
217 27 : out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
218 27 : out->Print("__metaclass__ = abc.ABCMeta\n");
219 150 : for (int i = 0; i < service->method_count(); ++i) {
220 123 : const MethodDescriptor* meth = service->method(i);
221 123 : grpc::string arg_name = meth->client_streaming() ?
222 246 : "request_iterator" : "request";
223 246 : auto methdict = ListToDict({"Method", meth->name(), "ArgName", arg_name});
224 123 : out->Print("@abc.abstractmethod\n");
225 123 : out->Print(methdict, "def $Method$(self, $ArgName$):\n");
226 : {
227 123 : IndentScope raii_method_indent(out);
228 123 : out->Print("raise NotImplementedError()\n");
229 : }
230 123 : out->Print(methdict, "$Method$.async = None\n");
231 150 : }
232 : }
233 54 : return true;
234 : }
235 :
236 : // TODO(protobuf team): Export `ModuleName` from protobuf's
237 : // `src/google/protobuf/compiler/python/python_generator.cc` file.
238 984 : grpc::string ModuleName(const grpc::string& filename) {
239 984 : grpc::string basename = StripProto(filename);
240 984 : basename = StringReplace(basename, "-", "_");
241 984 : basename = StringReplace(basename, "/", ".");
242 984 : return basename + "_pb2";
243 : }
244 :
245 984 : bool GetModuleAndMessagePath(const Descriptor* type,
246 : pair<grpc::string, grpc::string>* out) {
247 984 : const Descriptor* path_elem_type = type;
248 984 : vector<const Descriptor*> message_path;
249 984 : do {
250 984 : message_path.push_back(path_elem_type);
251 984 : path_elem_type = path_elem_type->containing_type();
252 : } while (path_elem_type); // implicit nullptr comparison; don't be explicit
253 1968 : grpc::string file_name = type->file()->name();
254 : static const int proto_suffix_length = strlen(".proto");
255 1968 : if (!(file_name.size() > static_cast<size_t>(proto_suffix_length) &&
256 984 : file_name.find_last_of(".proto") == file_name.size() - 1)) {
257 0 : return false;
258 : }
259 1968 : grpc::string module = ModuleName(file_name);
260 1968 : grpc::string message_type;
261 5904 : for (auto path_iter = message_path.rbegin();
262 3936 : path_iter != message_path.rend(); ++path_iter) {
263 984 : message_type += (*path_iter)->name() + ".";
264 : }
265 : // no pop_back prior to C++11
266 984 : message_type.resize(message_type.size() - 1);
267 984 : *out = make_pair(module, message_type);
268 1968 : return true;
269 : }
270 :
271 27 : bool PrintAlphaServerFactory(const grpc::string& package_qualified_service_name,
272 : const ServiceDescriptor* service, Printer* out) {
273 : out->Print("def early_adopter_create_$Service$_server(servicer, port, "
274 : "private_key=None, certificate_chain=None):\n",
275 27 : "Service", service->name());
276 : {
277 27 : IndentScope raii_create_server_indent(out);
278 54 : map<grpc::string, grpc::string> method_description_constructors;
279 : map<grpc::string, pair<grpc::string, grpc::string>>
280 54 : input_message_modules_and_classes;
281 : map<grpc::string, pair<grpc::string, grpc::string>>
282 54 : output_message_modules_and_classes;
283 150 : for (int i = 0; i < service->method_count(); ++i) {
284 123 : const MethodDescriptor* method = service->method(i);
285 : const grpc::string method_description_constructor =
286 492 : grpc::string(method->client_streaming() ? "stream_" : "unary_") +
287 123 : grpc::string(method->server_streaming() ? "stream_" : "unary_") +
288 246 : "service_description";
289 246 : pair<grpc::string, grpc::string> input_message_module_and_class;
290 123 : if (!GetModuleAndMessagePath(method->input_type(),
291 123 : &input_message_module_and_class)) {
292 0 : return false;
293 : }
294 246 : pair<grpc::string, grpc::string> output_message_module_and_class;
295 123 : if (!GetModuleAndMessagePath(method->output_type(),
296 123 : &output_message_module_and_class)) {
297 0 : return false;
298 : }
299 : // Import the modules that define the messages used in RPCs.
300 : out->Print("import $Module$\n", "Module",
301 123 : input_message_module_and_class.first);
302 : out->Print("import $Module$\n", "Module",
303 123 : output_message_module_and_class.first);
304 : method_description_constructors.insert(
305 123 : make_pair(method->name(), method_description_constructor));
306 : input_message_modules_and_classes.insert(
307 123 : make_pair(method->name(), input_message_module_and_class));
308 : output_message_modules_and_classes.insert(
309 123 : make_pair(method->name(), output_message_module_and_class));
310 123 : }
311 27 : out->Print("method_service_descriptions = {\n");
312 450 : for (auto name_and_description_constructor =
313 27 : method_description_constructors.begin();
314 300 : name_and_description_constructor !=
315 : method_description_constructors.end();
316 : name_and_description_constructor++) {
317 123 : IndentScope raii_descriptions_indent(out);
318 246 : const grpc::string method_name = name_and_description_constructor->first;
319 : auto input_message_module_and_class =
320 123 : input_message_modules_and_classes.find(method_name);
321 : auto output_message_module_and_class =
322 123 : output_message_modules_and_classes.find(method_name);
323 : out->Print("\"$Method$\": alpha_utilities.$Constructor$(\n", "Method",
324 : method_name, "Constructor",
325 123 : name_and_description_constructor->second);
326 : {
327 123 : IndentScope raii_description_arguments_indent(out);
328 123 : out->Print("servicer.$Method$,\n", "Method", method_name);
329 : out->Print(
330 : "$InputTypeModule$.$InputTypeClass$.FromString,\n",
331 123 : "InputTypeModule", input_message_module_and_class->second.first,
332 246 : "InputTypeClass", input_message_module_and_class->second.second);
333 : out->Print(
334 : "$OutputTypeModule$.$OutputTypeClass$.SerializeToString,\n",
335 123 : "OutputTypeModule", output_message_module_and_class->second.first,
336 246 : "OutputTypeClass", output_message_module_and_class->second.second);
337 : }
338 123 : out->Print("),\n");
339 123 : }
340 27 : out->Print("}\n");
341 : out->Print(
342 : "return early_adopter_implementations.server("
343 : "\"$PackageQualifiedServiceName$\","
344 : " method_service_descriptions, port, private_key=private_key,"
345 : " certificate_chain=certificate_chain)\n",
346 54 : "PackageQualifiedServiceName", package_qualified_service_name);
347 : }
348 27 : return true;
349 : }
350 :
351 27 : bool PrintAlphaStubFactory(const grpc::string& package_qualified_service_name,
352 : const ServiceDescriptor* service, Printer* out) {
353 : map<grpc::string, grpc::string> dict = ListToDict({
354 27 : "Service", service->name(),
355 54 : });
356 : out->Print(dict, "def early_adopter_create_$Service$_stub(host, port,"
357 : " metadata_transformer=None,"
358 : " secure=False, root_certificates=None, private_key=None,"
359 27 : " certificate_chain=None, server_host_override=None):\n");
360 : {
361 27 : IndentScope raii_create_server_indent(out);
362 54 : map<grpc::string, grpc::string> method_description_constructors;
363 : map<grpc::string, pair<grpc::string, grpc::string>>
364 54 : input_message_modules_and_classes;
365 : map<grpc::string, pair<grpc::string, grpc::string>>
366 54 : output_message_modules_and_classes;
367 150 : for (int i = 0; i < service->method_count(); ++i) {
368 123 : const MethodDescriptor* method = service->method(i);
369 : const grpc::string method_description_constructor =
370 492 : grpc::string(method->client_streaming() ? "stream_" : "unary_") +
371 123 : grpc::string(method->server_streaming() ? "stream_" : "unary_") +
372 246 : "invocation_description";
373 246 : pair<grpc::string, grpc::string> input_message_module_and_class;
374 123 : if (!GetModuleAndMessagePath(method->input_type(),
375 123 : &input_message_module_and_class)) {
376 0 : return false;
377 : }
378 246 : pair<grpc::string, grpc::string> output_message_module_and_class;
379 123 : if (!GetModuleAndMessagePath(method->output_type(),
380 123 : &output_message_module_and_class)) {
381 0 : return false;
382 : }
383 : // Import the modules that define the messages used in RPCs.
384 : out->Print("import $Module$\n", "Module",
385 123 : input_message_module_and_class.first);
386 : out->Print("import $Module$\n", "Module",
387 123 : output_message_module_and_class.first);
388 : method_description_constructors.insert(
389 123 : make_pair(method->name(), method_description_constructor));
390 : input_message_modules_and_classes.insert(
391 123 : make_pair(method->name(), input_message_module_and_class));
392 : output_message_modules_and_classes.insert(
393 123 : make_pair(method->name(), output_message_module_and_class));
394 123 : }
395 27 : out->Print("method_invocation_descriptions = {\n");
396 450 : for (auto name_and_description_constructor =
397 27 : method_description_constructors.begin();
398 300 : name_and_description_constructor !=
399 : method_description_constructors.end();
400 : name_and_description_constructor++) {
401 123 : IndentScope raii_descriptions_indent(out);
402 246 : const grpc::string method_name = name_and_description_constructor->first;
403 : auto input_message_module_and_class =
404 123 : input_message_modules_and_classes.find(method_name);
405 : auto output_message_module_and_class =
406 123 : output_message_modules_and_classes.find(method_name);
407 : out->Print("\"$Method$\": alpha_utilities.$Constructor$(\n", "Method",
408 : method_name, "Constructor",
409 123 : name_and_description_constructor->second);
410 : {
411 123 : IndentScope raii_description_arguments_indent(out);
412 : out->Print(
413 : "$InputTypeModule$.$InputTypeClass$.SerializeToString,\n",
414 123 : "InputTypeModule", input_message_module_and_class->second.first,
415 246 : "InputTypeClass", input_message_module_and_class->second.second);
416 : out->Print(
417 : "$OutputTypeModule$.$OutputTypeClass$.FromString,\n",
418 123 : "OutputTypeModule", output_message_module_and_class->second.first,
419 246 : "OutputTypeClass", output_message_module_and_class->second.second);
420 : }
421 123 : out->Print("),\n");
422 123 : }
423 27 : out->Print("}\n");
424 : out->Print(
425 : "return early_adopter_implementations.stub("
426 : "\"$PackageQualifiedServiceName$\","
427 : " method_invocation_descriptions, host, port,"
428 : " metadata_transformer=metadata_transformer, secure=secure,"
429 : " root_certificates=root_certificates, private_key=private_key,"
430 : " certificate_chain=certificate_chain,"
431 : " server_host_override=server_host_override)\n",
432 54 : "PackageQualifiedServiceName", package_qualified_service_name);
433 : }
434 27 : return true;
435 : }
436 :
437 27 : bool PrintBetaServicer(const ServiceDescriptor* service,
438 : Printer* out) {
439 27 : grpc::string doc = "<fill me in later!>";
440 : map<grpc::string, grpc::string> dict = ListToDict({
441 27 : "Service", service->name(),
442 : "Documentation", doc,
443 81 : });
444 27 : out->Print("\n");
445 27 : out->Print(dict, "class Beta$Service$Servicer(object):\n");
446 : {
447 27 : IndentScope raii_class_indent(out);
448 27 : out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
449 27 : out->Print("__metaclass__ = abc.ABCMeta\n");
450 150 : for (int i = 0; i < service->method_count(); ++i) {
451 123 : auto meth = service->method(i);
452 123 : grpc::string arg_name = meth->client_streaming() ?
453 246 : "request_iterator" : "request";
454 123 : out->Print("@abc.abstractmethod\n");
455 : out->Print("def $Method$(self, $ArgName$, context):\n",
456 123 : "Method", meth->name(), "ArgName", arg_name);
457 : {
458 123 : IndentScope raii_method_indent(out);
459 123 : out->Print("raise NotImplementedError()\n");
460 : }
461 150 : }
462 : }
463 54 : return true;
464 : }
465 :
466 27 : bool PrintBetaStub(const ServiceDescriptor* service,
467 : Printer* out) {
468 27 : grpc::string doc = "The interface to which stubs will conform.";
469 : map<grpc::string, grpc::string> dict = ListToDict({
470 27 : "Service", service->name(),
471 : "Documentation", doc,
472 81 : });
473 27 : out->Print("\n");
474 27 : out->Print(dict, "class Beta$Service$Stub(object):\n");
475 : {
476 27 : IndentScope raii_class_indent(out);
477 27 : out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
478 27 : out->Print("__metaclass__ = abc.ABCMeta\n");
479 150 : for (int i = 0; i < service->method_count(); ++i) {
480 123 : const MethodDescriptor* meth = service->method(i);
481 123 : grpc::string arg_name = meth->client_streaming() ?
482 246 : "request_iterator" : "request";
483 246 : auto methdict = ListToDict({"Method", meth->name(), "ArgName", arg_name});
484 123 : out->Print("@abc.abstractmethod\n");
485 123 : out->Print(methdict, "def $Method$(self, $ArgName$, timeout):\n");
486 : {
487 123 : IndentScope raii_method_indent(out);
488 123 : out->Print("raise NotImplementedError()\n");
489 : }
490 123 : if (!meth->server_streaming()) {
491 54 : out->Print(methdict, "$Method$.future = None\n");
492 : }
493 150 : }
494 : }
495 54 : return true;
496 : }
497 :
498 27 : bool PrintBetaServerFactory(const grpc::string& package_qualified_service_name,
499 : const ServiceDescriptor* service, Printer* out) {
500 27 : out->Print("\n");
501 : out->Print("def beta_create_$Service$_server(servicer, pool=None, "
502 : "pool_size=None, default_timeout=None, maximum_timeout=None):\n",
503 27 : "Service", service->name());
504 : {
505 27 : IndentScope raii_create_server_indent(out);
506 54 : map<grpc::string, grpc::string> method_implementation_constructors;
507 : map<grpc::string, pair<grpc::string, grpc::string>>
508 54 : input_message_modules_and_classes;
509 : map<grpc::string, pair<grpc::string, grpc::string>>
510 54 : output_message_modules_and_classes;
511 150 : for (int i = 0; i < service->method_count(); ++i) {
512 123 : const MethodDescriptor* method = service->method(i);
513 : const grpc::string method_implementation_constructor =
514 492 : grpc::string(method->client_streaming() ? "stream_" : "unary_") +
515 123 : grpc::string(method->server_streaming() ? "stream_" : "unary_") +
516 246 : "inline";
517 246 : pair<grpc::string, grpc::string> input_message_module_and_class;
518 123 : if (!GetModuleAndMessagePath(method->input_type(),
519 123 : &input_message_module_and_class)) {
520 0 : return false;
521 : }
522 246 : pair<grpc::string, grpc::string> output_message_module_and_class;
523 123 : if (!GetModuleAndMessagePath(method->output_type(),
524 123 : &output_message_module_and_class)) {
525 0 : return false;
526 : }
527 : // Import the modules that define the messages used in RPCs.
528 : out->Print("import $Module$\n", "Module",
529 123 : input_message_module_and_class.first);
530 : out->Print("import $Module$\n", "Module",
531 123 : output_message_module_and_class.first);
532 : method_implementation_constructors.insert(
533 123 : make_pair(method->name(), method_implementation_constructor));
534 : input_message_modules_and_classes.insert(
535 123 : make_pair(method->name(), input_message_module_and_class));
536 : output_message_modules_and_classes.insert(
537 123 : make_pair(method->name(), output_message_module_and_class));
538 123 : }
539 27 : out->Print("request_deserializers = {\n");
540 450 : for (auto name_and_input_module_class_pair =
541 27 : input_message_modules_and_classes.begin();
542 300 : name_and_input_module_class_pair !=
543 : input_message_modules_and_classes.end();
544 : name_and_input_module_class_pair++) {
545 123 : IndentScope raii_indent(out);
546 : out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
547 : "$InputTypeModule$.$InputTypeClass$.FromString,\n",
548 : "PackageQualifiedServiceName", package_qualified_service_name,
549 123 : "MethodName", name_and_input_module_class_pair->first,
550 : "InputTypeModule",
551 123 : name_and_input_module_class_pair->second.first,
552 : "InputTypeClass",
553 369 : name_and_input_module_class_pair->second.second);
554 123 : }
555 27 : out->Print("}\n");
556 27 : out->Print("response_serializers = {\n");
557 450 : for (auto name_and_output_module_class_pair =
558 27 : output_message_modules_and_classes.begin();
559 300 : name_and_output_module_class_pair !=
560 : output_message_modules_and_classes.end();
561 : name_and_output_module_class_pair++) {
562 123 : IndentScope raii_indent(out);
563 : out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
564 : "$OutputTypeModule$.$OutputTypeClass$.SerializeToString,\n",
565 : "PackageQualifiedServiceName", package_qualified_service_name,
566 123 : "MethodName", name_and_output_module_class_pair->first,
567 : "OutputTypeModule",
568 123 : name_and_output_module_class_pair->second.first,
569 : "OutputTypeClass",
570 369 : name_and_output_module_class_pair->second.second);
571 123 : }
572 27 : out->Print("}\n");
573 27 : out->Print("method_implementations = {\n");
574 450 : for (auto name_and_implementation_constructor =
575 27 : method_implementation_constructors.begin();
576 300 : name_and_implementation_constructor !=
577 : method_implementation_constructors.end();
578 : name_and_implementation_constructor++) {
579 123 : IndentScope raii_descriptions_indent(out);
580 : const grpc::string method_name =
581 246 : name_and_implementation_constructor->first;
582 : out->Print("(\'$PackageQualifiedServiceName$\', \'$Method$\'): "
583 : "face_utilities.$Constructor$(servicer.$Method$),\n",
584 : "PackageQualifiedServiceName", package_qualified_service_name,
585 123 : "Method", name_and_implementation_constructor->first,
586 246 : "Constructor", name_and_implementation_constructor->second);
587 123 : }
588 27 : out->Print("}\n");
589 : out->Print("server_options = beta_implementations.server_options("
590 : "request_deserializers=request_deserializers, "
591 : "response_serializers=response_serializers, "
592 : "thread_pool=pool, thread_pool_size=pool_size, "
593 : "default_timeout=default_timeout, "
594 27 : "maximum_timeout=maximum_timeout)\n");
595 : out->Print("return beta_implementations.server(method_implementations, "
596 54 : "options=server_options)\n");
597 : }
598 27 : return true;
599 : }
600 :
601 27 : bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
602 : const ServiceDescriptor* service, Printer* out) {
603 : map<grpc::string, grpc::string> dict = ListToDict({
604 27 : "Service", service->name(),
605 54 : });
606 27 : out->Print("\n");
607 : out->Print(dict, "def beta_create_$Service$_stub(channel, host=None,"
608 27 : " metadata_transformer=None, pool=None, pool_size=None):\n");
609 : {
610 27 : IndentScope raii_create_server_indent(out);
611 54 : map<grpc::string, grpc::string> method_cardinalities;
612 : map<grpc::string, pair<grpc::string, grpc::string>>
613 54 : input_message_modules_and_classes;
614 : map<grpc::string, pair<grpc::string, grpc::string>>
615 54 : output_message_modules_and_classes;
616 150 : for (int i = 0; i < service->method_count(); ++i) {
617 123 : const MethodDescriptor* method = service->method(i);
618 : const grpc::string method_cardinality =
619 246 : grpc::string(method->client_streaming() ? "STREAM" : "UNARY") +
620 : "_" +
621 369 : grpc::string(method->server_streaming() ? "STREAM" : "UNARY");
622 246 : pair<grpc::string, grpc::string> input_message_module_and_class;
623 123 : if (!GetModuleAndMessagePath(method->input_type(),
624 123 : &input_message_module_and_class)) {
625 0 : return false;
626 : }
627 246 : pair<grpc::string, grpc::string> output_message_module_and_class;
628 123 : if (!GetModuleAndMessagePath(method->output_type(),
629 123 : &output_message_module_and_class)) {
630 0 : return false;
631 : }
632 : // Import the modules that define the messages used in RPCs.
633 : out->Print("import $Module$\n", "Module",
634 123 : input_message_module_and_class.first);
635 : out->Print("import $Module$\n", "Module",
636 123 : output_message_module_and_class.first);
637 : method_cardinalities.insert(
638 123 : make_pair(method->name(), method_cardinality));
639 : input_message_modules_and_classes.insert(
640 123 : make_pair(method->name(), input_message_module_and_class));
641 : output_message_modules_and_classes.insert(
642 123 : make_pair(method->name(), output_message_module_and_class));
643 123 : }
644 27 : out->Print("request_serializers = {\n");
645 450 : for (auto name_and_input_module_class_pair =
646 27 : input_message_modules_and_classes.begin();
647 300 : name_and_input_module_class_pair !=
648 : input_message_modules_and_classes.end();
649 : name_and_input_module_class_pair++) {
650 123 : IndentScope raii_indent(out);
651 : out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
652 : "$InputTypeModule$.$InputTypeClass$.SerializeToString,\n",
653 : "PackageQualifiedServiceName", package_qualified_service_name,
654 123 : "MethodName", name_and_input_module_class_pair->first,
655 : "InputTypeModule",
656 123 : name_and_input_module_class_pair->second.first,
657 : "InputTypeClass",
658 369 : name_and_input_module_class_pair->second.second);
659 123 : }
660 27 : out->Print("}\n");
661 27 : out->Print("response_deserializers = {\n");
662 450 : for (auto name_and_output_module_class_pair =
663 27 : output_message_modules_and_classes.begin();
664 300 : name_and_output_module_class_pair !=
665 : output_message_modules_and_classes.end();
666 : name_and_output_module_class_pair++) {
667 123 : IndentScope raii_indent(out);
668 : out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
669 : "$OutputTypeModule$.$OutputTypeClass$.FromString,\n",
670 : "PackageQualifiedServiceName", package_qualified_service_name,
671 123 : "MethodName", name_and_output_module_class_pair->first,
672 : "OutputTypeModule",
673 123 : name_and_output_module_class_pair->second.first,
674 : "OutputTypeClass",
675 369 : name_and_output_module_class_pair->second.second);
676 123 : }
677 27 : out->Print("}\n");
678 27 : out->Print("cardinalities = {\n");
679 450 : for (auto name_and_cardinality = method_cardinalities.begin();
680 300 : name_and_cardinality != method_cardinalities.end();
681 : name_and_cardinality++) {
682 123 : IndentScope raii_descriptions_indent(out);
683 : out->Print("\'$Method$\': cardinality.Cardinality.$Cardinality$,\n",
684 123 : "Method", name_and_cardinality->first,
685 246 : "Cardinality", name_and_cardinality->second);
686 123 : }
687 27 : out->Print("}\n");
688 : out->Print("stub_options = beta_implementations.stub_options("
689 : "host=host, metadata_transformer=metadata_transformer, "
690 : "request_serializers=request_serializers, "
691 : "response_deserializers=response_deserializers, "
692 27 : "thread_pool=pool, thread_pool_size=pool_size)\n");
693 : out->Print(
694 : "return beta_implementations.dynamic_stub(channel, \'$PackageQualifiedServiceName$\', "
695 : "cardinalities, options=stub_options)\n",
696 54 : "PackageQualifiedServiceName", package_qualified_service_name);
697 : }
698 27 : return true;
699 : }
700 :
701 27 : bool PrintPreamble(const FileDescriptor* file,
702 : const GeneratorConfiguration& config, Printer* out) {
703 27 : out->Print("import abc\n");
704 : out->Print("from $Package$ import implementations as beta_implementations\n",
705 27 : "Package", config.beta_package_root);
706 : out->Print("from $Package$ import implementations as early_adopter_implementations\n",
707 27 : "Package", config.early_adopter_package_root);
708 27 : out->Print("from grpc.framework.alpha import utilities as alpha_utilities\n");
709 27 : out->Print("from grpc.framework.common import cardinality\n");
710 27 : out->Print("from grpc.framework.interfaces.face import utilities as face_utilities\n");
711 27 : return true;
712 : }
713 :
714 : } // namespace
715 :
716 27 : pair<bool, grpc::string> GetServices(const FileDescriptor* file,
717 : const GeneratorConfiguration& config) {
718 27 : grpc::string output;
719 : {
720 : // Scope the output stream so it closes and finalizes output to the string.
721 27 : StringOutputStream output_stream(&output);
722 54 : Printer out(&output_stream, '$');
723 27 : if (!PrintPreamble(file, config, &out)) {
724 0 : return make_pair(false, "");
725 : }
726 54 : auto package = file->package();
727 27 : if (!package.empty()) {
728 27 : package = package.append(".");
729 : }
730 54 : for (int i = 0; i < file->service_count(); ++i) {
731 27 : auto service = file->service(i);
732 27 : auto package_qualified_service_name = package + service->name();
733 81 : if (!(PrintAlphaServicer(service, &out) &&
734 54 : PrintAlphaServer(service, &out) &&
735 54 : PrintAlphaStub(service, &out) &&
736 54 : PrintAlphaServerFactory(package_qualified_service_name, service, &out) &&
737 54 : PrintAlphaStubFactory(package_qualified_service_name, service, &out) &&
738 54 : PrintBetaServicer(service, &out) &&
739 54 : PrintBetaStub(service, &out) &&
740 27 : PrintBetaServerFactory(package_qualified_service_name, service, &out) &&
741 54 : PrintBetaStubFactory(package_qualified_service_name, service, &out))) {
742 0 : return make_pair(false, "");
743 : }
744 54 : }
745 : }
746 27 : return make_pair(true, std::move(output));
747 : }
748 :
749 : } // namespace grpc_python_generator
|