blob: 0fac1b88cd93692a86d328ba6c8352cefc86dbca [file] [log] [blame]
Masood Malekghassemif8e297a2015-02-19 15:39:32 -08001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
Masood Malekghassemif8e297a2015-02-19 15:39:32 -08004 * 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 Malekghassemid9539592016-10-20 14:47:14 -070038#include <fstream>
39#include <iostream>
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080040#include <map>
Masood Malekghassemi3bb52152015-03-17 21:52:52 -070041#include <memory>
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080042#include <ostream>
Bryan Blanchardc549a3e2016-12-13 07:46:28 -050043#include <set>
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080044#include <sstream>
Masood Malekghassemi3bb52152015-03-17 21:52:52 -070045#include <tuple>
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -080046#include <vector>
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080047
Masood Malekghassemi65c803b2015-03-20 06:48:47 -070048#include "src/compiler/config.h"
Nicolas "Pixel" Noble93fa0982015-02-27 21:50:58 +010049#include "src/compiler/generator_helpers.h"
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080050#include "src/compiler/python_generator.h"
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080051
Nicolas "Pixel" Noble93fa0982015-02-27 21:50:58 +010052using grpc_generator::StringReplace;
53using grpc_generator::StripProto;
Masood Malekghassemi65c803b2015-03-20 06:48:47 -070054using grpc::protobuf::Descriptor;
55using grpc::protobuf::FileDescriptor;
56using grpc::protobuf::MethodDescriptor;
57using grpc::protobuf::ServiceDescriptor;
58using grpc::protobuf::compiler::GeneratorContext;
59using grpc::protobuf::io::CodedOutputStream;
60using grpc::protobuf::io::Printer;
61using grpc::protobuf::io::StringOutputStream;
62using grpc::protobuf::io::ZeroCopyOutputStream;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080063using std::initializer_list;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -080064using std::make_pair;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080065using std::map;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -080066using std::pair;
Masood Malekghassemi40e8cbd2015-02-26 08:39:50 -080067using std::replace;
Bryan Blanchardc549a3e2016-12-13 07:46:28 -050068using std::tuple;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -080069using std::vector;
Bryan Blanchardc549a3e2016-12-13 07:46:28 -050070using std::set;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080071
72namespace grpc_python_generator {
Masood Malekghassemi3bb52152015-03-17 21:52:52 -070073
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080074namespace {
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080075
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -070076typedef vector<const Descriptor*> DescriptorVector;
77typedef map<grpc::string, grpc::string> StringMap;
78typedef vector<grpc::string> StringVector;
Bryan Blanchardc549a3e2016-12-13 07:46:28 -050079typedef tuple<grpc::string, grpc::string> StringPair;
80typedef set<StringPair> StringPairSet;
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -070081
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080082// Provides RAII indentation handling. Use as:
83// {
84// IndentScope raii_my_indent_var_name_here(my_py_printer);
85// // constructor indented my_py_printer
86// ...
87// // destructor called at end of scope, un-indenting my_py_printer
88// }
89class IndentScope {
90 public:
91 explicit IndentScope(Printer* printer) : printer_(printer) {
92 printer_->Indent();
93 }
94
Masood Malekghassemiac592452016-07-01 11:58:04 -070095 ~IndentScope() { printer_->Outdent(); }
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080096
97 private:
98 Printer* printer_;
99};
100
Ken Paysonbe187b02016-05-06 15:32:58 -0700101// TODO(https://github.com/google/protobuf/issues/888):
102// Export `ModuleName` from protobuf's
Masood Malekghassemi40e8cbd2015-02-26 08:39:50 -0800103// `src/google/protobuf/compiler/python/python_generator.cc` file.
Masood Malekghassemi65c803b2015-03-20 06:48:47 -0700104grpc::string ModuleName(const grpc::string& filename) {
105 grpc::string basename = StripProto(filename);
Nicolas "Pixel" Noble93fa0982015-02-27 21:50:58 +0100106 basename = StringReplace(basename, "-", "_");
107 basename = StringReplace(basename, "/", ".");
Masood Malekghassemi40e8cbd2015-02-26 08:39:50 -0800108 return basename + "_pb2";
109}
110
Ken Paysonbe187b02016-05-06 15:32:58 -0700111// TODO(https://github.com/google/protobuf/issues/888):
112// Export `ModuleAlias` from protobuf's
113// `src/google/protobuf/compiler/python/python_generator.cc` file.
114grpc::string ModuleAlias(const grpc::string& filename) {
115 grpc::string module_name = ModuleName(filename);
116 // We can't have dots in the module name, so we replace each with _dot_.
117 // But that could lead to a collision between a.b and a_dot_b, so we also
118 // duplicate each underscore.
119 module_name = StringReplace(module_name, "_", "__");
120 module_name = StringReplace(module_name, ".", "_dot_");
121 return module_name;
122}
123
Masood Malekghassemid9539592016-10-20 14:47:14 -0700124// Tucks all generator state in an anonymous namespace away from
125// PythonGrpcGenerator and the header file, mostly to encourage future changes
126// to not require updates to the grpcio-tools C++ code part. Assumes that it is
127// only ever used from a single thread.
128struct PrivateGenerator {
129 const GeneratorConfiguration& config;
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700130 const FileDescriptor* file;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700131
132 bool generate_in_pb2_grpc;
133
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700134 Printer* out;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700135
136 PrivateGenerator(const GeneratorConfiguration& config,
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700137 const FileDescriptor* file);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700138
139 std::pair<bool, grpc::string> GetGrpcServices();
140
141 private:
142 bool PrintPreamble();
143 bool PrintBetaPreamble();
144 bool PrintGAServices();
145 bool PrintBetaServices();
146
147 bool PrintAddServicerToServer(
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700148 const grpc::string& package_qualified_service_name,
149 const ServiceDescriptor* service);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700150 bool PrintServicer(const ServiceDescriptor* service);
151 bool PrintStub(const grpc::string& package_qualified_service_name,
152 const ServiceDescriptor* service);
153
154 bool PrintBetaServicer(const ServiceDescriptor* service);
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700155 bool PrintBetaServerFactory(
Masood Malekghassemid9539592016-10-20 14:47:14 -0700156 const grpc::string& package_qualified_service_name,
157 const ServiceDescriptor* service);
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700158 bool PrintBetaStub(const ServiceDescriptor* service);
159 bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
160 const ServiceDescriptor* service);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700161
162 // Get all comments (leading, leading_detached, trailing) and print them as a
163 // docstring. Any leading space of a line will be removed, but the line
164 // wrapping will not be changed.
165 template <typename DescriptorType>
166 void PrintAllComments(const DescriptorType* descriptor);
167
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700168 bool GetModuleAndMessagePath(const Descriptor* type, grpc::string* out);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700169};
170
Masood Malekghassemid9539592016-10-20 14:47:14 -0700171PrivateGenerator::PrivateGenerator(const GeneratorConfiguration& config,
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700172 const FileDescriptor* file)
173 : config(config), file(file) {}
Masood Malekghassemid9539592016-10-20 14:47:14 -0700174
175bool PrivateGenerator::GetModuleAndMessagePath(const Descriptor* type,
176 grpc::string* out) {
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800177 const Descriptor* path_elem_type = type;
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700178 DescriptorVector message_path;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800179 do {
180 message_path.push_back(path_elem_type);
181 path_elem_type = path_elem_type->containing_type();
Masood Malekghassemiac592452016-07-01 11:58:04 -0700182 } while (path_elem_type); // implicit nullptr comparison; don't be explicit
Masood Malekghassemi65c803b2015-03-20 06:48:47 -0700183 grpc::string file_name = type->file()->name();
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800184 static const int proto_suffix_length = strlen(".proto");
185 if (!(file_name.size() > static_cast<size_t>(proto_suffix_length) &&
186 file_name.find_last_of(".proto") == file_name.size() - 1)) {
187 return false;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800188 }
Masood Malekghassemid9539592016-10-20 14:47:14 -0700189 grpc::string generator_file_name = file->name();
190 grpc::string module;
191 if (generator_file_name != file_name || generate_in_pb2_grpc) {
192 module = ModuleAlias(file_name) + ".";
193 } else {
194 module = "";
195 }
Masood Malekghassemi65c803b2015-03-20 06:48:47 -0700196 grpc::string message_type;
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700197 for (DescriptorVector::reverse_iterator path_iter = message_path.rbegin();
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700198 path_iter != message_path.rend(); ++path_iter) {
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800199 message_type += (*path_iter)->name() + ".";
200 }
Craig Tillercf133f42015-02-26 14:05:56 -0800201 // no pop_back prior to C++11
202 message_type.resize(message_type.size() - 1);
Ken Paysonbe187b02016-05-06 15:32:58 -0700203 *out = module + message_type;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800204 return true;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800205}
206
yang-gb0de7162016-05-03 15:48:19 -0700207template <typename DescriptorType>
Masood Malekghassemid9539592016-10-20 14:47:14 -0700208void PrivateGenerator::PrintAllComments(const DescriptorType* descriptor) {
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700209 StringVector comments;
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700210 grpc_generator::GetComment(
211 descriptor, grpc_generator::COMMENTTYPE_LEADING_DETACHED, &comments);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700212 grpc_generator::GetComment(descriptor, grpc_generator::COMMENTTYPE_LEADING,
yang-gb0de7162016-05-03 15:48:19 -0700213 &comments);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700214 grpc_generator::GetComment(descriptor, grpc_generator::COMMENTTYPE_TRAILING,
yang-gb0de7162016-05-03 15:48:19 -0700215 &comments);
216 if (comments.empty()) {
217 return;
218 }
Masood Malekghassemid9539592016-10-20 14:47:14 -0700219 out->Print("\"\"\"");
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700220 for (StringVector::iterator it = comments.begin(); it != comments.end();
221 ++it) {
yang-gb0de7162016-05-03 15:48:19 -0700222 size_t start_pos = it->find_first_not_of(' ');
223 if (start_pos != grpc::string::npos) {
Masood Malekghassemid9539592016-10-20 14:47:14 -0700224 out->Print(it->c_str() + start_pos);
yang-gb0de7162016-05-03 15:48:19 -0700225 }
Masood Malekghassemid9539592016-10-20 14:47:14 -0700226 out->Print("\n");
yang-gb0de7162016-05-03 15:48:19 -0700227 }
Masood Malekghassemid9539592016-10-20 14:47:14 -0700228 out->Print("\"\"\"\n");
yang-gb0de7162016-05-03 15:48:19 -0700229}
230
Masood Malekghassemid9539592016-10-20 14:47:14 -0700231bool PrivateGenerator::PrintBetaServicer(const ServiceDescriptor* service) {
Ken Paysonbe187b02016-05-06 15:32:58 -0700232 out->Print("\n\n");
yang-gb0de7162016-05-03 15:48:19 -0700233 out->Print("class Beta$Service$Servicer(object):\n", "Service",
234 service->name());
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000235 {
236 IndentScope raii_class_indent(out);
Nicolas "Pixel" Noblebeeeddd2016-09-29 20:27:23 +0200237 out->Print(
238 "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
239 "\nIt is recommended to use the GA API (classes and functions in this\n"
240 "file not marked beta) for all further purposes. This class was "
241 "generated\n"
242 "only to ease transition from grpcio<0.15.0 to "
243 "grpcio>=0.15.0.\"\"\"\n");
Masood Malekghassemid9539592016-10-20 14:47:14 -0700244 PrintAllComments(service);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000245 for (int i = 0; i < service->method_count(); ++i) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700246 const MethodDescriptor* method = service->method(i);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700247 grpc::string arg_name =
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700248 method->client_streaming() ? "request_iterator" : "request";
Masood Malekghassemiac592452016-07-01 11:58:04 -0700249 out->Print("def $Method$(self, $ArgName$, context):\n", "Method",
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700250 method->name(), "ArgName", arg_name);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000251 {
252 IndentScope raii_method_indent(out);
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700253 PrintAllComments(method);
Masood Malekghassemi832ae812016-04-27 18:38:54 -0700254 out->Print("context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)\n");
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000255 }
256 }
257 }
258 return true;
259}
260
Masood Malekghassemid9539592016-10-20 14:47:14 -0700261bool PrivateGenerator::PrintBetaStub(const ServiceDescriptor* service) {
Ken Paysonbe187b02016-05-06 15:32:58 -0700262 out->Print("\n\n");
yang-gb0de7162016-05-03 15:48:19 -0700263 out->Print("class Beta$Service$Stub(object):\n", "Service", service->name());
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000264 {
265 IndentScope raii_class_indent(out);
Nicolas "Pixel" Noblebeeeddd2016-09-29 20:27:23 +0200266 out->Print(
267 "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
268 "\nIt is recommended to use the GA API (classes and functions in this\n"
269 "file not marked beta) for all further purposes. This class was "
270 "generated\n"
271 "only to ease transition from grpcio<0.15.0 to "
272 "grpcio>=0.15.0.\"\"\"\n");
Masood Malekghassemid9539592016-10-20 14:47:14 -0700273 PrintAllComments(service);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000274 for (int i = 0; i < service->method_count(); ++i) {
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700275 const MethodDescriptor* method = service->method(i);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700276 grpc::string arg_name =
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700277 method->client_streaming() ? "request_iterator" : "request";
278 StringMap method_dict;
279 method_dict["Method"] = method->name();
280 method_dict["ArgName"] = arg_name;
281 out->Print(method_dict,
Masood Malekghassemiac592452016-07-01 11:58:04 -0700282 "def $Method$(self, $ArgName$, timeout, metadata=None, "
283 "with_call=False, protocol_options=None):\n");
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000284 {
285 IndentScope raii_method_indent(out);
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700286 PrintAllComments(method);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000287 out->Print("raise NotImplementedError()\n");
288 }
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700289 if (!method->server_streaming()) {
290 out->Print(method_dict, "$Method$.future = None\n");
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000291 }
292 }
293 }
294 return true;
295}
296
Masood Malekghassemid9539592016-10-20 14:47:14 -0700297bool PrivateGenerator::PrintBetaServerFactory(
298 const grpc::string& package_qualified_service_name,
299 const ServiceDescriptor* service) {
Ken Paysonbe187b02016-05-06 15:32:58 -0700300 out->Print("\n\n");
Masood Malekghassemiac592452016-07-01 11:58:04 -0700301 out->Print(
302 "def beta_create_$Service$_server(servicer, pool=None, "
303 "pool_size=None, default_timeout=None, maximum_timeout=None):\n",
304 "Service", service->name());
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000305 {
306 IndentScope raii_create_server_indent(out);
Nicolas "Pixel" Noblebeeeddd2016-09-29 20:27:23 +0200307 out->Print(
308 "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
309 "\nIt is recommended to use the GA API (classes and functions in this\n"
310 "file not marked beta) for all further purposes. This function was\n"
311 "generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"
312 "\"\"\"\n");
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700313 StringMap method_implementation_constructors;
314 StringMap input_message_modules_and_classes;
315 StringMap output_message_modules_and_classes;
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000316 for (int i = 0; i < service->method_count(); ++i) {
317 const MethodDescriptor* method = service->method(i);
318 const grpc::string method_implementation_constructor =
319 grpc::string(method->client_streaming() ? "stream_" : "unary_") +
320 grpc::string(method->server_streaming() ? "stream_" : "unary_") +
321 "inline";
Ken Paysonbe187b02016-05-06 15:32:58 -0700322 grpc::string input_message_module_and_class;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700323 if (!GetModuleAndMessagePath(method->input_type(),
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000324 &input_message_module_and_class)) {
325 return false;
326 }
Ken Paysonbe187b02016-05-06 15:32:58 -0700327 grpc::string output_message_module_and_class;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700328 if (!GetModuleAndMessagePath(method->output_type(),
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000329 &output_message_module_and_class)) {
330 return false;
331 }
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000332 method_implementation_constructors.insert(
333 make_pair(method->name(), method_implementation_constructor));
334 input_message_modules_and_classes.insert(
335 make_pair(method->name(), input_message_module_and_class));
336 output_message_modules_and_classes.insert(
337 make_pair(method->name(), output_message_module_and_class));
338 }
339 out->Print("request_deserializers = {\n");
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700340 for (StringMap::iterator name_and_input_module_class_pair =
Masood Malekghassemiac592452016-07-01 11:58:04 -0700341 input_message_modules_and_classes.begin();
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000342 name_and_input_module_class_pair !=
Masood Malekghassemiac592452016-07-01 11:58:04 -0700343 input_message_modules_and_classes.end();
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000344 name_and_input_module_class_pair++) {
345 IndentScope raii_indent(out);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700346 out->Print(
347 "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
348 "$InputTypeModuleAndClass$.FromString,\n",
349 "PackageQualifiedServiceName", package_qualified_service_name,
350 "MethodName", name_and_input_module_class_pair->first,
351 "InputTypeModuleAndClass", name_and_input_module_class_pair->second);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000352 }
353 out->Print("}\n");
354 out->Print("response_serializers = {\n");
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700355 for (StringMap::iterator name_and_output_module_class_pair =
Masood Malekghassemiac592452016-07-01 11:58:04 -0700356 output_message_modules_and_classes.begin();
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000357 name_and_output_module_class_pair !=
Masood Malekghassemiac592452016-07-01 11:58:04 -0700358 output_message_modules_and_classes.end();
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000359 name_and_output_module_class_pair++) {
360 IndentScope raii_indent(out);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700361 out->Print(
362 "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
363 "$OutputTypeModuleAndClass$.SerializeToString,\n",
364 "PackageQualifiedServiceName", package_qualified_service_name,
365 "MethodName", name_and_output_module_class_pair->first,
366 "OutputTypeModuleAndClass",
367 name_and_output_module_class_pair->second);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000368 }
369 out->Print("}\n");
370 out->Print("method_implementations = {\n");
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700371 for (StringMap::iterator name_and_implementation_constructor =
Masood Malekghassemiac592452016-07-01 11:58:04 -0700372 method_implementation_constructors.begin();
373 name_and_implementation_constructor !=
374 method_implementation_constructors.end();
375 name_and_implementation_constructor++) {
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000376 IndentScope raii_descriptions_indent(out);
377 const grpc::string method_name =
378 name_and_implementation_constructor->first;
Masood Malekghassemiac592452016-07-01 11:58:04 -0700379 out->Print(
380 "(\'$PackageQualifiedServiceName$\', \'$Method$\'): "
381 "face_utilities.$Constructor$(servicer.$Method$),\n",
382 "PackageQualifiedServiceName", package_qualified_service_name,
383 "Method", name_and_implementation_constructor->first, "Constructor",
384 name_and_implementation_constructor->second);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000385 }
386 out->Print("}\n");
Masood Malekghassemiac592452016-07-01 11:58:04 -0700387 out->Print(
388 "server_options = beta_implementations.server_options("
389 "request_deserializers=request_deserializers, "
390 "response_serializers=response_serializers, "
391 "thread_pool=pool, thread_pool_size=pool_size, "
392 "default_timeout=default_timeout, "
393 "maximum_timeout=maximum_timeout)\n");
394 out->Print(
395 "return beta_implementations.server(method_implementations, "
396 "options=server_options)\n");
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000397 }
398 return true;
399}
400
Masood Malekghassemid9539592016-10-20 14:47:14 -0700401bool PrivateGenerator::PrintBetaStubFactory(
402 const grpc::string& package_qualified_service_name,
403 const ServiceDescriptor* service) {
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700404 StringMap dict;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700405 dict["Service"] = service->name();
Ken Paysonbe187b02016-05-06 15:32:58 -0700406 out->Print("\n\n");
Masood Malekghassemiac592452016-07-01 11:58:04 -0700407 out->Print(dict,
408 "def beta_create_$Service$_stub(channel, host=None,"
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000409 " metadata_transformer=None, pool=None, pool_size=None):\n");
410 {
411 IndentScope raii_create_server_indent(out);
Nicolas "Pixel" Noblebeeeddd2016-09-29 20:27:23 +0200412 out->Print(
413 "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
414 "\nIt is recommended to use the GA API (classes and functions in this\n"
415 "file not marked beta) for all further purposes. This function was\n"
416 "generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"
417 "\"\"\"\n");
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700418 StringMap method_cardinalities;
419 StringMap input_message_modules_and_classes;
420 StringMap output_message_modules_and_classes;
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000421 for (int i = 0; i < service->method_count(); ++i) {
422 const MethodDescriptor* method = service->method(i);
423 const grpc::string method_cardinality =
Masood Malekghassemiac592452016-07-01 11:58:04 -0700424 grpc::string(method->client_streaming() ? "STREAM" : "UNARY") + "_" +
Ken Paysonbe187b02016-05-06 15:32:58 -0700425 grpc::string(method->server_streaming() ? "STREAM" : "UNARY");
426 grpc::string input_message_module_and_class;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700427 if (!GetModuleAndMessagePath(method->input_type(),
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000428 &input_message_module_and_class)) {
429 return false;
430 }
Ken Paysonbe187b02016-05-06 15:32:58 -0700431 grpc::string output_message_module_and_class;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700432 if (!GetModuleAndMessagePath(method->output_type(),
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000433 &output_message_module_and_class)) {
434 return false;
435 }
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000436 method_cardinalities.insert(
437 make_pair(method->name(), method_cardinality));
438 input_message_modules_and_classes.insert(
439 make_pair(method->name(), input_message_module_and_class));
440 output_message_modules_and_classes.insert(
441 make_pair(method->name(), output_message_module_and_class));
442 }
443 out->Print("request_serializers = {\n");
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700444 for (StringMap::iterator name_and_input_module_class_pair =
Masood Malekghassemiac592452016-07-01 11:58:04 -0700445 input_message_modules_and_classes.begin();
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000446 name_and_input_module_class_pair !=
Masood Malekghassemiac592452016-07-01 11:58:04 -0700447 input_message_modules_and_classes.end();
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000448 name_and_input_module_class_pair++) {
449 IndentScope raii_indent(out);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700450 out->Print(
451 "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
452 "$InputTypeModuleAndClass$.SerializeToString,\n",
453 "PackageQualifiedServiceName", package_qualified_service_name,
454 "MethodName", name_and_input_module_class_pair->first,
455 "InputTypeModuleAndClass", name_and_input_module_class_pair->second);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000456 }
457 out->Print("}\n");
458 out->Print("response_deserializers = {\n");
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700459 for (StringMap::iterator name_and_output_module_class_pair =
Masood Malekghassemiac592452016-07-01 11:58:04 -0700460 output_message_modules_and_classes.begin();
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000461 name_and_output_module_class_pair !=
Masood Malekghassemiac592452016-07-01 11:58:04 -0700462 output_message_modules_and_classes.end();
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000463 name_and_output_module_class_pair++) {
464 IndentScope raii_indent(out);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700465 out->Print(
466 "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
467 "$OutputTypeModuleAndClass$.FromString,\n",
468 "PackageQualifiedServiceName", package_qualified_service_name,
469 "MethodName", name_and_output_module_class_pair->first,
470 "OutputTypeModuleAndClass",
471 name_and_output_module_class_pair->second);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000472 }
473 out->Print("}\n");
474 out->Print("cardinalities = {\n");
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700475 for (StringMap::iterator name_and_cardinality =
476 method_cardinalities.begin();
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000477 name_and_cardinality != method_cardinalities.end();
478 name_and_cardinality++) {
479 IndentScope raii_descriptions_indent(out);
480 out->Print("\'$Method$\': cardinality.Cardinality.$Cardinality$,\n",
Masood Malekghassemiac592452016-07-01 11:58:04 -0700481 "Method", name_and_cardinality->first, "Cardinality",
482 name_and_cardinality->second);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000483 }
484 out->Print("}\n");
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000485 out->Print(
Masood Malekghassemiac592452016-07-01 11:58:04 -0700486 "stub_options = beta_implementations.stub_options("
487 "host=host, metadata_transformer=metadata_transformer, "
488 "request_serializers=request_serializers, "
489 "response_deserializers=response_deserializers, "
490 "thread_pool=pool, thread_pool_size=pool_size)\n");
491 out->Print(
492 "return beta_implementations.dynamic_stub(channel, "
493 "\'$PackageQualifiedServiceName$\', "
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000494 "cardinalities, options=stub_options)\n",
495 "PackageQualifiedServiceName", package_qualified_service_name);
496 }
497 return true;
498}
499
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700500bool PrivateGenerator::PrintStub(
501 const grpc::string& package_qualified_service_name,
502 const ServiceDescriptor* service) {
Nathaniel Manista45479402016-06-13 20:14:18 +0000503 out->Print("\n\n");
504 out->Print("class $Service$Stub(object):\n", "Service", service->name());
505 {
506 IndentScope raii_class_indent(out);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700507 PrintAllComments(service);
Nathaniel Manista45479402016-06-13 20:14:18 +0000508 out->Print("\n");
509 out->Print("def __init__(self, channel):\n");
510 {
511 IndentScope raii_init_indent(out);
512 out->Print("\"\"\"Constructor.\n");
513 out->Print("\n");
514 out->Print("Args:\n");
515 {
516 IndentScope raii_args_indent(out);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700517 out->Print("channel: A grpc.Channel.\n");
Nathaniel Manista45479402016-06-13 20:14:18 +0000518 }
519 out->Print("\"\"\"\n");
520 for (int i = 0; i < service->method_count(); ++i) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700521 const MethodDescriptor* method = service->method(i);
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700522 grpc::string multi_callable_constructor =
Masood Malekghassemiac592452016-07-01 11:58:04 -0700523 grpc::string(method->client_streaming() ? "stream" : "unary") +
524 "_" + grpc::string(method->server_streaming() ? "stream" : "unary");
525 grpc::string request_module_and_class;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700526 if (!GetModuleAndMessagePath(method->input_type(),
Masood Malekghassemiac592452016-07-01 11:58:04 -0700527 &request_module_and_class)) {
Nathaniel Manista45479402016-06-13 20:14:18 +0000528 return false;
Masood Malekghassemiac592452016-07-01 11:58:04 -0700529 }
530 grpc::string response_module_and_class;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700531 if (!GetModuleAndMessagePath(method->output_type(),
Masood Malekghassemiac592452016-07-01 11:58:04 -0700532 &response_module_and_class)) {
533 return false;
534 }
535 out->Print("self.$Method$ = channel.$MultiCallableConstructor$(\n",
536 "Method", method->name(), "MultiCallableConstructor",
537 multi_callable_constructor);
538 {
Nathaniel Manista45479402016-06-13 20:14:18 +0000539 IndentScope raii_first_attribute_indent(out);
540 IndentScope raii_second_attribute_indent(out);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700541 out->Print("'/$PackageQualifiedService$/$Method$',\n",
542 "PackageQualifiedService", package_qualified_service_name,
543 "Method", method->name());
544 out->Print(
545 "request_serializer=$RequestModuleAndClass$.SerializeToString,\n",
546 "RequestModuleAndClass", request_module_and_class);
547 out->Print(
Nathaniel Manista45479402016-06-13 20:14:18 +0000548 "response_deserializer=$ResponseModuleAndClass$.FromString,\n",
Masood Malekghassemiac592452016-07-01 11:58:04 -0700549 "ResponseModuleAndClass", response_module_and_class);
550 out->Print(")\n");
551 }
Nathaniel Manista45479402016-06-13 20:14:18 +0000552 }
553 }
554 }
555 return true;
556}
557
Masood Malekghassemid9539592016-10-20 14:47:14 -0700558bool PrivateGenerator::PrintServicer(const ServiceDescriptor* service) {
Nathaniel Manista45479402016-06-13 20:14:18 +0000559 out->Print("\n\n");
560 out->Print("class $Service$Servicer(object):\n", "Service", service->name());
561 {
562 IndentScope raii_class_indent(out);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700563 PrintAllComments(service);
Nathaniel Manista45479402016-06-13 20:14:18 +0000564 for (int i = 0; i < service->method_count(); ++i) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700565 const MethodDescriptor* method = service->method(i);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700566 grpc::string arg_name =
567 method->client_streaming() ? "request_iterator" : "request";
Nathaniel Manista45479402016-06-13 20:14:18 +0000568 out->Print("\n");
Masood Malekghassemiac592452016-07-01 11:58:04 -0700569 out->Print("def $Method$(self, $ArgName$, context):\n", "Method",
570 method->name(), "ArgName", arg_name);
Nathaniel Manista45479402016-06-13 20:14:18 +0000571 {
572 IndentScope raii_method_indent(out);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700573 PrintAllComments(method);
Nathaniel Manista45479402016-06-13 20:14:18 +0000574 out->Print("context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n");
575 out->Print("context.set_details('Method not implemented!')\n");
576 out->Print("raise NotImplementedError('Method not implemented!')\n");
577 }
578 }
579 }
580 return true;
581}
582
Masood Malekghassemid9539592016-10-20 14:47:14 -0700583bool PrivateGenerator::PrintAddServicerToServer(
Masood Malekghassemiac592452016-07-01 11:58:04 -0700584 const grpc::string& package_qualified_service_name,
Masood Malekghassemid9539592016-10-20 14:47:14 -0700585 const ServiceDescriptor* service) {
Nathaniel Manista45479402016-06-13 20:14:18 +0000586 out->Print("\n\n");
587 out->Print("def add_$Service$Servicer_to_server(servicer, server):\n",
Masood Malekghassemiac592452016-07-01 11:58:04 -0700588 "Service", service->name());
Nathaniel Manista45479402016-06-13 20:14:18 +0000589 {
590 IndentScope raii_class_indent(out);
591 out->Print("rpc_method_handlers = {\n");
592 {
593 IndentScope raii_dict_first_indent(out);
594 IndentScope raii_dict_second_indent(out);
595 for (int i = 0; i < service->method_count(); ++i) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700596 const MethodDescriptor* method = service->method(i);
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700597 grpc::string method_handler_constructor =
Nathaniel Manista45479402016-06-13 20:14:18 +0000598 grpc::string(method->client_streaming() ? "stream" : "unary") +
Masood Malekghassemiac592452016-07-01 11:58:04 -0700599 "_" +
Nathaniel Manista45479402016-06-13 20:14:18 +0000600 grpc::string(method->server_streaming() ? "stream" : "unary") +
601 "_rpc_method_handler";
Masood Malekghassemiac592452016-07-01 11:58:04 -0700602 grpc::string request_module_and_class;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700603 if (!GetModuleAndMessagePath(method->input_type(),
Masood Malekghassemiac592452016-07-01 11:58:04 -0700604 &request_module_and_class)) {
Nathaniel Manista45479402016-06-13 20:14:18 +0000605 return false;
Masood Malekghassemiac592452016-07-01 11:58:04 -0700606 }
607 grpc::string response_module_and_class;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700608 if (!GetModuleAndMessagePath(method->output_type(),
Masood Malekghassemiac592452016-07-01 11:58:04 -0700609 &response_module_and_class)) {
610 return false;
611 }
612 out->Print("'$Method$': grpc.$MethodHandlerConstructor$(\n", "Method",
613 method->name(), "MethodHandlerConstructor",
614 method_handler_constructor);
615 {
Nathaniel Manista45479402016-06-13 20:14:18 +0000616 IndentScope raii_call_first_indent(out);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700617 IndentScope raii_call_second_indent(out);
618 out->Print("servicer.$Method$,\n", "Method", method->name());
619 out->Print(
620 "request_deserializer=$RequestModuleAndClass$.FromString,\n",
621 "RequestModuleAndClass", request_module_and_class);
622 out->Print(
623 "response_serializer=$ResponseModuleAndClass$.SerializeToString,"
624 "\n",
625 "ResponseModuleAndClass", response_module_and_class);
626 }
627 out->Print("),\n");
Nathaniel Manista45479402016-06-13 20:14:18 +0000628 }
629 }
630 out->Print("}\n");
631 out->Print("generic_handler = grpc.method_handlers_generic_handler(\n");
632 {
633 IndentScope raii_call_first_indent(out);
634 IndentScope raii_call_second_indent(out);
635 out->Print("'$PackageQualifiedServiceName$', rpc_method_handlers)\n",
Masood Malekghassemiac592452016-07-01 11:58:04 -0700636 "PackageQualifiedServiceName", package_qualified_service_name);
Nathaniel Manista45479402016-06-13 20:14:18 +0000637 }
638 out->Print("server.add_generic_rpc_handlers((generic_handler,))\n");
639 }
640 return true;
641}
642
Masood Malekghassemid9539592016-10-20 14:47:14 -0700643bool PrivateGenerator::PrintBetaPreamble() {
Nathaniel Manistaf65d3c12015-09-05 03:55:19 +0000644 out->Print("from $Package$ import implementations as beta_implementations\n",
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000645 "Package", config.beta_package_root);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700646 out->Print("from $Package$ import interfaces as beta_interfaces\n", "Package",
647 config.beta_package_root);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700648 return true;
649}
650
651bool PrivateGenerator::PrintPreamble() {
652 out->Print("import $Package$\n", "Package", config.grpc_package_root);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000653 out->Print("from grpc.framework.common import cardinality\n");
Masood Malekghassemiac592452016-07-01 11:58:04 -0700654 out->Print(
655 "from grpc.framework.interfaces.face import utilities as "
656 "face_utilities\n");
Masood Malekghassemid9539592016-10-20 14:47:14 -0700657 if (generate_in_pb2_grpc) {
658 out->Print("\n");
Bryan Blanchardc549a3e2016-12-13 07:46:28 -0500659 StringPairSet imports_set;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700660 for (int i = 0; i < file->service_count(); ++i) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700661 const ServiceDescriptor* service = file->service(i);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700662 for (int j = 0; j < service->method_count(); ++j) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700663 const MethodDescriptor* method = service->method(j);
664 const Descriptor* types[2] = {method->input_type(),
665 method->output_type()};
Masood Malekghassemid9539592016-10-20 14:47:14 -0700666 for (int k = 0; k < 2; ++k) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700667 const Descriptor* type = types[k];
Masood Malekghassemid9539592016-10-20 14:47:14 -0700668 grpc::string type_file_name = type->file()->name();
669 grpc::string module_name = ModuleName(type_file_name);
670 grpc::string module_alias = ModuleAlias(type_file_name);
Bryan Blanchardc549a3e2016-12-13 07:46:28 -0500671 imports_set.insert(std::make_tuple(module_name, module_alias));
Masood Malekghassemid9539592016-10-20 14:47:14 -0700672 }
673 }
674 }
Bryan Blanchardc549a3e2016-12-13 07:46:28 -0500675 for (StringPairSet::iterator it = imports_set.begin();
676 it != imports_set.end(); ++it) {
677 out->Print("import $ModuleName$ as $ModuleAlias$\n", "ModuleName",
678 std::get<0>(*it), "ModuleAlias", std::get<1>(*it));
679 }
Masood Malekghassemid9539592016-10-20 14:47:14 -0700680 }
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800681 return true;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800682}
683
Masood Malekghassemid9539592016-10-20 14:47:14 -0700684bool PrivateGenerator::PrintGAServices() {
685 grpc::string package = file->package();
686 if (!package.empty()) {
687 package = package.append(".");
688 }
689 for (int i = 0; i < file->service_count(); ++i) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700690 const ServiceDescriptor* service = file->service(i);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700691 grpc::string package_qualified_service_name = package + service->name();
692 if (!(PrintStub(package_qualified_service_name, service) &&
693 PrintServicer(service) &&
694 PrintAddServicerToServer(package_qualified_service_name, service))) {
695 return false;
696 }
697 }
698 return true;
699}
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800700
Masood Malekghassemid9539592016-10-20 14:47:14 -0700701bool PrivateGenerator::PrintBetaServices() {
702 grpc::string package = file->package();
703 if (!package.empty()) {
704 package = package.append(".");
705 }
706 for (int i = 0; i < file->service_count(); ++i) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700707 const ServiceDescriptor* service = file->service(i);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700708 grpc::string package_qualified_service_name = package + service->name();
709 if (!(PrintBetaServicer(service) && PrintBetaStub(service) &&
710 PrintBetaServerFactory(package_qualified_service_name, service) &&
711 PrintBetaStubFactory(package_qualified_service_name, service))) {
712 return false;
713 }
714 }
715 return true;
716}
717
718pair<bool, grpc::string> PrivateGenerator::GetGrpcServices() {
Masood Malekghassemi65c803b2015-03-20 06:48:47 -0700719 grpc::string output;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800720 {
721 // Scope the output stream so it closes and finalizes output to the string.
722 StringOutputStream output_stream(&output);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700723 Printer out_printer(&output_stream, '$');
724 out = &out_printer;
725
726 if (generate_in_pb2_grpc) {
727 if (!PrintPreamble()) {
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800728 return make_pair(false, "");
729 }
Masood Malekghassemid9539592016-10-20 14:47:14 -0700730 if (!PrintGAServices()) {
731 return make_pair(false, "");
732 }
733 } else {
734 out->Print("try:\n");
735 {
736 IndentScope raii_dict_try_indent(out);
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700737 out->Print(
738 "# THESE ELEMENTS WILL BE DEPRECATED.\n"
739 "# Please use the generated *_pb2_grpc.py files instead.\n");
Masood Malekghassemid9539592016-10-20 14:47:14 -0700740 if (!PrintPreamble()) {
741 return make_pair(false, "");
742 }
743 if (!PrintBetaPreamble()) {
744 return make_pair(false, "");
745 }
746 if (!PrintGAServices()) {
747 return make_pair(false, "");
748 }
749 if (!PrintBetaServices()) {
750 return make_pair(false, "");
751 }
752 }
753 out->Print("except ImportError:\n");
754 {
755 IndentScope raii_dict_except_indent(out);
756 out->Print("pass");
757 }
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800758 }
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800759 }
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800760 return make_pair(true, std::move(output));
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800761}
762
Masood Malekghassemid9539592016-10-20 14:47:14 -0700763} // namespace
764
765GeneratorConfiguration::GeneratorConfiguration()
766 : grpc_package_root("grpc"), beta_package_root("grpc.beta") {}
767
768PythonGrpcGenerator::PythonGrpcGenerator(const GeneratorConfiguration& config)
769 : config_(config) {}
770
771PythonGrpcGenerator::~PythonGrpcGenerator() {}
772
Masood Malekghassemi561dce42016-11-30 20:20:32 -0800773static bool GenerateGrpc(GeneratorContext* context, PrivateGenerator& generator,
774 grpc::string file_name, bool generate_in_pb2_grpc) {
775 bool success;
776 std::unique_ptr<ZeroCopyOutputStream> output;
777 std::unique_ptr<CodedOutputStream> coded_output;
778 grpc::string grpc_code;
779
780 if (generate_in_pb2_grpc) {
781 output.reset(context->Open(file_name));
782 generator.generate_in_pb2_grpc = true;
783 } else {
784 output.reset(context->OpenForInsert(file_name, "module_scope"));
785 generator.generate_in_pb2_grpc = false;
786 }
787
788 coded_output.reset(new CodedOutputStream(output.get()));
789 tie(success, grpc_code) = generator.GetGrpcServices();
790
791 if (success) {
792 coded_output->WriteRaw(grpc_code.data(), grpc_code.size());
793 return true;
794 } else {
795 return false;
796 }
797}
798
Masood Malekghassemid9539592016-10-20 14:47:14 -0700799bool PythonGrpcGenerator::Generate(const FileDescriptor* file,
800 const grpc::string& parameter,
801 GeneratorContext* context,
802 grpc::string* error) const {
803 // Get output file name.
804 grpc::string pb2_file_name;
805 grpc::string pb2_grpc_file_name;
806 static const int proto_suffix_length = strlen(".proto");
807 if (file->name().size() > static_cast<size_t>(proto_suffix_length) &&
808 file->name().find_last_of(".proto") == file->name().size() - 1) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700809 grpc::string base =
810 file->name().substr(0, file->name().size() - proto_suffix_length);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700811 pb2_file_name = base + "_pb2.py";
812 pb2_grpc_file_name = base + "_pb2_grpc.py";
813 } else {
814 *error = "Invalid proto file name. Proto file must end with .proto";
815 return false;
816 }
817
818 PrivateGenerator generator(config_, file);
Masood Malekghassemi561dce42016-11-30 20:20:32 -0800819 if (parameter == "grpc_2_0") {
820 return GenerateGrpc(context, generator, pb2_grpc_file_name, true);
821 } else if (parameter == "") {
822 return GenerateGrpc(context, generator, pb2_grpc_file_name, true) &&
823 GenerateGrpc(context, generator, pb2_file_name, false);
824 } else {
825 *error = "Invalid parameter '" + parameter + "'.";
826 return false;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700827 }
Masood Malekghassemid9539592016-10-20 14:47:14 -0700828}
829
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800830} // namespace grpc_python_generator