blob: b0a60092ab1549d19343fcda31580139f56e8035 [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>
43#include <sstream>
Masood Malekghassemi3bb52152015-03-17 21:52:52 -070044#include <tuple>
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -080045#include <vector>
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080046
Masood Malekghassemi65c803b2015-03-20 06:48:47 -070047#include "src/compiler/config.h"
Nicolas "Pixel" Noble93fa0982015-02-27 21:50:58 +010048#include "src/compiler/generator_helpers.h"
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080049#include "src/compiler/python_generator.h"
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080050
Nicolas "Pixel" Noble93fa0982015-02-27 21:50:58 +010051using grpc_generator::StringReplace;
52using grpc_generator::StripProto;
Masood Malekghassemi65c803b2015-03-20 06:48:47 -070053using grpc::protobuf::Descriptor;
54using grpc::protobuf::FileDescriptor;
55using grpc::protobuf::MethodDescriptor;
56using grpc::protobuf::ServiceDescriptor;
57using grpc::protobuf::compiler::GeneratorContext;
58using grpc::protobuf::io::CodedOutputStream;
59using grpc::protobuf::io::Printer;
60using grpc::protobuf::io::StringOutputStream;
61using grpc::protobuf::io::ZeroCopyOutputStream;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080062using std::initializer_list;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -080063using std::make_pair;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080064using std::map;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -080065using std::pair;
Masood Malekghassemi40e8cbd2015-02-26 08:39:50 -080066using std::replace;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -080067using std::vector;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080068
69namespace grpc_python_generator {
Masood Malekghassemi3bb52152015-03-17 21:52:52 -070070
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080071namespace {
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080072
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -070073typedef vector<const Descriptor*> DescriptorVector;
74typedef map<grpc::string, grpc::string> StringMap;
75typedef vector<grpc::string> StringVector;
76
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080077// Provides RAII indentation handling. Use as:
78// {
79// IndentScope raii_my_indent_var_name_here(my_py_printer);
80// // constructor indented my_py_printer
81// ...
82// // destructor called at end of scope, un-indenting my_py_printer
83// }
84class IndentScope {
85 public:
86 explicit IndentScope(Printer* printer) : printer_(printer) {
87 printer_->Indent();
88 }
89
Masood Malekghassemiac592452016-07-01 11:58:04 -070090 ~IndentScope() { printer_->Outdent(); }
Masood Malekghassemif8e297a2015-02-19 15:39:32 -080091
92 private:
93 Printer* printer_;
94};
95
Ken Paysonbe187b02016-05-06 15:32:58 -070096// TODO(https://github.com/google/protobuf/issues/888):
97// Export `ModuleName` from protobuf's
Masood Malekghassemi40e8cbd2015-02-26 08:39:50 -080098// `src/google/protobuf/compiler/python/python_generator.cc` file.
Masood Malekghassemi65c803b2015-03-20 06:48:47 -070099grpc::string ModuleName(const grpc::string& filename) {
100 grpc::string basename = StripProto(filename);
Nicolas "Pixel" Noble93fa0982015-02-27 21:50:58 +0100101 basename = StringReplace(basename, "-", "_");
102 basename = StringReplace(basename, "/", ".");
Masood Malekghassemi40e8cbd2015-02-26 08:39:50 -0800103 return basename + "_pb2";
104}
105
Ken Paysonbe187b02016-05-06 15:32:58 -0700106// TODO(https://github.com/google/protobuf/issues/888):
107// Export `ModuleAlias` from protobuf's
108// `src/google/protobuf/compiler/python/python_generator.cc` file.
109grpc::string ModuleAlias(const grpc::string& filename) {
110 grpc::string module_name = ModuleName(filename);
111 // We can't have dots in the module name, so we replace each with _dot_.
112 // But that could lead to a collision between a.b and a_dot_b, so we also
113 // duplicate each underscore.
114 module_name = StringReplace(module_name, "_", "__");
115 module_name = StringReplace(module_name, ".", "_dot_");
116 return module_name;
117}
118
Masood Malekghassemid9539592016-10-20 14:47:14 -0700119// Tucks all generator state in an anonymous namespace away from
120// PythonGrpcGenerator and the header file, mostly to encourage future changes
121// to not require updates to the grpcio-tools C++ code part. Assumes that it is
122// only ever used from a single thread.
123struct PrivateGenerator {
124 const GeneratorConfiguration& config;
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700125 const FileDescriptor* file;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700126
127 bool generate_in_pb2_grpc;
128
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700129 Printer* out;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700130
131 PrivateGenerator(const GeneratorConfiguration& config,
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700132 const FileDescriptor* file);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700133
134 std::pair<bool, grpc::string> GetGrpcServices();
135
136 private:
137 bool PrintPreamble();
138 bool PrintBetaPreamble();
139 bool PrintGAServices();
140 bool PrintBetaServices();
141
142 bool PrintAddServicerToServer(
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700143 const grpc::string& package_qualified_service_name,
144 const ServiceDescriptor* service);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700145 bool PrintServicer(const ServiceDescriptor* service);
146 bool PrintStub(const grpc::string& package_qualified_service_name,
147 const ServiceDescriptor* service);
148
149 bool PrintBetaServicer(const ServiceDescriptor* service);
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700150 bool PrintBetaServerFactory(
Masood Malekghassemid9539592016-10-20 14:47:14 -0700151 const grpc::string& package_qualified_service_name,
152 const ServiceDescriptor* service);
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700153 bool PrintBetaStub(const ServiceDescriptor* service);
154 bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
155 const ServiceDescriptor* service);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700156
157 // Get all comments (leading, leading_detached, trailing) and print them as a
158 // docstring. Any leading space of a line will be removed, but the line
159 // wrapping will not be changed.
160 template <typename DescriptorType>
161 void PrintAllComments(const DescriptorType* descriptor);
162
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700163 bool GetModuleAndMessagePath(const Descriptor* type, grpc::string* out);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700164};
165
Masood Malekghassemid9539592016-10-20 14:47:14 -0700166PrivateGenerator::PrivateGenerator(const GeneratorConfiguration& config,
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700167 const FileDescriptor* file)
168 : config(config), file(file) {}
Masood Malekghassemid9539592016-10-20 14:47:14 -0700169
170bool PrivateGenerator::GetModuleAndMessagePath(const Descriptor* type,
171 grpc::string* out) {
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800172 const Descriptor* path_elem_type = type;
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700173 DescriptorVector message_path;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800174 do {
175 message_path.push_back(path_elem_type);
176 path_elem_type = path_elem_type->containing_type();
Masood Malekghassemiac592452016-07-01 11:58:04 -0700177 } while (path_elem_type); // implicit nullptr comparison; don't be explicit
Masood Malekghassemi65c803b2015-03-20 06:48:47 -0700178 grpc::string file_name = type->file()->name();
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800179 static const int proto_suffix_length = strlen(".proto");
180 if (!(file_name.size() > static_cast<size_t>(proto_suffix_length) &&
181 file_name.find_last_of(".proto") == file_name.size() - 1)) {
182 return false;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800183 }
Masood Malekghassemid9539592016-10-20 14:47:14 -0700184 grpc::string generator_file_name = file->name();
185 grpc::string module;
186 if (generator_file_name != file_name || generate_in_pb2_grpc) {
187 module = ModuleAlias(file_name) + ".";
188 } else {
189 module = "";
190 }
Masood Malekghassemi65c803b2015-03-20 06:48:47 -0700191 grpc::string message_type;
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700192 for (DescriptorVector::reverse_iterator path_iter = message_path.rbegin();
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700193 path_iter != message_path.rend(); ++path_iter) {
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800194 message_type += (*path_iter)->name() + ".";
195 }
Craig Tillercf133f42015-02-26 14:05:56 -0800196 // no pop_back prior to C++11
197 message_type.resize(message_type.size() - 1);
Ken Paysonbe187b02016-05-06 15:32:58 -0700198 *out = module + message_type;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800199 return true;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800200}
201
yang-gb0de7162016-05-03 15:48:19 -0700202template <typename DescriptorType>
Masood Malekghassemid9539592016-10-20 14:47:14 -0700203void PrivateGenerator::PrintAllComments(const DescriptorType* descriptor) {
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700204 StringVector comments;
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700205 grpc_generator::GetComment(
206 descriptor, grpc_generator::COMMENTTYPE_LEADING_DETACHED, &comments);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700207 grpc_generator::GetComment(descriptor, grpc_generator::COMMENTTYPE_LEADING,
yang-gb0de7162016-05-03 15:48:19 -0700208 &comments);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700209 grpc_generator::GetComment(descriptor, grpc_generator::COMMENTTYPE_TRAILING,
yang-gb0de7162016-05-03 15:48:19 -0700210 &comments);
211 if (comments.empty()) {
212 return;
213 }
Masood Malekghassemid9539592016-10-20 14:47:14 -0700214 out->Print("\"\"\"");
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700215 for (StringVector::iterator it = comments.begin(); it != comments.end();
216 ++it) {
yang-gb0de7162016-05-03 15:48:19 -0700217 size_t start_pos = it->find_first_not_of(' ');
218 if (start_pos != grpc::string::npos) {
Masood Malekghassemid9539592016-10-20 14:47:14 -0700219 out->Print(it->c_str() + start_pos);
yang-gb0de7162016-05-03 15:48:19 -0700220 }
Masood Malekghassemid9539592016-10-20 14:47:14 -0700221 out->Print("\n");
yang-gb0de7162016-05-03 15:48:19 -0700222 }
Masood Malekghassemid9539592016-10-20 14:47:14 -0700223 out->Print("\"\"\"\n");
yang-gb0de7162016-05-03 15:48:19 -0700224}
225
Masood Malekghassemid9539592016-10-20 14:47:14 -0700226bool PrivateGenerator::PrintBetaServicer(const ServiceDescriptor* service) {
Ken Paysonbe187b02016-05-06 15:32:58 -0700227 out->Print("\n\n");
yang-gb0de7162016-05-03 15:48:19 -0700228 out->Print("class Beta$Service$Servicer(object):\n", "Service",
229 service->name());
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000230 {
231 IndentScope raii_class_indent(out);
Nicolas "Pixel" Noblebeeeddd2016-09-29 20:27:23 +0200232 out->Print(
233 "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
234 "\nIt is recommended to use the GA API (classes and functions in this\n"
235 "file not marked beta) for all further purposes. This class was "
236 "generated\n"
237 "only to ease transition from grpcio<0.15.0 to "
238 "grpcio>=0.15.0.\"\"\"\n");
Masood Malekghassemid9539592016-10-20 14:47:14 -0700239 PrintAllComments(service);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000240 for (int i = 0; i < service->method_count(); ++i) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700241 const MethodDescriptor* method = service->method(i);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700242 grpc::string arg_name =
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700243 method->client_streaming() ? "request_iterator" : "request";
Masood Malekghassemiac592452016-07-01 11:58:04 -0700244 out->Print("def $Method$(self, $ArgName$, context):\n", "Method",
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700245 method->name(), "ArgName", arg_name);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000246 {
247 IndentScope raii_method_indent(out);
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700248 PrintAllComments(method);
Masood Malekghassemi832ae812016-04-27 18:38:54 -0700249 out->Print("context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)\n");
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000250 }
251 }
252 }
253 return true;
254}
255
Masood Malekghassemid9539592016-10-20 14:47:14 -0700256bool PrivateGenerator::PrintBetaStub(const ServiceDescriptor* service) {
Ken Paysonbe187b02016-05-06 15:32:58 -0700257 out->Print("\n\n");
yang-gb0de7162016-05-03 15:48:19 -0700258 out->Print("class Beta$Service$Stub(object):\n", "Service", service->name());
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000259 {
260 IndentScope raii_class_indent(out);
Nicolas "Pixel" Noblebeeeddd2016-09-29 20:27:23 +0200261 out->Print(
262 "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
263 "\nIt is recommended to use the GA API (classes and functions in this\n"
264 "file not marked beta) for all further purposes. This class was "
265 "generated\n"
266 "only to ease transition from grpcio<0.15.0 to "
267 "grpcio>=0.15.0.\"\"\"\n");
Masood Malekghassemid9539592016-10-20 14:47:14 -0700268 PrintAllComments(service);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000269 for (int i = 0; i < service->method_count(); ++i) {
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700270 const MethodDescriptor* method = service->method(i);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700271 grpc::string arg_name =
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700272 method->client_streaming() ? "request_iterator" : "request";
273 StringMap method_dict;
274 method_dict["Method"] = method->name();
275 method_dict["ArgName"] = arg_name;
276 out->Print(method_dict,
Masood Malekghassemiac592452016-07-01 11:58:04 -0700277 "def $Method$(self, $ArgName$, timeout, metadata=None, "
278 "with_call=False, protocol_options=None):\n");
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000279 {
280 IndentScope raii_method_indent(out);
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700281 PrintAllComments(method);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000282 out->Print("raise NotImplementedError()\n");
283 }
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700284 if (!method->server_streaming()) {
285 out->Print(method_dict, "$Method$.future = None\n");
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000286 }
287 }
288 }
289 return true;
290}
291
Masood Malekghassemid9539592016-10-20 14:47:14 -0700292bool PrivateGenerator::PrintBetaServerFactory(
293 const grpc::string& package_qualified_service_name,
294 const ServiceDescriptor* service) {
Ken Paysonbe187b02016-05-06 15:32:58 -0700295 out->Print("\n\n");
Masood Malekghassemiac592452016-07-01 11:58:04 -0700296 out->Print(
297 "def beta_create_$Service$_server(servicer, pool=None, "
298 "pool_size=None, default_timeout=None, maximum_timeout=None):\n",
299 "Service", service->name());
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000300 {
301 IndentScope raii_create_server_indent(out);
Nicolas "Pixel" Noblebeeeddd2016-09-29 20:27:23 +0200302 out->Print(
303 "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
304 "\nIt is recommended to use the GA API (classes and functions in this\n"
305 "file not marked beta) for all further purposes. This function was\n"
306 "generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"
307 "\"\"\"\n");
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700308 StringMap method_implementation_constructors;
309 StringMap input_message_modules_and_classes;
310 StringMap output_message_modules_and_classes;
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000311 for (int i = 0; i < service->method_count(); ++i) {
312 const MethodDescriptor* method = service->method(i);
313 const grpc::string method_implementation_constructor =
314 grpc::string(method->client_streaming() ? "stream_" : "unary_") +
315 grpc::string(method->server_streaming() ? "stream_" : "unary_") +
316 "inline";
Ken Paysonbe187b02016-05-06 15:32:58 -0700317 grpc::string input_message_module_and_class;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700318 if (!GetModuleAndMessagePath(method->input_type(),
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000319 &input_message_module_and_class)) {
320 return false;
321 }
Ken Paysonbe187b02016-05-06 15:32:58 -0700322 grpc::string output_message_module_and_class;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700323 if (!GetModuleAndMessagePath(method->output_type(),
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000324 &output_message_module_and_class)) {
325 return false;
326 }
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000327 method_implementation_constructors.insert(
328 make_pair(method->name(), method_implementation_constructor));
329 input_message_modules_and_classes.insert(
330 make_pair(method->name(), input_message_module_and_class));
331 output_message_modules_and_classes.insert(
332 make_pair(method->name(), output_message_module_and_class));
333 }
334 out->Print("request_deserializers = {\n");
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700335 for (StringMap::iterator name_and_input_module_class_pair =
Masood Malekghassemiac592452016-07-01 11:58:04 -0700336 input_message_modules_and_classes.begin();
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000337 name_and_input_module_class_pair !=
Masood Malekghassemiac592452016-07-01 11:58:04 -0700338 input_message_modules_and_classes.end();
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000339 name_and_input_module_class_pair++) {
340 IndentScope raii_indent(out);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700341 out->Print(
342 "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
343 "$InputTypeModuleAndClass$.FromString,\n",
344 "PackageQualifiedServiceName", package_qualified_service_name,
345 "MethodName", name_and_input_module_class_pair->first,
346 "InputTypeModuleAndClass", name_and_input_module_class_pair->second);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000347 }
348 out->Print("}\n");
349 out->Print("response_serializers = {\n");
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700350 for (StringMap::iterator name_and_output_module_class_pair =
Masood Malekghassemiac592452016-07-01 11:58:04 -0700351 output_message_modules_and_classes.begin();
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000352 name_and_output_module_class_pair !=
Masood Malekghassemiac592452016-07-01 11:58:04 -0700353 output_message_modules_and_classes.end();
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000354 name_and_output_module_class_pair++) {
355 IndentScope raii_indent(out);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700356 out->Print(
357 "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
358 "$OutputTypeModuleAndClass$.SerializeToString,\n",
359 "PackageQualifiedServiceName", package_qualified_service_name,
360 "MethodName", name_and_output_module_class_pair->first,
361 "OutputTypeModuleAndClass",
362 name_and_output_module_class_pair->second);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000363 }
364 out->Print("}\n");
365 out->Print("method_implementations = {\n");
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700366 for (StringMap::iterator name_and_implementation_constructor =
Masood Malekghassemiac592452016-07-01 11:58:04 -0700367 method_implementation_constructors.begin();
368 name_and_implementation_constructor !=
369 method_implementation_constructors.end();
370 name_and_implementation_constructor++) {
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000371 IndentScope raii_descriptions_indent(out);
372 const grpc::string method_name =
373 name_and_implementation_constructor->first;
Masood Malekghassemiac592452016-07-01 11:58:04 -0700374 out->Print(
375 "(\'$PackageQualifiedServiceName$\', \'$Method$\'): "
376 "face_utilities.$Constructor$(servicer.$Method$),\n",
377 "PackageQualifiedServiceName", package_qualified_service_name,
378 "Method", name_and_implementation_constructor->first, "Constructor",
379 name_and_implementation_constructor->second);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000380 }
381 out->Print("}\n");
Masood Malekghassemiac592452016-07-01 11:58:04 -0700382 out->Print(
383 "server_options = beta_implementations.server_options("
384 "request_deserializers=request_deserializers, "
385 "response_serializers=response_serializers, "
386 "thread_pool=pool, thread_pool_size=pool_size, "
387 "default_timeout=default_timeout, "
388 "maximum_timeout=maximum_timeout)\n");
389 out->Print(
390 "return beta_implementations.server(method_implementations, "
391 "options=server_options)\n");
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000392 }
393 return true;
394}
395
Masood Malekghassemid9539592016-10-20 14:47:14 -0700396bool PrivateGenerator::PrintBetaStubFactory(
397 const grpc::string& package_qualified_service_name,
398 const ServiceDescriptor* service) {
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700399 StringMap dict;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700400 dict["Service"] = service->name();
Ken Paysonbe187b02016-05-06 15:32:58 -0700401 out->Print("\n\n");
Masood Malekghassemiac592452016-07-01 11:58:04 -0700402 out->Print(dict,
403 "def beta_create_$Service$_stub(channel, host=None,"
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000404 " metadata_transformer=None, pool=None, pool_size=None):\n");
405 {
406 IndentScope raii_create_server_indent(out);
Nicolas "Pixel" Noblebeeeddd2016-09-29 20:27:23 +0200407 out->Print(
408 "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
409 "\nIt is recommended to use the GA API (classes and functions in this\n"
410 "file not marked beta) for all further purposes. This function was\n"
411 "generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"
412 "\"\"\"\n");
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700413 StringMap method_cardinalities;
414 StringMap input_message_modules_and_classes;
415 StringMap output_message_modules_and_classes;
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000416 for (int i = 0; i < service->method_count(); ++i) {
417 const MethodDescriptor* method = service->method(i);
418 const grpc::string method_cardinality =
Masood Malekghassemiac592452016-07-01 11:58:04 -0700419 grpc::string(method->client_streaming() ? "STREAM" : "UNARY") + "_" +
Ken Paysonbe187b02016-05-06 15:32:58 -0700420 grpc::string(method->server_streaming() ? "STREAM" : "UNARY");
421 grpc::string input_message_module_and_class;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700422 if (!GetModuleAndMessagePath(method->input_type(),
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000423 &input_message_module_and_class)) {
424 return false;
425 }
Ken Paysonbe187b02016-05-06 15:32:58 -0700426 grpc::string output_message_module_and_class;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700427 if (!GetModuleAndMessagePath(method->output_type(),
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000428 &output_message_module_and_class)) {
429 return false;
430 }
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000431 method_cardinalities.insert(
432 make_pair(method->name(), method_cardinality));
433 input_message_modules_and_classes.insert(
434 make_pair(method->name(), input_message_module_and_class));
435 output_message_modules_and_classes.insert(
436 make_pair(method->name(), output_message_module_and_class));
437 }
438 out->Print("request_serializers = {\n");
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700439 for (StringMap::iterator name_and_input_module_class_pair =
Masood Malekghassemiac592452016-07-01 11:58:04 -0700440 input_message_modules_and_classes.begin();
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000441 name_and_input_module_class_pair !=
Masood Malekghassemiac592452016-07-01 11:58:04 -0700442 input_message_modules_and_classes.end();
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000443 name_and_input_module_class_pair++) {
444 IndentScope raii_indent(out);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700445 out->Print(
446 "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
447 "$InputTypeModuleAndClass$.SerializeToString,\n",
448 "PackageQualifiedServiceName", package_qualified_service_name,
449 "MethodName", name_and_input_module_class_pair->first,
450 "InputTypeModuleAndClass", name_and_input_module_class_pair->second);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000451 }
452 out->Print("}\n");
453 out->Print("response_deserializers = {\n");
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700454 for (StringMap::iterator name_and_output_module_class_pair =
Masood Malekghassemiac592452016-07-01 11:58:04 -0700455 output_message_modules_and_classes.begin();
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000456 name_and_output_module_class_pair !=
Masood Malekghassemiac592452016-07-01 11:58:04 -0700457 output_message_modules_and_classes.end();
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000458 name_and_output_module_class_pair++) {
459 IndentScope raii_indent(out);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700460 out->Print(
461 "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
462 "$OutputTypeModuleAndClass$.FromString,\n",
463 "PackageQualifiedServiceName", package_qualified_service_name,
464 "MethodName", name_and_output_module_class_pair->first,
465 "OutputTypeModuleAndClass",
466 name_and_output_module_class_pair->second);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000467 }
468 out->Print("}\n");
469 out->Print("cardinalities = {\n");
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700470 for (StringMap::iterator name_and_cardinality =
471 method_cardinalities.begin();
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000472 name_and_cardinality != method_cardinalities.end();
473 name_and_cardinality++) {
474 IndentScope raii_descriptions_indent(out);
475 out->Print("\'$Method$\': cardinality.Cardinality.$Cardinality$,\n",
Masood Malekghassemiac592452016-07-01 11:58:04 -0700476 "Method", name_and_cardinality->first, "Cardinality",
477 name_and_cardinality->second);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000478 }
479 out->Print("}\n");
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000480 out->Print(
Masood Malekghassemiac592452016-07-01 11:58:04 -0700481 "stub_options = beta_implementations.stub_options("
482 "host=host, metadata_transformer=metadata_transformer, "
483 "request_serializers=request_serializers, "
484 "response_deserializers=response_deserializers, "
485 "thread_pool=pool, thread_pool_size=pool_size)\n");
486 out->Print(
487 "return beta_implementations.dynamic_stub(channel, "
488 "\'$PackageQualifiedServiceName$\', "
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000489 "cardinalities, options=stub_options)\n",
490 "PackageQualifiedServiceName", package_qualified_service_name);
491 }
492 return true;
493}
494
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700495bool PrivateGenerator::PrintStub(
496 const grpc::string& package_qualified_service_name,
497 const ServiceDescriptor* service) {
Nathaniel Manista45479402016-06-13 20:14:18 +0000498 out->Print("\n\n");
499 out->Print("class $Service$Stub(object):\n", "Service", service->name());
500 {
501 IndentScope raii_class_indent(out);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700502 PrintAllComments(service);
Nathaniel Manista45479402016-06-13 20:14:18 +0000503 out->Print("\n");
504 out->Print("def __init__(self, channel):\n");
505 {
506 IndentScope raii_init_indent(out);
507 out->Print("\"\"\"Constructor.\n");
508 out->Print("\n");
509 out->Print("Args:\n");
510 {
511 IndentScope raii_args_indent(out);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700512 out->Print("channel: A grpc.Channel.\n");
Nathaniel Manista45479402016-06-13 20:14:18 +0000513 }
514 out->Print("\"\"\"\n");
515 for (int i = 0; i < service->method_count(); ++i) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700516 const MethodDescriptor* method = service->method(i);
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700517 grpc::string multi_callable_constructor =
Masood Malekghassemiac592452016-07-01 11:58:04 -0700518 grpc::string(method->client_streaming() ? "stream" : "unary") +
519 "_" + grpc::string(method->server_streaming() ? "stream" : "unary");
520 grpc::string request_module_and_class;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700521 if (!GetModuleAndMessagePath(method->input_type(),
Masood Malekghassemiac592452016-07-01 11:58:04 -0700522 &request_module_and_class)) {
Nathaniel Manista45479402016-06-13 20:14:18 +0000523 return false;
Masood Malekghassemiac592452016-07-01 11:58:04 -0700524 }
525 grpc::string response_module_and_class;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700526 if (!GetModuleAndMessagePath(method->output_type(),
Masood Malekghassemiac592452016-07-01 11:58:04 -0700527 &response_module_and_class)) {
528 return false;
529 }
530 out->Print("self.$Method$ = channel.$MultiCallableConstructor$(\n",
531 "Method", method->name(), "MultiCallableConstructor",
532 multi_callable_constructor);
533 {
Nathaniel Manista45479402016-06-13 20:14:18 +0000534 IndentScope raii_first_attribute_indent(out);
535 IndentScope raii_second_attribute_indent(out);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700536 out->Print("'/$PackageQualifiedService$/$Method$',\n",
537 "PackageQualifiedService", package_qualified_service_name,
538 "Method", method->name());
539 out->Print(
540 "request_serializer=$RequestModuleAndClass$.SerializeToString,\n",
541 "RequestModuleAndClass", request_module_and_class);
542 out->Print(
Nathaniel Manista45479402016-06-13 20:14:18 +0000543 "response_deserializer=$ResponseModuleAndClass$.FromString,\n",
Masood Malekghassemiac592452016-07-01 11:58:04 -0700544 "ResponseModuleAndClass", response_module_and_class);
545 out->Print(")\n");
546 }
Nathaniel Manista45479402016-06-13 20:14:18 +0000547 }
548 }
549 }
550 return true;
551}
552
Masood Malekghassemid9539592016-10-20 14:47:14 -0700553bool PrivateGenerator::PrintServicer(const ServiceDescriptor* service) {
Nathaniel Manista45479402016-06-13 20:14:18 +0000554 out->Print("\n\n");
555 out->Print("class $Service$Servicer(object):\n", "Service", service->name());
556 {
557 IndentScope raii_class_indent(out);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700558 PrintAllComments(service);
Nathaniel Manista45479402016-06-13 20:14:18 +0000559 for (int i = 0; i < service->method_count(); ++i) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700560 const MethodDescriptor* method = service->method(i);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700561 grpc::string arg_name =
562 method->client_streaming() ? "request_iterator" : "request";
Nathaniel Manista45479402016-06-13 20:14:18 +0000563 out->Print("\n");
Masood Malekghassemiac592452016-07-01 11:58:04 -0700564 out->Print("def $Method$(self, $ArgName$, context):\n", "Method",
565 method->name(), "ArgName", arg_name);
Nathaniel Manista45479402016-06-13 20:14:18 +0000566 {
567 IndentScope raii_method_indent(out);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700568 PrintAllComments(method);
Nathaniel Manista45479402016-06-13 20:14:18 +0000569 out->Print("context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n");
570 out->Print("context.set_details('Method not implemented!')\n");
571 out->Print("raise NotImplementedError('Method not implemented!')\n");
572 }
573 }
574 }
575 return true;
576}
577
Masood Malekghassemid9539592016-10-20 14:47:14 -0700578bool PrivateGenerator::PrintAddServicerToServer(
Masood Malekghassemiac592452016-07-01 11:58:04 -0700579 const grpc::string& package_qualified_service_name,
Masood Malekghassemid9539592016-10-20 14:47:14 -0700580 const ServiceDescriptor* service) {
Nathaniel Manista45479402016-06-13 20:14:18 +0000581 out->Print("\n\n");
582 out->Print("def add_$Service$Servicer_to_server(servicer, server):\n",
Masood Malekghassemiac592452016-07-01 11:58:04 -0700583 "Service", service->name());
Nathaniel Manista45479402016-06-13 20:14:18 +0000584 {
585 IndentScope raii_class_indent(out);
586 out->Print("rpc_method_handlers = {\n");
587 {
588 IndentScope raii_dict_first_indent(out);
589 IndentScope raii_dict_second_indent(out);
590 for (int i = 0; i < service->method_count(); ++i) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700591 const MethodDescriptor* method = service->method(i);
Masood Malekghassemi4a051cc2016-10-20 14:50:49 -0700592 grpc::string method_handler_constructor =
Nathaniel Manista45479402016-06-13 20:14:18 +0000593 grpc::string(method->client_streaming() ? "stream" : "unary") +
Masood Malekghassemiac592452016-07-01 11:58:04 -0700594 "_" +
Nathaniel Manista45479402016-06-13 20:14:18 +0000595 grpc::string(method->server_streaming() ? "stream" : "unary") +
596 "_rpc_method_handler";
Masood Malekghassemiac592452016-07-01 11:58:04 -0700597 grpc::string request_module_and_class;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700598 if (!GetModuleAndMessagePath(method->input_type(),
Masood Malekghassemiac592452016-07-01 11:58:04 -0700599 &request_module_and_class)) {
Nathaniel Manista45479402016-06-13 20:14:18 +0000600 return false;
Masood Malekghassemiac592452016-07-01 11:58:04 -0700601 }
602 grpc::string response_module_and_class;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700603 if (!GetModuleAndMessagePath(method->output_type(),
Masood Malekghassemiac592452016-07-01 11:58:04 -0700604 &response_module_and_class)) {
605 return false;
606 }
607 out->Print("'$Method$': grpc.$MethodHandlerConstructor$(\n", "Method",
608 method->name(), "MethodHandlerConstructor",
609 method_handler_constructor);
610 {
Nathaniel Manista45479402016-06-13 20:14:18 +0000611 IndentScope raii_call_first_indent(out);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700612 IndentScope raii_call_second_indent(out);
613 out->Print("servicer.$Method$,\n", "Method", method->name());
614 out->Print(
615 "request_deserializer=$RequestModuleAndClass$.FromString,\n",
616 "RequestModuleAndClass", request_module_and_class);
617 out->Print(
618 "response_serializer=$ResponseModuleAndClass$.SerializeToString,"
619 "\n",
620 "ResponseModuleAndClass", response_module_and_class);
621 }
622 out->Print("),\n");
Nathaniel Manista45479402016-06-13 20:14:18 +0000623 }
624 }
625 out->Print("}\n");
626 out->Print("generic_handler = grpc.method_handlers_generic_handler(\n");
627 {
628 IndentScope raii_call_first_indent(out);
629 IndentScope raii_call_second_indent(out);
630 out->Print("'$PackageQualifiedServiceName$', rpc_method_handlers)\n",
Masood Malekghassemiac592452016-07-01 11:58:04 -0700631 "PackageQualifiedServiceName", package_qualified_service_name);
Nathaniel Manista45479402016-06-13 20:14:18 +0000632 }
633 out->Print("server.add_generic_rpc_handlers((generic_handler,))\n");
634 }
635 return true;
636}
637
Masood Malekghassemid9539592016-10-20 14:47:14 -0700638bool PrivateGenerator::PrintBetaPreamble() {
Nathaniel Manistaf65d3c12015-09-05 03:55:19 +0000639 out->Print("from $Package$ import implementations as beta_implementations\n",
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000640 "Package", config.beta_package_root);
Masood Malekghassemiac592452016-07-01 11:58:04 -0700641 out->Print("from $Package$ import interfaces as beta_interfaces\n", "Package",
642 config.beta_package_root);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700643 return true;
644}
645
646bool PrivateGenerator::PrintPreamble() {
647 out->Print("import $Package$\n", "Package", config.grpc_package_root);
Nathaniel Manistacd9ec0e2015-08-31 07:49:45 +0000648 out->Print("from grpc.framework.common import cardinality\n");
Masood Malekghassemiac592452016-07-01 11:58:04 -0700649 out->Print(
650 "from grpc.framework.interfaces.face import utilities as "
651 "face_utilities\n");
Masood Malekghassemid9539592016-10-20 14:47:14 -0700652 if (generate_in_pb2_grpc) {
653 out->Print("\n");
654 for (int i = 0; i < file->service_count(); ++i) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700655 const ServiceDescriptor* service = file->service(i);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700656 for (int j = 0; j < service->method_count(); ++j) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700657 const MethodDescriptor* method = service->method(j);
658 const Descriptor* types[2] = {method->input_type(),
659 method->output_type()};
Masood Malekghassemid9539592016-10-20 14:47:14 -0700660 for (int k = 0; k < 2; ++k) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700661 const Descriptor* type = types[k];
Masood Malekghassemid9539592016-10-20 14:47:14 -0700662 grpc::string type_file_name = type->file()->name();
663 grpc::string module_name = ModuleName(type_file_name);
664 grpc::string module_alias = ModuleAlias(type_file_name);
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700665 out->Print("import $ModuleName$ as $ModuleAlias$\n", "ModuleName",
666 module_name, "ModuleAlias", module_alias);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700667 }
668 }
669 }
670 }
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800671 return true;
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800672}
673
Masood Malekghassemid9539592016-10-20 14:47:14 -0700674bool PrivateGenerator::PrintGAServices() {
675 grpc::string package = file->package();
676 if (!package.empty()) {
677 package = package.append(".");
678 }
679 for (int i = 0; i < file->service_count(); ++i) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700680 const ServiceDescriptor* service = file->service(i);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700681 grpc::string package_qualified_service_name = package + service->name();
682 if (!(PrintStub(package_qualified_service_name, service) &&
683 PrintServicer(service) &&
684 PrintAddServicerToServer(package_qualified_service_name, service))) {
685 return false;
686 }
687 }
688 return true;
689}
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800690
Masood Malekghassemid9539592016-10-20 14:47:14 -0700691bool PrivateGenerator::PrintBetaServices() {
692 grpc::string package = file->package();
693 if (!package.empty()) {
694 package = package.append(".");
695 }
696 for (int i = 0; i < file->service_count(); ++i) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700697 const ServiceDescriptor* service = file->service(i);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700698 grpc::string package_qualified_service_name = package + service->name();
699 if (!(PrintBetaServicer(service) && PrintBetaStub(service) &&
700 PrintBetaServerFactory(package_qualified_service_name, service) &&
701 PrintBetaStubFactory(package_qualified_service_name, service))) {
702 return false;
703 }
704 }
705 return true;
706}
707
708pair<bool, grpc::string> PrivateGenerator::GetGrpcServices() {
Masood Malekghassemi65c803b2015-03-20 06:48:47 -0700709 grpc::string output;
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800710 {
711 // Scope the output stream so it closes and finalizes output to the string.
712 StringOutputStream output_stream(&output);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700713 Printer out_printer(&output_stream, '$');
714 out = &out_printer;
715
716 if (generate_in_pb2_grpc) {
717 if (!PrintPreamble()) {
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800718 return make_pair(false, "");
719 }
Masood Malekghassemid9539592016-10-20 14:47:14 -0700720 if (!PrintGAServices()) {
721 return make_pair(false, "");
722 }
723 } else {
724 out->Print("try:\n");
725 {
726 IndentScope raii_dict_try_indent(out);
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700727 out->Print(
728 "# THESE ELEMENTS WILL BE DEPRECATED.\n"
729 "# Please use the generated *_pb2_grpc.py files instead.\n");
Masood Malekghassemid9539592016-10-20 14:47:14 -0700730 if (!PrintPreamble()) {
731 return make_pair(false, "");
732 }
733 if (!PrintBetaPreamble()) {
734 return make_pair(false, "");
735 }
736 if (!PrintGAServices()) {
737 return make_pair(false, "");
738 }
739 if (!PrintBetaServices()) {
740 return make_pair(false, "");
741 }
742 }
743 out->Print("except ImportError:\n");
744 {
745 IndentScope raii_dict_except_indent(out);
746 out->Print("pass");
747 }
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800748 }
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800749 }
Masood Malekghassemi59d9ff42015-02-23 15:28:07 -0800750 return make_pair(true, std::move(output));
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800751}
752
Masood Malekghassemid9539592016-10-20 14:47:14 -0700753} // namespace
754
755GeneratorConfiguration::GeneratorConfiguration()
756 : grpc_package_root("grpc"), beta_package_root("grpc.beta") {}
757
758PythonGrpcGenerator::PythonGrpcGenerator(const GeneratorConfiguration& config)
759 : config_(config) {}
760
761PythonGrpcGenerator::~PythonGrpcGenerator() {}
762
Masood Malekghassemi561dce42016-11-30 20:20:32 -0800763static bool GenerateGrpc(GeneratorContext* context, PrivateGenerator& generator,
764 grpc::string file_name, bool generate_in_pb2_grpc) {
765 bool success;
766 std::unique_ptr<ZeroCopyOutputStream> output;
767 std::unique_ptr<CodedOutputStream> coded_output;
768 grpc::string grpc_code;
769
770 if (generate_in_pb2_grpc) {
771 output.reset(context->Open(file_name));
772 generator.generate_in_pb2_grpc = true;
773 } else {
774 output.reset(context->OpenForInsert(file_name, "module_scope"));
775 generator.generate_in_pb2_grpc = false;
776 }
777
778 coded_output.reset(new CodedOutputStream(output.get()));
779 tie(success, grpc_code) = generator.GetGrpcServices();
780
781 if (success) {
782 coded_output->WriteRaw(grpc_code.data(), grpc_code.size());
783 return true;
784 } else {
785 return false;
786 }
787}
788
Masood Malekghassemid9539592016-10-20 14:47:14 -0700789bool PythonGrpcGenerator::Generate(const FileDescriptor* file,
790 const grpc::string& parameter,
791 GeneratorContext* context,
792 grpc::string* error) const {
793 // Get output file name.
794 grpc::string pb2_file_name;
795 grpc::string pb2_grpc_file_name;
796 static const int proto_suffix_length = strlen(".proto");
797 if (file->name().size() > static_cast<size_t>(proto_suffix_length) &&
798 file->name().find_last_of(".proto") == file->name().size() - 1) {
Masood Malekghassemi7780cc02016-10-24 15:30:05 -0700799 grpc::string base =
800 file->name().substr(0, file->name().size() - proto_suffix_length);
Masood Malekghassemid9539592016-10-20 14:47:14 -0700801 pb2_file_name = base + "_pb2.py";
802 pb2_grpc_file_name = base + "_pb2_grpc.py";
803 } else {
804 *error = "Invalid proto file name. Proto file must end with .proto";
805 return false;
806 }
807
808 PrivateGenerator generator(config_, file);
Masood Malekghassemi561dce42016-11-30 20:20:32 -0800809 if (parameter == "grpc_2_0") {
810 return GenerateGrpc(context, generator, pb2_grpc_file_name, true);
811 } else if (parameter == "") {
812 return GenerateGrpc(context, generator, pb2_grpc_file_name, true) &&
813 GenerateGrpc(context, generator, pb2_file_name, false);
814 } else {
815 *error = "Invalid parameter '" + parameter + "'.";
816 return false;
Masood Malekghassemid9539592016-10-20 14:47:14 -0700817 }
Masood Malekghassemid9539592016-10-20 14:47:14 -0700818}
819
Masood Malekghassemif8e297a2015-02-19 15:39:32 -0800820} // namespace grpc_python_generator