59 typedef map<std::string, std::string> StringMap;
60 typedef vector<std::string> StringVector;
61 typedef tuple<std::string, std::string> StringPair;
62 typedef set<StringPair> StringPairSet;
89 PrivateGenerator::PrivateGenerator(
const GeneratorConfiguration&
config,
93 void PrivateGenerator::PrintAllComments(StringVector comments,
95 if (comments.empty()) {
103 "\"\"\"Missing associated documentation comment in .proto "
107 out->Print(
"\"\"\"");
110 size_t start_pos =
it->find_first_not_of(
' ');
111 if (start_pos != std::string::npos) {
112 out->PrintRaw(
it->c_str() + start_pos);
116 out->Print(
"\"\"\"\n");
121 StringMap service_dict;
122 service_dict[
"Service"] =
service->name();
124 out->Print(service_dict,
"class Beta$Service$Servicer(object):\n");
126 IndentScope raii_class_indent(
out);
128 "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
129 "\nIt is recommended to use the GA API (classes and functions in this\n"
130 "file not marked beta) for all further purposes. This class was "
132 "only to ease transition from grpcio<0.15.0 to "
133 "grpcio>=0.15.0.\"\"\"\n");
134 StringVector service_comments =
service->GetAllComments();
135 PrintAllComments(service_comments,
out);
136 for (
int i = 0;
i <
service->method_count(); ++
i) {
139 method->ClientStreaming() ?
"request_iterator" :
"request";
140 StringMap method_dict;
141 method_dict[
"Method"] =
method->name();
142 method_dict[
"ArgName"] = arg_name;
143 out->Print(method_dict,
"def $Method$(self, $ArgName$, context):\n");
145 IndentScope raii_method_indent(
out);
146 StringVector method_comments =
method->GetAllComments();
147 PrintAllComments(method_comments,
out);
148 out->Print(
"context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)\n");
157 StringMap service_dict;
158 service_dict[
"Service"] =
service->name();
160 out->Print(service_dict,
"class Beta$Service$Stub(object):\n");
162 IndentScope raii_class_indent(
out);
164 "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
165 "\nIt is recommended to use the GA API (classes and functions in this\n"
166 "file not marked beta) for all further purposes. This class was "
168 "only to ease transition from grpcio<0.15.0 to "
169 "grpcio>=0.15.0.\"\"\"\n");
170 StringVector service_comments =
service->GetAllComments();
171 PrintAllComments(service_comments,
out);
172 for (
int i = 0;
i <
service->method_count(); ++
i) {
175 method->ClientStreaming() ?
"request_iterator" :
"request";
176 StringMap method_dict;
177 method_dict[
"Method"] =
method->name();
178 method_dict[
"ArgName"] = arg_name;
179 out->Print(method_dict,
180 "def $Method$(self, $ArgName$, timeout, metadata=None, "
181 "with_call=False, protocol_options=None):\n");
183 IndentScope raii_method_indent(
out);
184 StringVector method_comments =
method->GetAllComments();
185 PrintAllComments(method_comments,
out);
186 out->Print(
"raise NotImplementedError()\n");
188 if (!
method->ServerStreaming()) {
189 out->Print(method_dict,
"$Method$.future = None\n");
196 bool PrivateGenerator::PrintBetaServerFactory(
199 StringMap service_dict;
200 service_dict[
"Service"] =
service->name();
202 out->Print(service_dict,
203 "def beta_create_$Service$_server(servicer, pool=None, "
204 "pool_size=None, default_timeout=None, maximum_timeout=None):\n");
206 IndentScope raii_create_server_indent(
out);
208 "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
209 "\nIt is recommended to use the GA API (classes and functions in this\n"
210 "file not marked beta) for all further purposes. This function was\n"
211 "generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"
213 StringMap method_implementation_constructors;
214 StringMap input_message_modules_and_classes;
215 StringMap output_message_modules_and_classes;
216 for (
int i = 0;
i <
service->method_count(); ++
i) {
218 const std::string method_implementation_constructor =
223 if (!
method->get_module_and_message_path_input(
226 config.prefixes_to_filter)) {
230 if (!
method->get_module_and_message_path_output(
233 config.prefixes_to_filter)) {
236 method_implementation_constructors.insert(
237 make_pair(
method->name(), method_implementation_constructor));
238 input_message_modules_and_classes.insert(
239 make_pair(
method->name(), input_message_module_and_class));
240 output_message_modules_and_classes.insert(
241 make_pair(
method->name(), output_message_module_and_class));
243 StringMap method_dict;
244 method_dict[
"PackageQualifiedServiceName"] = package_qualified_service_name;
245 out->Print(
"request_deserializers = {\n");
247 input_message_modules_and_classes.begin();
248 name_and_input_module_class_pair !=
249 input_message_modules_and_classes.end();
250 name_and_input_module_class_pair++) {
251 method_dict[
"MethodName"] = name_and_input_module_class_pair->first;
252 method_dict[
"InputTypeModuleAndClass"] =
253 name_and_input_module_class_pair->second;
254 IndentScope raii_indent(
out);
255 out->Print(method_dict,
256 "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
257 "$InputTypeModuleAndClass$.FromString,\n");
260 out->Print(
"response_serializers = {\n");
262 output_message_modules_and_classes.begin();
263 name_and_output_module_class_pair !=
264 output_message_modules_and_classes.end();
265 name_and_output_module_class_pair++) {
266 method_dict[
"MethodName"] = name_and_output_module_class_pair->first;
267 method_dict[
"OutputTypeModuleAndClass"] =
268 name_and_output_module_class_pair->second;
269 IndentScope raii_indent(
out);
270 out->Print(method_dict,
271 "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
272 "$OutputTypeModuleAndClass$.SerializeToString,\n");
275 out->Print(
"method_implementations = {\n");
277 method_implementation_constructors.begin();
278 name_and_implementation_constructor !=
279 method_implementation_constructors.end();
280 name_and_implementation_constructor++) {
281 method_dict[
"Method"] = name_and_implementation_constructor->first;
282 method_dict[
"Constructor"] = name_and_implementation_constructor->second;
283 IndentScope raii_descriptions_indent(
out);
285 name_and_implementation_constructor->first;
286 out->Print(method_dict,
287 "(\'$PackageQualifiedServiceName$\', \'$Method$\'): "
288 "face_utilities.$Constructor$(servicer.$Method$),\n");
292 "server_options = beta_implementations.server_options("
293 "request_deserializers=request_deserializers, "
294 "response_serializers=response_serializers, "
295 "thread_pool=pool, thread_pool_size=pool_size, "
296 "default_timeout=default_timeout, "
297 "maximum_timeout=maximum_timeout)\n");
299 "return beta_implementations.server(method_implementations, "
300 "options=server_options)\n");
305 bool PrivateGenerator::PrintBetaStubFactory(
309 dict[
"Service"] =
service->name();
312 "def beta_create_$Service$_stub(channel, host=None,"
313 " metadata_transformer=None, pool=None, pool_size=None):\n");
315 IndentScope raii_create_server_indent(
out);
317 "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
318 "\nIt is recommended to use the GA API (classes and functions in this\n"
319 "file not marked beta) for all further purposes. This function was\n"
320 "generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"
322 StringMap method_cardinalities;
323 StringMap input_message_modules_and_classes;
324 StringMap output_message_modules_and_classes;
325 for (
int i = 0;
i <
service->method_count(); ++
i) {
331 if (!
method->get_module_and_message_path_input(
334 config.prefixes_to_filter)) {
338 if (!
method->get_module_and_message_path_output(
341 config.prefixes_to_filter)) {
344 method_cardinalities.insert(
345 make_pair(
method->name(), method_cardinality));
346 input_message_modules_and_classes.insert(
347 make_pair(
method->name(), input_message_module_and_class));
348 output_message_modules_and_classes.insert(
349 make_pair(
method->name(), output_message_module_and_class));
351 StringMap method_dict;
352 method_dict[
"PackageQualifiedServiceName"] = package_qualified_service_name;
353 out->Print(
"request_serializers = {\n");
355 input_message_modules_and_classes.begin();
356 name_and_input_module_class_pair !=
357 input_message_modules_and_classes.end();
358 name_and_input_module_class_pair++) {
359 method_dict[
"MethodName"] = name_and_input_module_class_pair->first;
360 method_dict[
"InputTypeModuleAndClass"] =
361 name_and_input_module_class_pair->second;
362 IndentScope raii_indent(
out);
363 out->Print(method_dict,
364 "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
365 "$InputTypeModuleAndClass$.SerializeToString,\n");
368 out->Print(
"response_deserializers = {\n");
370 output_message_modules_and_classes.begin();
371 name_and_output_module_class_pair !=
372 output_message_modules_and_classes.end();
373 name_and_output_module_class_pair++) {
374 method_dict[
"MethodName"] = name_and_output_module_class_pair->first;
375 method_dict[
"OutputTypeModuleAndClass"] =
376 name_and_output_module_class_pair->second;
377 IndentScope raii_indent(
out);
378 out->Print(method_dict,
379 "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
380 "$OutputTypeModuleAndClass$.FromString,\n");
383 out->Print(
"cardinalities = {\n");
385 method_cardinalities.begin();
386 name_and_cardinality != method_cardinalities.end();
387 name_and_cardinality++) {
388 method_dict[
"Method"] = name_and_cardinality->first;
389 method_dict[
"Cardinality"] = name_and_cardinality->second;
390 IndentScope raii_descriptions_indent(
out);
391 out->Print(method_dict,
392 "\'$Method$\': cardinality.Cardinality.$Cardinality$,\n");
396 "stub_options = beta_implementations.stub_options("
397 "host=host, metadata_transformer=metadata_transformer, "
398 "request_serializers=request_serializers, "
399 "response_deserializers=response_deserializers, "
400 "thread_pool=pool, thread_pool_size=pool_size)\n");
401 out->Print(method_dict,
402 "return beta_implementations.dynamic_stub(channel, "
403 "\'$PackageQualifiedServiceName$\', "
404 "cardinalities, options=stub_options)\n");
409 bool PrivateGenerator::PrintStub(
413 dict[
"Service"] =
service->name();
415 out->Print(dict,
"class $Service$Stub(object):\n");
417 IndentScope raii_class_indent(
out);
418 StringVector service_comments =
service->GetAllComments();
419 PrintAllComments(service_comments,
out);
421 out->Print(
"def __init__(self, channel):\n");
423 IndentScope raii_init_indent(
out);
424 out->Print(
"\"\"\"Constructor.\n");
426 out->Print(
"Args:\n");
428 IndentScope raii_args_indent(
out);
429 out->Print(
"channel: A grpc.Channel.\n");
431 out->Print(
"\"\"\"\n");
432 for (
int i = 0;
i <
service->method_count(); ++
i) {
438 if (!
method->get_module_and_message_path_input(
441 config.prefixes_to_filter)) {
445 if (!
method->get_module_and_message_path_output(
448 config.prefixes_to_filter)) {
451 StringMap method_dict;
452 method_dict[
"Method"] =
method->name();
453 method_dict[
"MultiCallableConstructor"] = multi_callable_constructor;
454 out->Print(method_dict,
455 "self.$Method$ = channel.$MultiCallableConstructor$(\n");
457 method_dict[
"PackageQualifiedService"] =
458 package_qualified_service_name;
459 method_dict[
"RequestModuleAndClass"] = request_module_and_class;
460 method_dict[
"ResponseModuleAndClass"] = response_module_and_class;
461 IndentScope raii_first_attribute_indent(
out);
462 IndentScope raii_second_attribute_indent(
out);
463 out->Print(method_dict,
"'/$PackageQualifiedService$/$Method$',\n");
464 out->Print(method_dict,
465 "request_serializer=$RequestModuleAndClass$."
466 "SerializeToString,\n");
469 "response_deserializer=$ResponseModuleAndClass$.FromString,\n");
480 StringMap service_dict;
481 service_dict[
"Service"] =
service->name();
483 out->Print(service_dict,
"class $Service$Servicer(object):\n");
485 IndentScope raii_class_indent(
out);
486 StringVector service_comments =
service->GetAllComments();
487 PrintAllComments(service_comments,
out);
488 for (
int i = 0;
i <
service->method_count(); ++
i) {
491 method->ClientStreaming() ?
"request_iterator" :
"request";
492 StringMap method_dict;
493 method_dict[
"Method"] =
method->name();
494 method_dict[
"ArgName"] = arg_name;
496 out->Print(method_dict,
"def $Method$(self, $ArgName$, context):\n");
498 IndentScope raii_method_indent(
out);
499 StringVector method_comments =
method->GetAllComments();
500 PrintAllComments(method_comments,
out);
501 out->Print(
"context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n");
502 out->Print(
"context.set_details('Method not implemented!')\n");
503 out->Print(
"raise NotImplementedError('Method not implemented!')\n");
510 bool PrivateGenerator::PrintAddServicerToServer(
513 StringMap service_dict;
514 service_dict[
"Service"] =
service->name();
516 out->Print(service_dict,
517 "def add_$Service$Servicer_to_server(servicer, server):\n");
519 IndentScope raii_class_indent(
out);
520 out->Print(
"rpc_method_handlers = {\n");
522 IndentScope raii_dict_first_indent(
out);
523 IndentScope raii_dict_second_indent(
out);
524 for (
int i = 0;
i <
service->method_count(); ++
i) {
529 "_rpc_method_handler";
531 if (!
method->get_module_and_message_path_input(
534 config.prefixes_to_filter)) {
538 if (!
method->get_module_and_message_path_output(
541 config.prefixes_to_filter)) {
544 StringMap method_dict;
545 method_dict[
"Method"] =
method->name();
546 method_dict[
"MethodHandlerConstructor"] = method_handler_constructor;
547 method_dict[
"RequestModuleAndClass"] = request_module_and_class;
548 method_dict[
"ResponseModuleAndClass"] = response_module_and_class;
549 out->Print(method_dict,
550 "'$Method$': grpc.$MethodHandlerConstructor$(\n");
552 IndentScope raii_call_first_indent(
out);
553 IndentScope raii_call_second_indent(
out);
554 out->Print(method_dict,
"servicer.$Method$,\n");
557 "request_deserializer=$RequestModuleAndClass$.FromString,\n");
560 "response_serializer=$ResponseModuleAndClass$.SerializeToString,"
566 StringMap method_dict;
567 method_dict[
"PackageQualifiedServiceName"] = package_qualified_service_name;
569 out->Print(
"generic_handler = grpc.method_handlers_generic_handler(\n");
571 IndentScope raii_call_first_indent(
out);
572 IndentScope raii_call_second_indent(
out);
573 out->Print(method_dict,
574 "'$PackageQualifiedServiceName$', rpc_method_handlers)\n");
576 out->Print(
"server.add_generic_rpc_handlers((generic_handler,))\n");
586 bool PrivateGenerator::PrintServiceClass(
590 dict[
"Service"] =
service->name();
592 out->Print(
" # This class is part of an EXPERIMENTAL API.\n");
593 out->Print(dict,
"class $Service$(object):\n");
595 IndentScope class_indent(
out);
596 StringVector service_comments =
service->GetAllComments();
597 PrintAllComments(service_comments,
out);
598 for (
int i = 0;
i <
service->method_count(); ++
i) {
601 if (!
method->get_module_and_message_path_input(
604 config.prefixes_to_filter)) {
608 if (!
method->get_module_and_message_path_output(
611 config.prefixes_to_filter)) {
615 StringMap method_dict;
616 method_dict[
"Method"] =
method->name();
617 out->Print(
"@staticmethod\n");
618 out->Print(method_dict,
"def $Method$(");
620 method->ClientStreaming() ?
"request_iterator" :
"request");
622 args_dict[
"RequestParameter"] = request_parameter;
624 IndentScope args_indent(
out);
625 IndentScope args_double_indent(
out);
626 out->Print(args_dict,
"$RequestParameter$,\n");
627 out->Print(
"target,\n");
628 out->Print(
"options=(),\n");
629 out->Print(
"channel_credentials=None,\n");
630 out->Print(
"call_credentials=None,\n");
631 out->Print(
"insecure=False,\n");
632 out->Print(
"compression=None,\n");
633 out->Print(
"wait_for_ready=None,\n");
634 out->Print(
"timeout=None,\n");
635 out->Print(
"metadata=None):\n");
638 IndentScope method_indent(
out);
642 args_dict[
"ArityMethodName"] = arity_method_name;
643 args_dict[
"PackageQualifiedService"] = package_qualified_service_name;
644 args_dict[
"Method"] =
method->name();
645 out->Print(args_dict,
647 "grpc.experimental.$ArityMethodName$($RequestParameter$, "
648 "target, '/$PackageQualifiedService$/$Method$',\n");
650 IndentScope continuation_indent(
out);
651 StringMap serializer_dict;
652 serializer_dict[
"RequestModuleAndClass"] = request_module_and_class;
653 serializer_dict[
"ResponseModuleAndClass"] = response_module_and_class;
654 out->Print(serializer_dict,
655 "$RequestModuleAndClass$.SerializeToString,\n");
656 out->Print(serializer_dict,
"$ResponseModuleAndClass$.FromString,\n");
657 out->Print(
"options, channel_credentials,\n");
659 "insecure, call_credentials, compression, wait_for_ready, "
660 "timeout, metadata)\n");
671 var[
"Package"] =
config.beta_package_root;
673 "from $Package$ import implementations as beta_implementations\n");
674 out->Print(var,
"from $Package$ import interfaces as beta_interfaces\n");
675 out->Print(
"from grpc.framework.common import cardinality\n");
677 "from grpc.framework.interfaces.face import utilities as "
684 var[
"Package"] =
config.grpc_package_root;
685 out->Print(var,
"import $Package$\n");
688 StringPairSet imports_set;
689 for (
int i = 0;
i <
file->service_count(); ++
i) {
691 for (
int j = 0;
j <
service->method_count(); ++
j) {
697 config.prefixes_to_filter);
699 ModuleAlias(input_type_file_name,
config.import_prefix,
700 config.prefixes_to_filter);
707 config.prefixes_to_filter);
709 ModuleAlias(output_type_file_name,
config.import_prefix,
710 config.prefixes_to_filter);
717 it != imports_set.end(); ++
it) {
718 auto module_name = std::get<0>(*
it);
719 var[
"ModuleAlias"] = std::get<1>(*
it);
720 const size_t last_dot_pos = module_name.rfind(
'.');
721 if (last_dot_pos == std::string::npos) {
722 var[
"ImportStatement"] =
"import " + module_name;
724 var[
"ImportStatement"] =
"from " + module_name.substr(0, last_dot_pos) +
726 module_name.substr(last_dot_pos + 1);
728 out->Print(var,
"$ImportStatement$ as $ModuleAlias$\n");
736 if (!package.empty()) {
737 package = package.append(".");
739 for (
int i = 0;
i <
file->service_count(); ++
i) {
741 std::string package_qualified_service_name =
package + service->name();
742 if (!(PrintStub(package_qualified_service_name,
service.get(),
out) &&
744 PrintAddServicerToServer(package_qualified_service_name,
746 PrintServiceClass(package_qualified_service_name,
service.get(),
756 if (!package.empty()) {
757 package = package.append(".");
759 for (
int i = 0;
i <
file->service_count(); ++
i) {
761 std::string package_qualified_service_name =
package + service->name();
762 if (!(PrintBetaServicer(
service.get(),
out) &&
764 PrintBetaServerFactory(package_qualified_service_name,
service.get(),
766 PrintBetaStubFactory(package_qualified_service_name,
service.get(),
774 pair<bool, std::string> PrivateGenerator::GetGrpcServices() {
781 "# Generated by the gRPC Python protocol compiler plugin. "
782 "DO NOT EDIT!\n\"\"\""
783 "Client and server classes corresponding to protobuf-defined "
784 "services.\"\"\"\n");
785 if (!PrintPreamble(
out.get())) {
786 return make_pair(
false,
"");
788 if (!PrintGAServices(
out.get())) {
789 return make_pair(
false,
"");
792 out->Print(
"try:\n");
794 IndentScope raii_dict_try_indent(
out.get());
796 "# THESE ELEMENTS WILL BE DEPRECATED.\n"
797 "# Please use the generated *_pb2_grpc.py files instead.\n");
798 if (!PrintPreamble(
out.get())) {
799 return make_pair(
false,
"");
801 if (!PrintBetaPreamble(
out.get())) {
802 return make_pair(
false,
"");
804 if (!PrintGAServices(
out.get())) {
805 return make_pair(
false,
"");
807 if (!PrintBetaServices(
out.get())) {
808 return make_pair(
false,
"");
811 out->Print(
"except ImportError:\n");
813 IndentScope raii_dict_except_indent(
out.get());
823 GeneratorConfiguration::GeneratorConfiguration()
824 : grpc_package_root(
"grpc"),
825 beta_package_root(
"grpc.beta"),
836 std::unique_ptr<ZeroCopyOutputStream>
output;
837 std::unique_ptr<CodedOutputStream> coded_output;
842 generator.generate_in_pb2_grpc =
true;
844 output.reset(
context->OpenForInsert(file_name,
"module_scope"));
845 generator.generate_in_pb2_grpc =
false;
849 tie(success, grpc_code) = generator.GetGrpcServices();
852 coded_output->WriteRaw(grpc_code.data(), grpc_code.size());
861 std::vector<std::string>* strip_prefixes,
863 std::vector<std::string> comma_delimited_parameters;
865 if (comma_delimited_parameters.size() == 1 &&
866 comma_delimited_parameters[0].empty()) {
868 }
else if (comma_delimited_parameters.size() == 1) {
870 }
else if (comma_delimited_parameters.size() == 2) {
872 std::copy(comma_delimited_parameters.begin() + 1,
873 comma_delimited_parameters.end(),
874 std::back_inserter(*strip_prefixes));
876 *
error =
"--grpc_python_out received too many comma-delimited parameters.";
883 return FEATURE_PROTO3_OPTIONAL;
893 static const int proto_suffix_length = strlen(
".proto");
894 if (
file->
name().size() >
static_cast<size_t>(proto_suffix_length) &&
898 std::replace(
base.begin(),
base.end(),
'-',
'_');
899 pb2_file_name =
base +
"_pb2.py";
900 pb2_grpc_file_name =
base +
"_pb2_grpc.py";
902 *
error =
"Invalid proto file name. Proto file must end with .proto";
912 PrivateGenerator generator(extended_config, &pbfile);
913 if (!success)
return false;