blob: 1ec3772f9f72955afb1957e6f107e5d90c8fe381 [file] [log] [blame]
Masood Malekghassemif8e297a2015-02-19 15:39:32 -08001/*
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
Masood Malekghassemi40e8cbd2015-02-26 08:39:50 -080034#include <algorithm>
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080035#include <cassert>
36#include <cctype>
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -080037#include <cstring>
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080038#include <map>
Masood Malekghassemi3bb52152015-03-17 21:52:52 -070039#include <memory>
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080040#include <ostream>
41#include <sstream>
Masood Malekghassemi3bb52152015-03-17 21:52:52 -070042#include <string>
43#include <tuple>
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -080044#include <vector>
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080045
Nicolas "Pixel" Noble93fa0982015-02-27 21:50:58 +010046#include "src/compiler/generator_helpers.h"
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080047#include "src/compiler/python_generator.h"
Masood Malekghassemi3bb52152015-03-17 21:52:52 -070048#include <google/protobuf/io/coded_stream.h>
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080049#include <google/protobuf/io/printer.h>
Masood Malekghassemi3bb52152015-03-17 21:52:52 -070050#include <google/protobuf/io/zero_copy_stream.h>
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080051#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
52#include <google/protobuf/descriptor.pb.h>
53#include <google/protobuf/descriptor.h>
54
Nicolas "Pixel" Noble93fa0982015-02-27 21:50:58 +010055using grpc_generator::StringReplace;
56using grpc_generator::StripProto;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -080057using google::protobuf::Descriptor;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080058using google::protobuf::FileDescriptor;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080059using google::protobuf::MethodDescriptor;
Masood Malekghassemi40e8cbd2015-02-26 08:39:50 -080060using google::protobuf::ServiceDescriptor;
Masood Malekghassemi3bb52152015-03-17 21:52:52 -070061using google::protobuf::compiler::GeneratorContext;
62using google::protobuf::io::CodedOutputStream;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080063using google::protobuf::io::Printer;
64using google::protobuf::io::StringOutputStream;
Masood Malekghassemi3bb52152015-03-17 21:52:52 -070065using google::protobuf::io::ZeroCopyOutputStream;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080066using std::initializer_list;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -080067using std::make_pair;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080068using std::map;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -080069using std::pair;
Masood Malekghassemi40e8cbd2015-02-26 08:39:50 -080070using std::replace;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -080071using std::vector;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080072
73namespace grpc_python_generator {
Masood Malekghassemi3bb52152015-03-17 21:52:52 -070074
75PythonGrpcGenerator::PythonGrpcGenerator(const GeneratorConfiguration& config)
76 : config_(config) {}
77
78PythonGrpcGenerator::~PythonGrpcGenerator() {}
79
80bool PythonGrpcGenerator::Generate(
81 const FileDescriptor* file, const std::string& parameter,
82 GeneratorContext* context, std::string* error) const {
83 // Get output file name.
84 std::string file_name;
85 static const int proto_suffix_length = strlen(".proto");
86 if (file->name().size() > static_cast<size_t>(proto_suffix_length) &&
87 file->name().find_last_of(".proto") == file->name().size() - 1) {
88 file_name = file->name().substr(
89 0, file->name().size() - proto_suffix_length) + "_pb2.py";
90 } else {
91 *error = "Invalid proto file name. Proto file must end with .proto";
92 return false;
93 }
94
95 std::unique_ptr<ZeroCopyOutputStream> output(
96 context->OpenForInsert(file_name, "module_scope"));
97 CodedOutputStream coded_out(output.get());
98 bool success = false;
99 std::string code = "";
100 tie(success, code) = grpc_python_generator::GetServices(file, config_);
101 if (success) {
102 coded_out.WriteRaw(code.data(), code.size());
103 return true;
104 } else {
105 return false;
106 }
107}
108
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800109namespace {
110//////////////////////////////////
111// BEGIN FORMATTING BOILERPLATE //
112//////////////////////////////////
113
114// Converts an initializer list of the form { key0, value0, key1, value1, ... }
115// into a map of key* to value*. Is merely a readability helper for later code.
Masood Malekghassemi3bb52152015-03-17 21:52:52 -0700116map<std::string, std::string> ListToDict(
117 const initializer_list<std::string>& values) {
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800118 assert(values.size() % 2 == 0);
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100119 map<std::string, std::string> value_map;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800120 auto value_iter = values.begin();
121 for (unsigned i = 0; i < values.size()/2; ++i) {
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100122 std::string key = *value_iter;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800123 ++value_iter;
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100124 std::string value = *value_iter;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800125 value_map[key] = value;
126 ++value_iter;
127 }
128 return value_map;
129}
130
131// Provides RAII indentation handling. Use as:
132// {
133// IndentScope raii_my_indent_var_name_here(my_py_printer);
134// // constructor indented my_py_printer
135// ...
136// // destructor called at end of scope, un-indenting my_py_printer
137// }
138class IndentScope {
139 public:
140 explicit IndentScope(Printer* printer) : printer_(printer) {
141 printer_->Indent();
142 }
143
144 ~IndentScope() {
145 printer_->Outdent();
146 }
147
148 private:
149 Printer* printer_;
150};
151
152////////////////////////////////
153// END FORMATTING BOILERPLATE //
154////////////////////////////////
155
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800156bool PrintServicer(const ServiceDescriptor* service,
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800157 Printer* out) {
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100158 std::string doc = "<fill me in later!>";
159 map<std::string, std::string> dict = ListToDict({
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800160 "Service", service->name(),
161 "Documentation", doc,
162 });
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800163 out->Print(dict, "class EarlyAdopter$Service$Servicer(object):\n");
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800164 {
165 IndentScope raii_class_indent(out);
166 out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800167 out->Print("__metaclass__ = abc.ABCMeta\n");
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800168 for (int i = 0; i < service->method_count(); ++i) {
169 auto meth = service->method(i);
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100170 std::string arg_name = meth->client_streaming() ?
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800171 "request_iterator" : "request";
172 out->Print("@abc.abstractmethod\n");
Masood Malekghassemi40e8cbd2015-02-26 08:39:50 -0800173 out->Print("def $Method$(self, $ArgName$, context):\n",
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800174 "Method", meth->name(), "ArgName", arg_name);
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800175 {
176 IndentScope raii_method_indent(out);
177 out->Print("raise NotImplementedError()\n");
178 }
179 }
180 }
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800181 return true;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800182}
183
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800184bool PrintServer(const ServiceDescriptor* service, Printer* out) {
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100185 std::string doc = "<fill me in later!>";
186 map<std::string, std::string> dict = ListToDict({
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800187 "Service", service->name(),
188 "Documentation", doc,
189 });
190 out->Print(dict, "class EarlyAdopter$Service$Server(object):\n");
191 {
192 IndentScope raii_class_indent(out);
193 out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
194 out->Print("__metaclass__ = abc.ABCMeta\n");
195 out->Print("@abc.abstractmethod\n");
196 out->Print("def start(self):\n");
197 {
198 IndentScope raii_method_indent(out);
199 out->Print("raise NotImplementedError()\n");
200 }
201
202 out->Print("@abc.abstractmethod\n");
203 out->Print("def stop(self):\n");
204 {
205 IndentScope raii_method_indent(out);
206 out->Print("raise NotImplementedError()\n");
207 }
208 }
209 return true;
210}
211
212bool PrintStub(const ServiceDescriptor* service,
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800213 Printer* out) {
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100214 std::string doc = "<fill me in later!>";
215 map<std::string, std::string> dict = ListToDict({
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800216 "Service", service->name(),
217 "Documentation", doc,
218 });
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800219 out->Print(dict, "class EarlyAdopter$Service$Stub(object):\n");
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800220 {
221 IndentScope raii_class_indent(out);
222 out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800223 out->Print("__metaclass__ = abc.ABCMeta\n");
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800224 for (int i = 0; i < service->method_count(); ++i) {
225 const MethodDescriptor* meth = service->method(i);
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100226 std::string arg_name = meth->client_streaming() ?
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800227 "request_iterator" : "request";
228 auto methdict = ListToDict({"Method", meth->name(), "ArgName", arg_name});
229 out->Print("@abc.abstractmethod\n");
230 out->Print(methdict, "def $Method$(self, $ArgName$):\n");
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800231 {
232 IndentScope raii_method_indent(out);
233 out->Print("raise NotImplementedError()\n");
234 }
235 out->Print(methdict, "$Method$.async = None\n");
236 }
237 }
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800238 return true;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800239}
240
Masood Malekghassemi40e8cbd2015-02-26 08:39:50 -0800241// TODO(protobuf team): Export `ModuleName` from protobuf's
242// `src/google/protobuf/compiler/python/python_generator.cc` file.
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100243std::string ModuleName(const std::string& filename) {
244 std::string basename = StripProto(filename);
Nicolas "Pixel" Noble93fa0982015-02-27 21:50:58 +0100245 basename = StringReplace(basename, "-", "_");
246 basename = StringReplace(basename, "/", ".");
Masood Malekghassemi40e8cbd2015-02-26 08:39:50 -0800247 return basename + "_pb2";
248}
249
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800250bool GetModuleAndMessagePath(const Descriptor* type,
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100251 pair<std::string, std::string>* out) {
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800252 const Descriptor* path_elem_type = type;
253 vector<const Descriptor*> message_path;
254 do {
255 message_path.push_back(path_elem_type);
256 path_elem_type = path_elem_type->containing_type();
257 } while (path_elem_type != nullptr);
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100258 std::string file_name = type->file()->name();
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800259 static const int proto_suffix_length = strlen(".proto");
260 if (!(file_name.size() > static_cast<size_t>(proto_suffix_length) &&
261 file_name.find_last_of(".proto") == file_name.size() - 1)) {
262 return false;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800263 }
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100264 std::string module = ModuleName(file_name);
265 std::string message_type;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800266 for (auto path_iter = message_path.rbegin();
267 path_iter != message_path.rend(); ++path_iter) {
268 message_type += (*path_iter)->name() + ".";
269 }
Craig Tillercf133f42015-02-26 14:05:56 -0800270 // no pop_back prior to C++11
271 message_type.resize(message_type.size() - 1);
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800272 *out = make_pair(module, message_type);
273 return true;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800274}
275
Nathaniel Manistac4fada62015-03-13 22:23:59 +0000276bool PrintServerFactory(const std::string& package_qualified_service_name,
277 const ServiceDescriptor* service, Printer* out) {
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800278 out->Print("def early_adopter_create_$Service$_server(servicer, port, "
279 "root_certificates, key_chain_pairs):\n",
280 "Service", service->name());
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800281 {
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800282 IndentScope raii_create_server_indent(out);
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100283 map<std::string, std::string> method_description_constructors;
Masood Malekghassemi3bb52152015-03-17 21:52:52 -0700284 map<std::string, pair<std::string, std::string>>
285 input_message_modules_and_classes;
286 map<std::string, pair<std::string, std::string>>
287 output_message_modules_and_classes;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800288 for (int i = 0; i < service->method_count(); ++i) {
Nathaniel Manistaa60a77b2015-03-02 08:30:49 +0000289 const MethodDescriptor* method = service->method(i);
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100290 const std::string method_description_constructor =
291 std::string(method->client_streaming() ? "stream_" : "unary_") +
292 std::string(method->server_streaming() ? "stream_" : "unary_") +
Nathaniel Manistaa60a77b2015-03-02 08:30:49 +0000293 "service_description";
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100294 pair<std::string, std::string> input_message_module_and_class;
Nathaniel Manistaa60a77b2015-03-02 08:30:49 +0000295 if (!GetModuleAndMessagePath(method->input_type(),
296 &input_message_module_and_class)) {
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800297 return false;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800298 }
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100299 pair<std::string, std::string> output_message_module_and_class;
Nathaniel Manistaa60a77b2015-03-02 08:30:49 +0000300 if (!GetModuleAndMessagePath(method->output_type(),
301 &output_message_module_and_class)) {
302 return false;
303 }
304 // Import the modules that define the messages used in RPCs.
305 out->Print("import $Module$\n", "Module",
306 input_message_module_and_class.first);
307 out->Print("import $Module$\n", "Module",
308 output_message_module_and_class.first);
309 method_description_constructors.insert(
310 make_pair(method->name(), method_description_constructor));
311 input_message_modules_and_classes.insert(
312 make_pair(method->name(), input_message_module_and_class));
313 output_message_modules_and_classes.insert(
314 make_pair(method->name(), output_message_module_and_class));
315 }
316 out->Print("method_service_descriptions = {\n");
317 for (auto& name_and_description_constructor :
318 method_description_constructors) {
319 IndentScope raii_descriptions_indent(out);
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100320 const std::string method_name = name_and_description_constructor.first;
Nathaniel Manistaa60a77b2015-03-02 08:30:49 +0000321 auto input_message_module_and_class =
322 input_message_modules_and_classes.find(method_name);
323 auto output_message_module_and_class =
324 output_message_modules_and_classes.find(method_name);
325 out->Print("\"$Method$\": utilities.$Constructor$(\n", "Method",
326 method_name, "Constructor",
327 name_and_description_constructor.second);
328 {
329 IndentScope raii_description_arguments_indent(out);
330 out->Print("servicer.$Method$,\n", "Method", method_name);
331 out->Print(
332 "$InputTypeModule$.$InputTypeClass$.FromString,\n",
333 "InputTypeModule", input_message_module_and_class->second.first,
334 "InputTypeClass", input_message_module_and_class->second.second);
335 out->Print(
336 "$OutputTypeModule$.$OutputTypeClass$.SerializeToString,\n",
337 "OutputTypeModule", output_message_module_and_class->second.first,
338 "OutputTypeClass", output_message_module_and_class->second.second);
339 }
340 out->Print("),\n");
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800341 }
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800342 out->Print("}\n");
Nathaniel Manistaa60a77b2015-03-02 08:30:49 +0000343 out->Print(
344 "return implementations.secure_server("
Nathaniel Manistac4fada62015-03-13 22:23:59 +0000345 "\"$PackageQualifiedServiceName$\","
346 " method_service_descriptions, port, root_certificates,"
347 " key_chain_pairs)\n",
348 "PackageQualifiedServiceName", package_qualified_service_name);
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800349 }
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800350 return true;
351}
352
Nathaniel Manistac4fada62015-03-13 22:23:59 +0000353bool PrintStubFactory(const std::string& package_qualified_service_name,
354 const ServiceDescriptor* service, Printer* out) {
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100355 map<std::string, std::string> dict = ListToDict({
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800356 "Service", service->name(),
357 });
358 out->Print(dict, "def early_adopter_create_$Service$_stub(host, port):\n");
359 {
360 IndentScope raii_create_server_indent(out);
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100361 map<std::string, std::string> method_description_constructors;
Masood Malekghassemi3bb52152015-03-17 21:52:52 -0700362 map<std::string, pair<std::string, std::string>>
363 input_message_modules_and_classes;
364 map<std::string, pair<std::string, std::string>>
365 output_message_modules_and_classes;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800366 for (int i = 0; i < service->method_count(); ++i) {
Nathaniel Manistaa60a77b2015-03-02 08:30:49 +0000367 const MethodDescriptor* method = service->method(i);
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100368 const std::string method_description_constructor =
369 std::string(method->client_streaming() ? "stream_" : "unary_") +
370 std::string(method->server_streaming() ? "stream_" : "unary_") +
Nathaniel Manistaa60a77b2015-03-02 08:30:49 +0000371 "invocation_description";
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100372 pair<std::string, std::string> input_message_module_and_class;
Nathaniel Manistaa60a77b2015-03-02 08:30:49 +0000373 if (!GetModuleAndMessagePath(method->input_type(),
374 &input_message_module_and_class)) {
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800375 return false;
376 }
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100377 pair<std::string, std::string> output_message_module_and_class;
Nathaniel Manistaa60a77b2015-03-02 08:30:49 +0000378 if (!GetModuleAndMessagePath(method->output_type(),
379 &output_message_module_and_class)) {
380 return false;
381 }
382 // Import the modules that define the messages used in RPCs.
383 out->Print("import $Module$\n", "Module",
384 input_message_module_and_class.first);
385 out->Print("import $Module$\n", "Module",
386 output_message_module_and_class.first);
387 method_description_constructors.insert(
388 make_pair(method->name(), method_description_constructor));
389 input_message_modules_and_classes.insert(
390 make_pair(method->name(), input_message_module_and_class));
391 output_message_modules_and_classes.insert(
392 make_pair(method->name(), output_message_module_and_class));
393 }
394 out->Print("method_invocation_descriptions = {\n");
395 for (auto& name_and_description_constructor :
396 method_description_constructors) {
397 IndentScope raii_descriptions_indent(out);
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100398 const std::string method_name = name_and_description_constructor.first;
Nathaniel Manistaa60a77b2015-03-02 08:30:49 +0000399 auto input_message_module_and_class =
400 input_message_modules_and_classes.find(method_name);
401 auto output_message_module_and_class =
402 output_message_modules_and_classes.find(method_name);
403 out->Print("\"$Method$\": utilities.$Constructor$(\n", "Method",
404 method_name, "Constructor",
405 name_and_description_constructor.second);
406 {
407 IndentScope raii_description_arguments_indent(out);
408 out->Print(
409 "$InputTypeModule$.$InputTypeClass$.SerializeToString,\n",
410 "InputTypeModule", input_message_module_and_class->second.first,
411 "InputTypeClass", input_message_module_and_class->second.second);
412 out->Print(
413 "$OutputTypeModule$.$OutputTypeClass$.FromString,\n",
414 "OutputTypeModule", output_message_module_and_class->second.first,
415 "OutputTypeClass", output_message_module_and_class->second.second);
416 }
417 out->Print("),\n");
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800418 }
419 out->Print("}\n");
Nathaniel Manistaa60a77b2015-03-02 08:30:49 +0000420 out->Print(
421 "return implementations.insecure_stub("
Nathaniel Manistac4fada62015-03-13 22:23:59 +0000422 "\"$PackageQualifiedServiceName$\","
423 " method_invocation_descriptions, host, port)\n",
424 "PackageQualifiedServiceName", package_qualified_service_name);
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800425 }
426 return true;
427}
428
Masood Malekghassemi3bb52152015-03-17 21:52:52 -0700429bool PrintPreamble(const FileDescriptor* file,
430 const GeneratorConfiguration& config, Printer* out) {
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800431 out->Print("import abc\n");
Masood Malekghassemi3bb52152015-03-17 21:52:52 -0700432 out->Print("from $Package$ import implementations\n",
433 "Package", config.implementations_package_root);
Masood Malekghassemi89905ac2015-03-17 18:26:48 -0700434 out->Print("from grpc.framework.alpha import utilities\n");
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800435 return true;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800436}
437
438} // namespace
439
Masood Malekghassemi3bb52152015-03-17 21:52:52 -0700440pair<bool, std::string> GetServices(const FileDescriptor* file,
441 const GeneratorConfiguration& config) {
Nicolas "Pixel" Noble00841792015-03-11 00:18:55 +0100442 std::string output;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800443 {
444 // Scope the output stream so it closes and finalizes output to the string.
445 StringOutputStream output_stream(&output);
446 Printer out(&output_stream, '$');
Masood Malekghassemi3bb52152015-03-17 21:52:52 -0700447 if (!PrintPreamble(file, config, &out)) {
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800448 return make_pair(false, "");
449 }
Nathaniel Manistac4fada62015-03-13 22:23:59 +0000450 auto package = file->package();
451 if (!package.empty()) {
452 package = package.append(".");
453 }
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800454 for (int i = 0; i < file->service_count(); ++i) {
455 auto service = file->service(i);
Nathaniel Manistac4fada62015-03-13 22:23:59 +0000456 auto package_qualified_service_name = package + service->name();
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800457 if (!(PrintServicer(service, &out) &&
458 PrintServer(service, &out) &&
459 PrintStub(service, &out) &&
Nathaniel Manistac4fada62015-03-13 22:23:59 +0000460 PrintServerFactory(package_qualified_service_name, service, &out) &&
461 PrintStubFactory(package_qualified_service_name, service, &out))) {
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800462 return make_pair(false, "");
463 }
464 }
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800465 }
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800466 return make_pair(true, std::move(output));
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800467}
468
469} // namespace grpc_python_generator