1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc. All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// Author: robinson@google.com (Will Robinson)
32//
33// This module outputs pure-Python protocol message classes that will
34// largely be constructed at runtime via the metaclass in reflection.py.
35// In other words, our job is basically to output a Python equivalent
36// of the C++ *Descriptor objects, and fix up all circular references
37// within these objects.
38//
39// Note that the runtime performance of protocol message classes created in
40// this way is expected to be lousy. The plan is to create an alternate
41// generator that outputs a Python/C extension module that lets
42// performance-minded Python code leverage the fast C++ implementation
43// directly.
44
45#include <google/protobuf/compiler/python/generator.h>
46
47#include <algorithm>
48#include <limits>
49#include <map>
50#include <memory>
51#include <string>
52#include <utility>
53#include <vector>
54
55#include <google/protobuf/stubs/logging.h>
56#include <google/protobuf/stubs/common.h>
57#include <google/protobuf/stubs/strutil.h>
58#include <google/protobuf/stubs/stringprintf.h>
59#include <google/protobuf/stubs/substitute.h>
60#include <google/protobuf/compiler/python/helpers.h>
61#include <google/protobuf/compiler/python/pyi_generator.h>
62#include <google/protobuf/descriptor.h>
63#include <google/protobuf/descriptor.pb.h>
64#include <google/protobuf/io/printer.h>
65#include <google/protobuf/io/zero_copy_stream.h>
66
67namespace google {
68namespace protobuf {
69namespace compiler {
70namespace python {
71
72namespace {
73// Returns the alias we assign to the module of the given .proto filename
74// when importing. See testPackageInitializationImport in
75// net/proto2/python/internal/reflection_test.py
76// to see why we need the alias.
77std::string ModuleAlias(const std::string& filename) {
78 std::string module_name = ModuleName(filename);
79 // We can't have dots in the module name, so we replace each with _dot_.
80 // But that could lead to a collision between a.b and a_dot_b, so we also
81 // duplicate each underscore.
82 GlobalReplaceSubstring(substring: "_", replacement: "__", s: &module_name);
83 GlobalReplaceSubstring(substring: ".", replacement: "_dot_", s: &module_name);
84 return module_name;
85}
86
87// Name of the class attribute where we store the Python
88// descriptor.Descriptor instance for the generated class.
89// Must stay consistent with the _DESCRIPTOR_KEY constant
90// in proto2/public/reflection.py.
91const char kDescriptorKey[] = "DESCRIPTOR";
92
93
94// file output by this generator.
95void PrintTopBoilerplate(io::Printer* printer, const FileDescriptor* file,
96 bool descriptor_proto) {
97 // TODO(robinson): Allow parameterization of Python version?
98 printer->Print(
99 text: "# -*- coding: utf-8 -*-\n"
100 "# Generated by the protocol buffer compiler. DO NOT EDIT!\n"
101 "# source: $filename$\n"
102 "\"\"\"Generated protocol buffer code.\"\"\"\n",
103 args: "filename", args: file->name());
104 printer->Print(
105 text: "from google.protobuf.internal import builder as _builder\n"
106 "from google.protobuf import descriptor as _descriptor\n"
107 "from google.protobuf import descriptor_pool as "
108 "_descriptor_pool\n"
109 "from google.protobuf import symbol_database as "
110 "_symbol_database\n");
111
112 printer->Print(text: "# @@protoc_insertion_point(imports)\n\n");
113 printer->Print(text: "_sym_db = _symbol_database.Default()\n");
114 printer->Print(text: "\n\n");
115}
116
117// Returns a Python literal giving the default value for a field.
118// If the field specifies no explicit default value, we'll return
119// the default default value for the field type (zero for numbers,
120// empty string for strings, empty list for repeated fields, and
121// None for non-repeated, composite fields).
122//
123// TODO(robinson): Unify with code from
124// //compiler/cpp/internal/primitive_field.cc
125// //compiler/cpp/internal/enum_field.cc
126// //compiler/cpp/internal/string_field.cc
127std::string StringifyDefaultValue(const FieldDescriptor& field) {
128 if (field.is_repeated()) {
129 return "[]";
130 }
131
132 switch (field.cpp_type()) {
133 case FieldDescriptor::CPPTYPE_INT32:
134 return StrCat(a: field.default_value_int32());
135 case FieldDescriptor::CPPTYPE_UINT32:
136 return StrCat(a: field.default_value_uint32());
137 case FieldDescriptor::CPPTYPE_INT64:
138 return StrCat(a: field.default_value_int64());
139 case FieldDescriptor::CPPTYPE_UINT64:
140 return StrCat(a: field.default_value_uint64());
141 case FieldDescriptor::CPPTYPE_DOUBLE: {
142 double value = field.default_value_double();
143 if (value == std::numeric_limits<double>::infinity()) {
144 // Python pre-2.6 on Windows does not parse "inf" correctly. However,
145 // a numeric literal that is too big for a double will become infinity.
146 return "1e10000";
147 } else if (value == -std::numeric_limits<double>::infinity()) {
148 // See above.
149 return "-1e10000";
150 } else if (value != value) {
151 // infinity * 0 = nan
152 return "(1e10000 * 0)";
153 } else {
154 return "float(" + SimpleDtoa(value) + ")";
155 }
156 }
157 case FieldDescriptor::CPPTYPE_FLOAT: {
158 float value = field.default_value_float();
159 if (value == std::numeric_limits<float>::infinity()) {
160 // Python pre-2.6 on Windows does not parse "inf" correctly. However,
161 // a numeric literal that is too big for a double will become infinity.
162 return "1e10000";
163 } else if (value == -std::numeric_limits<float>::infinity()) {
164 // See above.
165 return "-1e10000";
166 } else if (value != value) {
167 // infinity - infinity = nan
168 return "(1e10000 * 0)";
169 } else {
170 return "float(" + SimpleFtoa(value) + ")";
171 }
172 }
173 case FieldDescriptor::CPPTYPE_BOOL:
174 return field.default_value_bool() ? "True" : "False";
175 case FieldDescriptor::CPPTYPE_ENUM:
176 return StrCat(a: field.default_value_enum()->number());
177 case FieldDescriptor::CPPTYPE_STRING:
178 return "b\"" + CEscape(src: field.default_value_string()) +
179 (field.type() != FieldDescriptor::TYPE_STRING
180 ? "\""
181 : "\".decode('utf-8')");
182 case FieldDescriptor::CPPTYPE_MESSAGE:
183 return "None";
184 }
185 // (We could add a default case above but then we wouldn't get the nice
186 // compiler warning when a new type is added.)
187 GOOGLE_LOG(FATAL) << "Not reached.";
188 return "";
189}
190
191std::string StringifySyntax(FileDescriptor::Syntax syntax) {
192 switch (syntax) {
193 case FileDescriptor::SYNTAX_PROTO2:
194 return "proto2";
195 case FileDescriptor::SYNTAX_PROTO3:
196 return "proto3";
197 case FileDescriptor::SYNTAX_UNKNOWN:
198 default:
199 GOOGLE_LOG(FATAL) << "Unsupported syntax; this generator only supports proto2 "
200 "and proto3 syntax.";
201 return "";
202 }
203}
204
205} // namespace
206
207Generator::Generator() : file_(nullptr) {}
208
209Generator::~Generator() {}
210
211uint64_t Generator::GetSupportedFeatures() const {
212 return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL;
213}
214
215bool Generator::Generate(const FileDescriptor* file,
216 const std::string& parameter,
217 GeneratorContext* context, std::string* error) const {
218 // -----------------------------------------------------------------
219 // parse generator options
220 bool cpp_generated_lib_linked = false;
221
222 std::vector<std::pair<std::string, std::string> > options;
223 ParseGeneratorParameter(parameter, &options);
224
225 for (int i = 0; i < options.size(); i++) {
226 if (options[i].first == "cpp_generated_lib_linked") {
227 cpp_generated_lib_linked = true;
228 } else if (options[i].first == "pyi_out") {
229 python::PyiGenerator pyi_generator;
230 if (!pyi_generator.Generate(file, parameter: "", generator_context: context, error)) {
231 return false;
232 }
233 } else {
234 *error = "Unknown generator option: " + options[i].first;
235 return false;
236 }
237 }
238
239 // Completely serialize all Generate() calls on this instance. The
240 // thread-safety constraints of the CodeGenerator interface aren't clear so
241 // just be as conservative as possible. It's easier to relax this later if
242 // we need to, but I doubt it will be an issue.
243 // TODO(kenton): The proper thing to do would be to allocate any state on
244 // the stack and use that, so that the Generator class itself does not need
245 // to have any mutable members. Then it is implicitly thread-safe.
246 MutexLock lock(&mutex_);
247 file_ = file;
248
249 std::string filename = GetFileName(file_des: file, suffix: ".py");
250 pure_python_workable_ = !cpp_generated_lib_linked;
251 if (HasPrefixString(str: file->name(), prefix: "google/protobuf/")) {
252 pure_python_workable_ = true;
253 }
254
255 FileDescriptorProto fdp;
256 file_->CopyTo(proto: &fdp);
257 fdp.SerializeToString(output: &file_descriptor_serialized_);
258
259
260 std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
261 GOOGLE_CHECK(output.get());
262 io::Printer printer(output.get(), '$');
263 printer_ = &printer;
264
265 PrintTopBoilerplate(printer: printer_, file: file_, descriptor_proto: GeneratingDescriptorProto());
266 if (pure_python_workable_) {
267 PrintImports();
268 }
269 PrintFileDescriptor();
270 if (pure_python_workable_) {
271 if (GeneratingDescriptorProto()) {
272 printer_->Print(text: "if _descriptor._USE_C_DESCRIPTORS == False:\n");
273 printer_->Indent();
274 // Create enums before message descriptors
275 PrintAllNestedEnumsInFile();
276 PrintMessageDescriptors();
277 FixForeignFieldsInDescriptors();
278 printer_->Outdent();
279 printer_->Print(text: "else:\n");
280 printer_->Indent();
281 }
282 // Find the message descriptors first and then use the message
283 // descriptor to find enums.
284 printer_->Print(
285 text: "_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())\n");
286 if (GeneratingDescriptorProto()) {
287 printer_->Outdent();
288 }
289 }
290 std::string module_name = ModuleName(filename: file->name());
291 printer_->Print(
292 text: "_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, '$module_name$', "
293 "globals())\n",
294 args: "module_name", args: module_name);
295 if (pure_python_workable_) {
296 printer.Print(text: "if _descriptor._USE_C_DESCRIPTORS == False:\n");
297 printer_->Indent();
298
299 // We have to fix up the extensions after the message classes themselves,
300 // since they need to call static RegisterExtension() methods on these
301 // classes.
302 FixForeignFieldsInExtensions();
303 // Descriptor options may have custom extensions. These custom options
304 // can only be successfully parsed after we register corresponding
305 // extensions. Therefore we parse all options again here to recognize
306 // custom options that may be unknown when we define the descriptors.
307 // This does not apply to services because they are not used by extensions.
308 FixAllDescriptorOptions();
309
310 // Set serialized_start and serialized_end.
311 SetSerializedPbInterval();
312
313 printer_->Outdent();
314 }
315 if (HasGenericServices(file)) {
316 printer_->Print(
317 text: "_builder.BuildServices(DESCRIPTOR, '$module_name$', globals())\n",
318 args: "module_name", args: module_name);
319 }
320
321 printer.Print(text: "# @@protoc_insertion_point(module_scope)\n");
322
323 return !printer.failed();
324}
325
326// Prints Python imports for all modules imported by |file|.
327void Generator::PrintImports() const {
328 for (int i = 0; i < file_->dependency_count(); ++i) {
329 const std::string& filename = file_->dependency(index: i)->name();
330
331 std::string module_name = ModuleName(filename);
332 std::string module_alias = ModuleAlias(filename);
333 if (ContainsPythonKeyword(module_name)) {
334 // If the module path contains a Python keyword, we have to quote the
335 // module name and import it using importlib. Otherwise the usual kind of
336 // import statement would result in a syntax error from the presence of
337 // the keyword.
338 printer_->Print(text: "import importlib\n");
339 printer_->Print(text: "$alias$ = importlib.import_module('$name$')\n", args: "alias",
340 args: module_alias, args: "name", args: module_name);
341 } else {
342 int last_dot_pos = module_name.rfind(c: '.');
343 std::string import_statement;
344 if (last_dot_pos == std::string::npos) {
345 // NOTE(petya): this is not tested as it would require a protocol buffer
346 // outside of any package, and I don't think that is easily achievable.
347 import_statement = "import " + module_name;
348 } else {
349 import_statement = "from " + module_name.substr(pos: 0, n: last_dot_pos) +
350 " import " + module_name.substr(pos: last_dot_pos + 1);
351 }
352 printer_->Print(text: "$statement$ as $alias$\n", args: "statement", args: import_statement,
353 args: "alias", args: module_alias);
354 }
355
356 CopyPublicDependenciesAliases(copy_from: module_alias, file: file_->dependency(index: i));
357 }
358 printer_->Print(text: "\n");
359
360 // Print public imports.
361 for (int i = 0; i < file_->public_dependency_count(); ++i) {
362 std::string module_name = ModuleName(filename: file_->public_dependency(index: i)->name());
363 printer_->Print(text: "from $module$ import *\n", args: "module", args: module_name);
364 }
365 printer_->Print(text: "\n");
366}
367
368// Prints the single file descriptor for this file.
369void Generator::PrintFileDescriptor() const {
370 std::map<std::string, std::string> m;
371 m["descriptor_name"] = kDescriptorKey;
372 m["name"] = file_->name();
373 m["package"] = file_->package();
374 m["syntax"] = StringifySyntax(syntax: file_->syntax());
375 m["options"] = OptionsValue(serialized_options: file_->options().SerializeAsString());
376 m["serialized_descriptor"] = strings::CHexEscape(src: file_descriptor_serialized_);
377 if (GeneratingDescriptorProto()) {
378 printer_->Print(text: "if _descriptor._USE_C_DESCRIPTORS == False:\n");
379 printer_->Indent();
380 // Pure python's AddSerializedFile() depend on the generated
381 // descriptor_pb2.py thus we can not use AddSerializedFile() when
382 // generated descriptor.proto for pure python.
383 const char file_descriptor_template[] =
384 "$descriptor_name$ = _descriptor.FileDescriptor(\n"
385 " name='$name$',\n"
386 " package='$package$',\n"
387 " syntax='$syntax$',\n"
388 " serialized_options=$options$,\n"
389 " create_key=_descriptor._internal_create_key,\n";
390 printer_->Print(variables: m, text: file_descriptor_template);
391 printer_->Indent();
392 if (pure_python_workable_) {
393 printer_->Print(text: "serialized_pb=b'$value$'\n", args: "value",
394 args: strings::CHexEscape(src: file_descriptor_serialized_));
395 if (file_->dependency_count() != 0) {
396 printer_->Print(text: ",\ndependencies=[");
397 for (int i = 0; i < file_->dependency_count(); ++i) {
398 std::string module_alias = ModuleAlias(filename: file_->dependency(index: i)->name());
399 printer_->Print(text: "$module_alias$.DESCRIPTOR,", args: "module_alias",
400 args: module_alias);
401 }
402 printer_->Print(text: "]");
403 }
404 if (file_->public_dependency_count() > 0) {
405 printer_->Print(text: ",\npublic_dependencies=[");
406 for (int i = 0; i < file_->public_dependency_count(); ++i) {
407 std::string module_alias =
408 ModuleAlias(filename: file_->public_dependency(index: i)->name());
409 printer_->Print(text: "$module_alias$.DESCRIPTOR,", args: "module_alias",
410 args: module_alias);
411 }
412 printer_->Print(text: "]");
413 }
414 } else {
415 printer_->Print(text: "serialized_pb=''\n");
416 }
417
418 // TODO(falk): Also print options and fix the message_type, enum_type,
419 // service and extension later in the generation.
420
421 printer_->Outdent();
422 printer_->Print(text: ")\n");
423
424 printer_->Outdent();
425 printer_->Print(text: "else:\n");
426 printer_->Indent();
427 }
428 printer_->Print(variables: m,
429 text: "$descriptor_name$ = "
430 "_descriptor_pool.Default().AddSerializedFile(b'$serialized_"
431 "descriptor$')\n");
432 if (GeneratingDescriptorProto()) {
433 printer_->Outdent();
434 }
435 printer_->Print(text: "\n");
436}
437
438// Prints all enums contained in all message types in |file|.
439void Generator::PrintAllNestedEnumsInFile() const {
440 for (int i = 0; i < file_->message_type_count(); ++i) {
441 PrintNestedEnums(descriptor: *file_->message_type(index: i));
442 }
443}
444
445// Prints a Python statement assigning the appropriate module-level
446// enum name to a Python EnumDescriptor object equivalent to
447// enum_descriptor.
448void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const {
449 std::map<std::string, std::string> m;
450 std::string module_level_descriptor_name =
451 ModuleLevelDescriptorName(descriptor: enum_descriptor);
452 m["descriptor_name"] = module_level_descriptor_name;
453 m["name"] = enum_descriptor.name();
454 m["full_name"] = enum_descriptor.full_name();
455 m["file"] = kDescriptorKey;
456 const char enum_descriptor_template[] =
457 "$descriptor_name$ = _descriptor.EnumDescriptor(\n"
458 " name='$name$',\n"
459 " full_name='$full_name$',\n"
460 " filename=None,\n"
461 " file=$file$,\n"
462 " create_key=_descriptor._internal_create_key,\n"
463 " values=[\n";
464 std::string options_string;
465 enum_descriptor.options().SerializeToString(output: &options_string);
466 printer_->Print(variables: m, text: enum_descriptor_template);
467 printer_->Indent();
468 printer_->Indent();
469
470 if (pure_python_workable_) {
471 for (int i = 0; i < enum_descriptor.value_count(); ++i) {
472 PrintEnumValueDescriptor(descriptor: *enum_descriptor.value(index: i));
473 printer_->Print(text: ",\n");
474 }
475 }
476
477 printer_->Outdent();
478 printer_->Print(text: "],\n");
479 printer_->Print(text: "containing_type=None,\n");
480 printer_->Print(text: "serialized_options=$options_value$,\n", args: "options_value",
481 args: OptionsValue(serialized_options: options_string));
482 EnumDescriptorProto edp;
483 printer_->Outdent();
484 printer_->Print(text: ")\n");
485 if (pure_python_workable_) {
486 printer_->Print(text: "_sym_db.RegisterEnumDescriptor($name$)\n", args: "name",
487 args: module_level_descriptor_name);
488 }
489 printer_->Print(text: "\n");
490}
491
492// Recursively prints enums in nested types within descriptor, then
493// prints enums contained at the top level in descriptor.
494void Generator::PrintNestedEnums(const Descriptor& descriptor) const {
495 for (int i = 0; i < descriptor.nested_type_count(); ++i) {
496 PrintNestedEnums(descriptor: *descriptor.nested_type(index: i));
497 }
498
499 for (int i = 0; i < descriptor.enum_type_count(); ++i) {
500 PrintEnum(enum_descriptor: *descriptor.enum_type(index: i));
501 }
502}
503
504// Prints Python equivalents of all Descriptors in |file|.
505void Generator::PrintMessageDescriptors() const {
506 for (int i = 0; i < file_->message_type_count(); ++i) {
507 PrintDescriptor(message_descriptor: *file_->message_type(index: i));
508 printer_->Print(text: "\n");
509 }
510}
511
512void Generator::PrintServiceDescriptors() const {
513 for (int i = 0; i < file_->service_count(); ++i) {
514 PrintServiceDescriptor(descriptor: *file_->service(index: i));
515 }
516}
517
518void Generator::PrintServices() const {
519 for (int i = 0; i < file_->service_count(); ++i) {
520 PrintServiceClass(descriptor: *file_->service(index: i));
521 PrintServiceStub(descriptor: *file_->service(index: i));
522 printer_->Print(text: "\n");
523 }
524}
525
526void Generator::PrintServiceDescriptor(
527 const ServiceDescriptor& descriptor) const {
528 std::map<std::string, std::string> m;
529 m["service_name"] = ModuleLevelServiceDescriptorName(descriptor);
530 m["name"] = descriptor.name();
531 m["file"] = kDescriptorKey;
532 printer_->Print(variables: m, text: "$service_name$ = $file$.services_by_name['$name$']\n");
533}
534
535void Generator::PrintDescriptorKeyAndModuleName(
536 const ServiceDescriptor& descriptor) const {
537 std::string name = ModuleLevelServiceDescriptorName(descriptor);
538 if (!pure_python_workable_) {
539 name = "_descriptor.ServiceDescriptor(full_name='" +
540 descriptor.full_name() + "')";
541 }
542 printer_->Print(text: "$descriptor_key$ = $descriptor_name$,\n", args: "descriptor_key",
543 args: kDescriptorKey, args: "descriptor_name", args: name);
544 std::string module_name = ModuleName(filename: file_->name());
545 printer_->Print(text: "__module__ = '$module_name$'\n", args: "module_name", args: module_name);
546}
547
548void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const {
549 // Print the service.
550 printer_->Print(
551 text: "$class_name$ = service_reflection.GeneratedServiceType("
552 "'$class_name$', (_service.Service,), dict(\n",
553 args: "class_name", args: descriptor.name());
554 printer_->Indent();
555 Generator::PrintDescriptorKeyAndModuleName(descriptor);
556 printer_->Print(text: "))\n\n");
557 printer_->Outdent();
558}
559
560void Generator::PrintServiceStub(const ServiceDescriptor& descriptor) const {
561 // Print the service stub.
562 printer_->Print(
563 text: "$class_name$_Stub = "
564 "service_reflection.GeneratedServiceStubType("
565 "'$class_name$_Stub', ($class_name$,), dict(\n",
566 args: "class_name", args: descriptor.name());
567 printer_->Indent();
568 Generator::PrintDescriptorKeyAndModuleName(descriptor);
569 printer_->Print(text: "))\n\n");
570 printer_->Outdent();
571}
572
573// Prints statement assigning ModuleLevelDescriptorName(message_descriptor)
574// to a Python Descriptor object for message_descriptor.
575//
576// Mutually recursive with PrintNestedDescriptors().
577void Generator::PrintDescriptor(const Descriptor& message_descriptor) const {
578 std::map<std::string, std::string> m;
579 m["name"] = message_descriptor.name();
580 m["full_name"] = message_descriptor.full_name();
581 m["file"] = kDescriptorKey;
582
583 PrintNestedDescriptors(containing_descriptor: message_descriptor);
584
585 printer_->Print(text: "\n");
586 printer_->Print(text: "$descriptor_name$ = _descriptor.Descriptor(\n",
587 args: "descriptor_name",
588 args: ModuleLevelDescriptorName(descriptor: message_descriptor));
589 printer_->Indent();
590 const char required_function_arguments[] =
591 "name='$name$',\n"
592 "full_name='$full_name$',\n"
593 "filename=None,\n"
594 "file=$file$,\n"
595 "containing_type=None,\n"
596 "create_key=_descriptor._internal_create_key,\n";
597 printer_->Print(variables: m, text: required_function_arguments);
598 PrintFieldsInDescriptor(message_descriptor);
599 PrintExtensionsInDescriptor(message_descriptor);
600
601 // Nested types
602 printer_->Print(text: "nested_types=[");
603 for (int i = 0; i < message_descriptor.nested_type_count(); ++i) {
604 const std::string nested_name =
605 ModuleLevelDescriptorName(descriptor: *message_descriptor.nested_type(index: i));
606 printer_->Print(text: "$name$, ", args: "name", args: nested_name);
607 }
608 printer_->Print(text: "],\n");
609
610 // Enum types
611 printer_->Print(text: "enum_types=[\n");
612 printer_->Indent();
613 for (int i = 0; i < message_descriptor.enum_type_count(); ++i) {
614 const std::string descriptor_name =
615 ModuleLevelDescriptorName(descriptor: *message_descriptor.enum_type(index: i));
616 printer_->Print(text: descriptor_name.c_str());
617 printer_->Print(text: ",\n");
618 }
619 printer_->Outdent();
620 printer_->Print(text: "],\n");
621 std::string options_string;
622 message_descriptor.options().SerializeToString(output: &options_string);
623 printer_->Print(
624 text: "serialized_options=$options_value$,\n"
625 "is_extendable=$extendable$,\n"
626 "syntax='$syntax$'",
627 args: "options_value", args: OptionsValue(serialized_options: options_string), args: "extendable",
628 args: message_descriptor.extension_range_count() > 0 ? "True" : "False",
629 args: "syntax", args: StringifySyntax(syntax: message_descriptor.file()->syntax()));
630 printer_->Print(text: ",\n");
631
632 // Extension ranges
633 printer_->Print(text: "extension_ranges=[");
634 for (int i = 0; i < message_descriptor.extension_range_count(); ++i) {
635 const Descriptor::ExtensionRange* range =
636 message_descriptor.extension_range(index: i);
637 printer_->Print(text: "($start$, $end$), ", args: "start", args: StrCat(a: range->start),
638 args: "end", args: StrCat(a: range->end));
639 }
640 printer_->Print(text: "],\n");
641 printer_->Print(text: "oneofs=[\n");
642 printer_->Indent();
643 for (int i = 0; i < message_descriptor.oneof_decl_count(); ++i) {
644 const OneofDescriptor* desc = message_descriptor.oneof_decl(index: i);
645 m.clear();
646 m["name"] = desc->name();
647 m["full_name"] = desc->full_name();
648 m["index"] = StrCat(a: desc->index());
649 options_string = OptionsValue(serialized_options: desc->options().SerializeAsString());
650 if (options_string == "None") {
651 m["serialized_options"] = "";
652 } else {
653 m["serialized_options"] = ", serialized_options=" + options_string;
654 }
655 printer_->Print(variables: m,
656 text: "_descriptor.OneofDescriptor(\n"
657 " name='$name$', full_name='$full_name$',\n"
658 " index=$index$, containing_type=None,\n"
659 " create_key=_descriptor._internal_create_key,\n"
660 "fields=[]$serialized_options$),\n");
661 }
662 printer_->Outdent();
663 printer_->Print(text: "],\n");
664
665 printer_->Outdent();
666 printer_->Print(text: ")\n");
667}
668
669// Prints Python Descriptor objects for all nested types contained in
670// message_descriptor.
671//
672// Mutually recursive with PrintDescriptor().
673void Generator::PrintNestedDescriptors(
674 const Descriptor& containing_descriptor) const {
675 for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) {
676 PrintDescriptor(message_descriptor: *containing_descriptor.nested_type(index: i));
677 }
678}
679
680// Prints all messages in |file|.
681void Generator::PrintMessages() const {
682 for (int i = 0; i < file_->message_type_count(); ++i) {
683 std::vector<std::string> to_register;
684 PrintMessage(message_descriptor: *file_->message_type(index: i), prefix: "", to_register: &to_register, is_nested: false);
685 for (int j = 0; j < to_register.size(); ++j) {
686 printer_->Print(text: "_sym_db.RegisterMessage($name$)\n", args: "name",
687 args: ResolveKeyword(name: to_register[j]));
688 }
689 printer_->Print(text: "\n");
690 }
691}
692
693// Prints a Python class for the given message descriptor. We defer to the
694// metaclass to do almost all of the work of actually creating a useful class.
695// The purpose of this function and its many helper functions above is merely
696// to output a Python version of the descriptors, which the metaclass in
697// reflection.py will use to construct the meat of the class itself.
698//
699// Mutually recursive with PrintNestedMessages().
700// Collect nested message names to_register for the symbol_database.
701void Generator::PrintMessage(const Descriptor& message_descriptor,
702 const std::string& prefix,
703 std::vector<std::string>* to_register,
704 bool is_nested) const {
705 std::string qualified_name;
706 if (is_nested) {
707 if (IsPythonKeyword(name: message_descriptor.name())) {
708 qualified_name =
709 "getattr(" + prefix + ", '" + message_descriptor.name() + "')";
710 } else {
711 qualified_name = prefix + "." + message_descriptor.name();
712 }
713 printer_->Print(
714 text: "'$name$' : _reflection.GeneratedProtocolMessageType('$name$', "
715 "(_message.Message,), {\n",
716 args: "name", args: message_descriptor.name());
717 } else {
718 qualified_name = ResolveKeyword(name: message_descriptor.name());
719 printer_->Print(
720 text: "$qualified_name$ = _reflection.GeneratedProtocolMessageType('$name$', "
721 "(_message.Message,), {\n",
722 args: "qualified_name", args: qualified_name, args: "name", args: message_descriptor.name());
723 }
724 printer_->Indent();
725
726 to_register->push_back(x: qualified_name);
727
728 PrintNestedMessages(containing_descriptor: message_descriptor, prefix: qualified_name, to_register);
729 std::map<std::string, std::string> m;
730 m["descriptor_key"] = kDescriptorKey;
731 if (pure_python_workable_) {
732 m["descriptor_name"] = ModuleLevelDescriptorName(descriptor: message_descriptor);
733 } else {
734 m["descriptor_name"] = "_descriptor.Descriptor(full_name='" +
735 message_descriptor.full_name() + "')";
736 }
737 printer_->Print(variables: m, text: "'$descriptor_key$' : $descriptor_name$,\n");
738 std::string module_name = ModuleName(filename: file_->name());
739 printer_->Print(text: "'__module__' : '$module_name$'\n", args: "module_name",
740 args: module_name);
741 printer_->Print(text: "# @@protoc_insertion_point(class_scope:$full_name$)\n",
742 args: "full_name", args: message_descriptor.full_name());
743 printer_->Print(text: "})\n");
744 printer_->Outdent();
745}
746
747// Prints all nested messages within |containing_descriptor|.
748// Mutually recursive with PrintMessage().
749void Generator::PrintNestedMessages(
750 const Descriptor& containing_descriptor, const std::string& prefix,
751 std::vector<std::string>* to_register) const {
752 for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) {
753 printer_->Print(text: "\n");
754 PrintMessage(message_descriptor: *containing_descriptor.nested_type(index: i), prefix, to_register,
755 is_nested: true);
756 printer_->Print(text: ",\n");
757 }
758}
759
760// Recursively fixes foreign fields in all nested types in |descriptor|, then
761// sets the message_type and enum_type of all message and enum fields to point
762// to their respective descriptors.
763// Args:
764// descriptor: descriptor to print fields for.
765// containing_descriptor: if descriptor is a nested type, this is its
766// containing type, or NULL if this is a root/top-level type.
767void Generator::FixForeignFieldsInDescriptor(
768 const Descriptor& descriptor,
769 const Descriptor* containing_descriptor) const {
770 for (int i = 0; i < descriptor.nested_type_count(); ++i) {
771 FixForeignFieldsInDescriptor(descriptor: *descriptor.nested_type(index: i), containing_descriptor: &descriptor);
772 }
773
774 for (int i = 0; i < descriptor.field_count(); ++i) {
775 const FieldDescriptor& field_descriptor = *descriptor.field(index: i);
776 FixForeignFieldsInField(containing_type: &descriptor, field: field_descriptor, python_dict_name: "fields_by_name");
777 }
778
779 FixContainingTypeInDescriptor(descriptor, containing_descriptor);
780 for (int i = 0; i < descriptor.enum_type_count(); ++i) {
781 const EnumDescriptor& enum_descriptor = *descriptor.enum_type(index: i);
782 FixContainingTypeInDescriptor(descriptor: enum_descriptor, containing_descriptor: &descriptor);
783 }
784 for (int i = 0; i < descriptor.oneof_decl_count(); ++i) {
785 std::map<std::string, std::string> m;
786 const OneofDescriptor* oneof = descriptor.oneof_decl(index: i);
787 m["descriptor_name"] = ModuleLevelDescriptorName(descriptor);
788 m["oneof_name"] = oneof->name();
789 for (int j = 0; j < oneof->field_count(); ++j) {
790 m["field_name"] = oneof->field(index: j)->name();
791 printer_->Print(
792 variables: m,
793 text: "$descriptor_name$.oneofs_by_name['$oneof_name$'].fields.append(\n"
794 " $descriptor_name$.fields_by_name['$field_name$'])\n");
795 printer_->Print(
796 variables: m,
797 text: "$descriptor_name$.fields_by_name['$field_name$'].containing_oneof = "
798 "$descriptor_name$.oneofs_by_name['$oneof_name$']\n");
799 }
800 }
801}
802
803void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const {
804 std::map<std::string, std::string> m;
805 m["descriptor_name"] = kDescriptorKey;
806 m["message_name"] = descriptor.name();
807 m["message_descriptor_name"] = ModuleLevelDescriptorName(descriptor);
808 const char file_descriptor_template[] =
809 "$descriptor_name$.message_types_by_name['$message_name$'] = "
810 "$message_descriptor_name$\n";
811 printer_->Print(variables: m, text: file_descriptor_template);
812}
813
814void Generator::AddServiceToFileDescriptor(
815 const ServiceDescriptor& descriptor) const {
816 std::map<std::string, std::string> m;
817 m["descriptor_name"] = kDescriptorKey;
818 m["service_name"] = descriptor.name();
819 m["service_descriptor_name"] = ModuleLevelServiceDescriptorName(descriptor);
820 const char file_descriptor_template[] =
821 "$descriptor_name$.services_by_name['$service_name$'] = "
822 "$service_descriptor_name$\n";
823 printer_->Print(variables: m, text: file_descriptor_template);
824}
825
826void Generator::AddEnumToFileDescriptor(
827 const EnumDescriptor& descriptor) const {
828 std::map<std::string, std::string> m;
829 m["descriptor_name"] = kDescriptorKey;
830 m["enum_name"] = descriptor.name();
831 m["enum_descriptor_name"] = ModuleLevelDescriptorName(descriptor);
832 const char file_descriptor_template[] =
833 "$descriptor_name$.enum_types_by_name['$enum_name$'] = "
834 "$enum_descriptor_name$\n";
835 printer_->Print(variables: m, text: file_descriptor_template);
836}
837
838void Generator::AddExtensionToFileDescriptor(
839 const FieldDescriptor& descriptor) const {
840 std::map<std::string, std::string> m;
841 m["descriptor_name"] = kDescriptorKey;
842 m["field_name"] = descriptor.name();
843 m["resolved_name"] = ResolveKeyword(name: descriptor.name());
844 const char file_descriptor_template[] =
845 "$descriptor_name$.extensions_by_name['$field_name$'] = "
846 "$resolved_name$\n";
847 printer_->Print(variables: m, text: file_descriptor_template);
848}
849
850// Sets any necessary message_type and enum_type attributes
851// for the Python version of |field|.
852//
853// containing_type may be NULL, in which case this is a module-level field.
854//
855// python_dict_name is the name of the Python dict where we should
856// look the field up in the containing type. (e.g., fields_by_name
857// or extensions_by_name). We ignore python_dict_name if containing_type
858// is NULL.
859void Generator::FixForeignFieldsInField(
860 const Descriptor* containing_type, const FieldDescriptor& field,
861 const std::string& python_dict_name) const {
862 const std::string field_referencing_expression =
863 FieldReferencingExpression(containing_type, field, python_dict_name);
864 std::map<std::string, std::string> m;
865 m["field_ref"] = field_referencing_expression;
866 const Descriptor* foreign_message_type = field.message_type();
867 if (foreign_message_type) {
868 m["foreign_type"] = ModuleLevelDescriptorName(descriptor: *foreign_message_type);
869 printer_->Print(variables: m, text: "$field_ref$.message_type = $foreign_type$\n");
870 }
871 const EnumDescriptor* enum_type = field.enum_type();
872 if (enum_type) {
873 m["enum_type"] = ModuleLevelDescriptorName(descriptor: *enum_type);
874 printer_->Print(variables: m, text: "$field_ref$.enum_type = $enum_type$\n");
875 }
876}
877
878// Returns the module-level expression for the given FieldDescriptor.
879// Only works for fields in the .proto file this Generator is generating for.
880//
881// containing_type may be NULL, in which case this is a module-level field.
882//
883// python_dict_name is the name of the Python dict where we should
884// look the field up in the containing type. (e.g., fields_by_name
885// or extensions_by_name). We ignore python_dict_name if containing_type
886// is NULL.
887std::string Generator::FieldReferencingExpression(
888 const Descriptor* containing_type, const FieldDescriptor& field,
889 const std::string& python_dict_name) const {
890 // We should only ever be looking up fields in the current file.
891 // The only things we refer to from other files are message descriptors.
892 GOOGLE_CHECK_EQ(field.file(), file_)
893 << field.file()->name() << " vs. " << file_->name();
894 if (!containing_type) {
895 return ResolveKeyword(name: field.name());
896 }
897 return strings::Substitute(format: "$0.$1['$2']",
898 arg0: ModuleLevelDescriptorName(descriptor: *containing_type),
899 arg1: python_dict_name, arg2: field.name());
900}
901
902// Prints containing_type for nested descriptors or enum descriptors.
903template <typename DescriptorT>
904void Generator::FixContainingTypeInDescriptor(
905 const DescriptorT& descriptor,
906 const Descriptor* containing_descriptor) const {
907 if (containing_descriptor != nullptr) {
908 const std::string nested_name = ModuleLevelDescriptorName(descriptor);
909 const std::string parent_name =
910 ModuleLevelDescriptorName(descriptor: *containing_descriptor);
911 printer_->Print(text: "$nested_name$.containing_type = $parent_name$\n",
912 args: "nested_name", args: nested_name, args: "parent_name", args: parent_name);
913 }
914}
915
916// Prints statements setting the message_type and enum_type fields in the
917// Python descriptor objects we've already output in the file. We must
918// do this in a separate step due to circular references (otherwise, we'd
919// just set everything in the initial assignment statements).
920void Generator::FixForeignFieldsInDescriptors() const {
921 for (int i = 0; i < file_->message_type_count(); ++i) {
922 FixForeignFieldsInDescriptor(descriptor: *file_->message_type(index: i), containing_descriptor: nullptr);
923 }
924 for (int i = 0; i < file_->message_type_count(); ++i) {
925 AddMessageToFileDescriptor(descriptor: *file_->message_type(index: i));
926 }
927 for (int i = 0; i < file_->enum_type_count(); ++i) {
928 AddEnumToFileDescriptor(descriptor: *file_->enum_type(index: i));
929 }
930 for (int i = 0; i < file_->extension_count(); ++i) {
931 AddExtensionToFileDescriptor(descriptor: *file_->extension(index: i));
932 }
933
934 // TODO(jieluo): Move this register to PrintFileDescriptor() when
935 // FieldDescriptor.file is added in generated file.
936 printer_->Print(text: "_sym_db.RegisterFileDescriptor($name$)\n", args: "name",
937 args: kDescriptorKey);
938 printer_->Print(text: "\n");
939}
940
941// We need to not only set any necessary message_type fields, but
942// also need to call RegisterExtension() on each message we're
943// extending.
944void Generator::FixForeignFieldsInExtensions() const {
945 // Top-level extensions.
946 for (int i = 0; i < file_->extension_count(); ++i) {
947 FixForeignFieldsInExtension(extension_field: *file_->extension(index: i));
948 }
949 // Nested extensions.
950 for (int i = 0; i < file_->message_type_count(); ++i) {
951 FixForeignFieldsInNestedExtensions(descriptor: *file_->message_type(index: i));
952 }
953 printer_->Print(text: "\n");
954}
955
956void Generator::FixForeignFieldsInExtension(
957 const FieldDescriptor& extension_field) const {
958 GOOGLE_CHECK(extension_field.is_extension());
959
960 std::map<std::string, std::string> m;
961 // Confusingly, for FieldDescriptors that happen to be extensions,
962 // containing_type() means "extended type."
963 // On the other hand, extension_scope() will give us what we normally
964 // mean by containing_type().
965 m["extended_message_class"] =
966 ModuleLevelMessageName(descriptor: *extension_field.containing_type());
967 m["field"] = FieldReferencingExpression(
968 containing_type: extension_field.extension_scope(), field: extension_field, python_dict_name: "extensions_by_name");
969 printer_->Print(variables: m, text: "$extended_message_class$.RegisterExtension($field$)\n");
970}
971
972void Generator::FixForeignFieldsInNestedExtensions(
973 const Descriptor& descriptor) const {
974 // Recursively fix up extensions in all nested types.
975 for (int i = 0; i < descriptor.nested_type_count(); ++i) {
976 FixForeignFieldsInNestedExtensions(descriptor: *descriptor.nested_type(index: i));
977 }
978 // Fix up extensions directly contained within this type.
979 for (int i = 0; i < descriptor.extension_count(); ++i) {
980 FixForeignFieldsInExtension(extension_field: *descriptor.extension(index: i));
981 }
982}
983
984// Returns a Python expression that instantiates a Python EnumValueDescriptor
985// object for the given C++ descriptor.
986void Generator::PrintEnumValueDescriptor(
987 const EnumValueDescriptor& descriptor) const {
988 // TODO(robinson): Fix up EnumValueDescriptor "type" fields.
989 // More circular references. ::sigh::
990 std::string options_string;
991 descriptor.options().SerializeToString(output: &options_string);
992 std::map<std::string, std::string> m;
993 m["name"] = descriptor.name();
994 m["index"] = StrCat(a: descriptor.index());
995 m["number"] = StrCat(a: descriptor.number());
996 m["options"] = OptionsValue(serialized_options: options_string);
997 printer_->Print(variables: m,
998 text: "_descriptor.EnumValueDescriptor(\n"
999 " name='$name$', index=$index$, number=$number$,\n"
1000 " serialized_options=$options$,\n"
1001 " type=None,\n"
1002 " create_key=_descriptor._internal_create_key)");
1003}
1004
1005// Returns a CEscaped string of serialized_options.
1006std::string Generator::OptionsValue(
1007 const std::string& serialized_options) const {
1008 if (serialized_options.length() == 0 || GeneratingDescriptorProto()) {
1009 return "None";
1010 } else {
1011 return "b'" + CEscape(src: serialized_options) + "'";
1012 }
1013}
1014
1015// Prints an expression for a Python FieldDescriptor for |field|.
1016void Generator::PrintFieldDescriptor(const FieldDescriptor& field,
1017 bool is_extension) const {
1018 std::string options_string;
1019 field.options().SerializeToString(output: &options_string);
1020 std::map<std::string, std::string> m;
1021 m["name"] = field.name();
1022 m["full_name"] = field.full_name();
1023 m["index"] = StrCat(a: field.index());
1024 m["number"] = StrCat(a: field.number());
1025 m["type"] = StrCat(a: field.type());
1026 m["cpp_type"] = StrCat(a: field.cpp_type());
1027 m["label"] = StrCat(a: field.label());
1028 m["has_default_value"] = field.has_default_value() ? "True" : "False";
1029 m["default_value"] = StringifyDefaultValue(field);
1030 m["is_extension"] = is_extension ? "True" : "False";
1031 m["serialized_options"] = OptionsValue(serialized_options: options_string);
1032 m["json_name"] =
1033 field.has_json_name() ? ", json_name='" + field.json_name() + "'" : "";
1034 // We always set message_type and enum_type to None at this point, and then
1035 // these fields in correctly after all referenced descriptors have been
1036 // defined and/or imported (see FixForeignFieldsInDescriptors()).
1037 const char field_descriptor_decl[] =
1038 "_descriptor.FieldDescriptor(\n"
1039 " name='$name$', full_name='$full_name$', index=$index$,\n"
1040 " number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n"
1041 " has_default_value=$has_default_value$, "
1042 "default_value=$default_value$,\n"
1043 " message_type=None, enum_type=None, containing_type=None,\n"
1044 " is_extension=$is_extension$, extension_scope=None,\n"
1045 " serialized_options=$serialized_options$$json_name$, file=DESCRIPTOR,"
1046 " create_key=_descriptor._internal_create_key)";
1047 printer_->Print(variables: m, text: field_descriptor_decl);
1048}
1049
1050// Helper for Print{Fields,Extensions}InDescriptor().
1051void Generator::PrintFieldDescriptorsInDescriptor(
1052 const Descriptor& message_descriptor, bool is_extension,
1053 const std::string& list_variable_name, int (Descriptor::*CountFn)() const,
1054 const FieldDescriptor* (Descriptor::*GetterFn)(int)const) const {
1055 printer_->Print(text: "$list$=[\n", args: "list", args: list_variable_name);
1056 printer_->Indent();
1057 for (int i = 0; i < (message_descriptor.*CountFn)(); ++i) {
1058 PrintFieldDescriptor(field: *(message_descriptor.*GetterFn)(i), is_extension);
1059 printer_->Print(text: ",\n");
1060 }
1061 printer_->Outdent();
1062 printer_->Print(text: "],\n");
1063}
1064
1065// Prints a statement assigning "fields" to a list of Python FieldDescriptors,
1066// one for each field present in message_descriptor.
1067void Generator::PrintFieldsInDescriptor(
1068 const Descriptor& message_descriptor) const {
1069 const bool is_extension = false;
1070 PrintFieldDescriptorsInDescriptor(message_descriptor, is_extension, list_variable_name: "fields",
1071 CountFn: &Descriptor::field_count,
1072 GetterFn: &Descriptor::field);
1073}
1074
1075// Prints a statement assigning "extensions" to a list of Python
1076// FieldDescriptors, one for each extension present in message_descriptor.
1077void Generator::PrintExtensionsInDescriptor(
1078 const Descriptor& message_descriptor) const {
1079 const bool is_extension = true;
1080 PrintFieldDescriptorsInDescriptor(message_descriptor, is_extension,
1081 list_variable_name: "extensions", CountFn: &Descriptor::extension_count,
1082 GetterFn: &Descriptor::extension);
1083}
1084
1085bool Generator::GeneratingDescriptorProto() const {
1086 return file_->name() == "net/proto2/proto/descriptor.proto" ||
1087 file_->name() == "google/protobuf/descriptor.proto";
1088}
1089
1090// Returns the unique Python module-level identifier given to a descriptor.
1091// This name is module-qualified iff the given descriptor describes an
1092// entity that doesn't come from the current file.
1093template <typename DescriptorT>
1094std::string Generator::ModuleLevelDescriptorName(
1095 const DescriptorT& descriptor) const {
1096 // FIXME(robinson):
1097 // We currently don't worry about collisions with underscores in the type
1098 // names, so these would collide in nasty ways if found in the same file:
1099 // OuterProto.ProtoA.ProtoB
1100 // OuterProto_ProtoA.ProtoB # Underscore instead of period.
1101 // As would these:
1102 // OuterProto.ProtoA_.ProtoB
1103 // OuterProto.ProtoA._ProtoB # Leading vs. trailing underscore.
1104 // (Contrived, but certainly possible).
1105 //
1106 // The C++ implementation doesn't guard against this either. Leaving
1107 // it for now...
1108 std::string name = NamePrefixedWithNestedTypes(descriptor, "_");
1109 ToUpper(s: &name);
1110 // Module-private for now. Easy to make public later; almost impossible
1111 // to make private later.
1112 name = "_" + name;
1113 // We now have the name relative to its own module. Also qualify with
1114 // the module name iff this descriptor is from a different .proto file.
1115 if (descriptor.file() != file_) {
1116 name = ModuleAlias(descriptor.file()->name()) + "." + name;
1117 }
1118 return name;
1119}
1120
1121// Returns the name of the message class itself, not the descriptor.
1122// Like ModuleLevelDescriptorName(), module-qualifies the name iff
1123// the given descriptor describes an entity that doesn't come from
1124// the current file.
1125std::string Generator::ModuleLevelMessageName(
1126 const Descriptor& descriptor) const {
1127 std::string name = NamePrefixedWithNestedTypes(descriptor, separator: ".");
1128 if (descriptor.file() != file_) {
1129 name = ModuleAlias(filename: descriptor.file()->name()) + "." + name;
1130 }
1131 return name;
1132}
1133
1134// Returns the unique Python module-level identifier given to a service
1135// descriptor.
1136std::string Generator::ModuleLevelServiceDescriptorName(
1137 const ServiceDescriptor& descriptor) const {
1138 std::string name = descriptor.name();
1139 ToUpper(s: &name);
1140 name = "_" + name;
1141 if (descriptor.file() != file_) {
1142 name = ModuleAlias(filename: descriptor.file()->name()) + "." + name;
1143 }
1144 return name;
1145}
1146
1147// Prints standard constructor arguments serialized_start and serialized_end.
1148// Args:
1149// descriptor: The cpp descriptor to have a serialized reference.
1150// proto: A proto
1151// Example printer output:
1152// serialized_start=41,
1153// serialized_end=43,
1154//
1155template <typename DescriptorT, typename DescriptorProtoT>
1156void Generator::PrintSerializedPbInterval(const DescriptorT& descriptor,
1157 DescriptorProtoT& proto,
1158 const std::string& name) const {
1159 descriptor.CopyTo(&proto);
1160 std::string sp;
1161 proto.SerializeToString(&sp);
1162 int offset = file_descriptor_serialized_.find(str: sp);
1163 GOOGLE_CHECK_GE(offset, 0);
1164
1165 printer_->Print(
1166 text: "$name$._serialized_start=$serialized_start$\n"
1167 "$name$._serialized_end=$serialized_end$\n",
1168 args: "name", args: name, args: "serialized_start", args: StrCat(a: offset), args: "serialized_end",
1169 args: StrCat(a: offset + sp.size()));
1170}
1171
1172namespace {
1173void PrintDescriptorOptionsFixingCode(const std::string& descriptor,
1174 const std::string& options,
1175 io::Printer* printer) {
1176 // Reset the _options to None thus DescriptorBase.GetOptions() can
1177 // parse _options again after extensions are registered.
1178 printer->Print(
1179 text: "$descriptor$._options = None\n"
1180 "$descriptor$._serialized_options = $serialized_value$\n",
1181 args: "descriptor", args: descriptor, args: "serialized_value", args: options);
1182}
1183} // namespace
1184
1185void Generator::SetSerializedPbInterval() const {
1186 // Top level enums.
1187 for (int i = 0; i < file_->enum_type_count(); ++i) {
1188 EnumDescriptorProto proto;
1189 const EnumDescriptor& descriptor = *file_->enum_type(index: i);
1190 PrintSerializedPbInterval(descriptor, proto,
1191 name: ModuleLevelDescriptorName(descriptor));
1192 }
1193
1194 // Messages.
1195 for (int i = 0; i < file_->message_type_count(); ++i) {
1196 SetMessagePbInterval(*file_->message_type(index: i));
1197 }
1198
1199 // Services.
1200 for (int i = 0; i < file_->service_count(); ++i) {
1201 ServiceDescriptorProto proto;
1202 const ServiceDescriptor& service = *file_->service(index: i);
1203 PrintSerializedPbInterval(descriptor: service, proto,
1204 name: ModuleLevelServiceDescriptorName(descriptor: service));
1205 }
1206}
1207
1208void Generator::SetMessagePbInterval(const Descriptor& descriptor) const {
1209 DescriptorProto message_proto;
1210 PrintSerializedPbInterval(descriptor, proto&: message_proto,
1211 name: ModuleLevelDescriptorName(descriptor));
1212
1213 // Nested messages.
1214 for (int i = 0; i < descriptor.nested_type_count(); ++i) {
1215 SetMessagePbInterval(*descriptor.nested_type(index: i));
1216 }
1217
1218 for (int i = 0; i < descriptor.enum_type_count(); ++i) {
1219 EnumDescriptorProto proto;
1220 const EnumDescriptor& enum_des = *descriptor.enum_type(index: i);
1221 PrintSerializedPbInterval(descriptor: enum_des, proto,
1222 name: ModuleLevelDescriptorName(descriptor: enum_des));
1223 }
1224}
1225
1226// Prints expressions that set the options field of all descriptors.
1227void Generator::FixAllDescriptorOptions() const {
1228 // Prints an expression that sets the file descriptor's options.
1229 std::string file_options = OptionsValue(serialized_options: file_->options().SerializeAsString());
1230 if (file_options != "None") {
1231 PrintDescriptorOptionsFixingCode(descriptor: kDescriptorKey, options: file_options, printer: printer_);
1232 } else {
1233 printer_->Print(text: "DESCRIPTOR._options = None\n");
1234 }
1235 // Prints expressions that set the options for all top level enums.
1236 for (int i = 0; i < file_->enum_type_count(); ++i) {
1237 const EnumDescriptor& enum_descriptor = *file_->enum_type(index: i);
1238 FixOptionsForEnum(descriptor: enum_descriptor);
1239 }
1240 // Prints expressions that set the options for all top level extensions.
1241 for (int i = 0; i < file_->extension_count(); ++i) {
1242 const FieldDescriptor& field = *file_->extension(index: i);
1243 FixOptionsForField(field);
1244 }
1245 // Prints expressions that set the options for all messages, nested enums,
1246 // nested extensions and message fields.
1247 for (int i = 0; i < file_->message_type_count(); ++i) {
1248 FixOptionsForMessage(descriptor: *file_->message_type(index: i));
1249 }
1250
1251 for (int i = 0; i < file_->service_count(); ++i) {
1252 FixOptionsForService(descriptor: *file_->service(index: i));
1253 }
1254}
1255
1256void Generator::FixOptionsForOneof(const OneofDescriptor& oneof) const {
1257 std::string oneof_options = OptionsValue(serialized_options: oneof.options().SerializeAsString());
1258 if (oneof_options != "None") {
1259 std::string oneof_name = strings::Substitute(
1260 format: "$0.$1['$2']", arg0: ModuleLevelDescriptorName(descriptor: *oneof.containing_type()),
1261 arg1: "oneofs_by_name", arg2: oneof.name());
1262 PrintDescriptorOptionsFixingCode(descriptor: oneof_name, options: oneof_options, printer: printer_);
1263 }
1264}
1265
1266// Prints expressions that set the options for an enum descriptor and its
1267// value descriptors.
1268void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const {
1269 std::string descriptor_name = ModuleLevelDescriptorName(descriptor: enum_descriptor);
1270 std::string enum_options =
1271 OptionsValue(serialized_options: enum_descriptor.options().SerializeAsString());
1272 if (enum_options != "None") {
1273 PrintDescriptorOptionsFixingCode(descriptor: descriptor_name, options: enum_options, printer: printer_);
1274 }
1275 for (int i = 0; i < enum_descriptor.value_count(); ++i) {
1276 const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(index: i);
1277 std::string value_options =
1278 OptionsValue(serialized_options: value_descriptor.options().SerializeAsString());
1279 if (value_options != "None") {
1280 PrintDescriptorOptionsFixingCode(
1281 descriptor: StringPrintf(format: "%s.values_by_name[\"%s\"]", descriptor_name.c_str(),
1282 value_descriptor.name().c_str()),
1283 options: value_options, printer: printer_);
1284 }
1285 }
1286}
1287
1288// Prints expressions that set the options for an service descriptor and its
1289// value descriptors.
1290void Generator::FixOptionsForService(
1291 const ServiceDescriptor& service_descriptor) const {
1292 std::string descriptor_name =
1293 ModuleLevelServiceDescriptorName(descriptor: service_descriptor);
1294 std::string service_options =
1295 OptionsValue(serialized_options: service_descriptor.options().SerializeAsString());
1296 if (service_options != "None") {
1297 PrintDescriptorOptionsFixingCode(descriptor: descriptor_name, options: service_options,
1298 printer: printer_);
1299 }
1300
1301 for (int i = 0; i < service_descriptor.method_count(); ++i) {
1302 const MethodDescriptor* method = service_descriptor.method(index: i);
1303 std::string method_options =
1304 OptionsValue(serialized_options: method->options().SerializeAsString());
1305 if (method_options != "None") {
1306 std::string method_name =
1307 descriptor_name + ".methods_by_name['" + method->name() + "']";
1308 PrintDescriptorOptionsFixingCode(descriptor: method_name, options: method_options, printer: printer_);
1309 }
1310 }
1311}
1312
1313// Prints expressions that set the options for field descriptors (including
1314// extensions).
1315void Generator::FixOptionsForField(const FieldDescriptor& field) const {
1316 std::string field_options = OptionsValue(serialized_options: field.options().SerializeAsString());
1317 if (field_options != "None") {
1318 std::string field_name;
1319 if (field.is_extension()) {
1320 if (field.extension_scope() == nullptr) {
1321 // Top level extensions.
1322 field_name = field.name();
1323 } else {
1324 field_name = FieldReferencingExpression(containing_type: field.extension_scope(), field,
1325 python_dict_name: "extensions_by_name");
1326 }
1327 } else {
1328 field_name = FieldReferencingExpression(containing_type: field.containing_type(), field,
1329 python_dict_name: "fields_by_name");
1330 }
1331 PrintDescriptorOptionsFixingCode(descriptor: field_name, options: field_options, printer: printer_);
1332 }
1333}
1334
1335// Prints expressions that set the options for a message and all its inner
1336// types (nested messages, nested enums, extensions, fields).
1337void Generator::FixOptionsForMessage(const Descriptor& descriptor) const {
1338 // Nested messages.
1339 for (int i = 0; i < descriptor.nested_type_count(); ++i) {
1340 FixOptionsForMessage(descriptor: *descriptor.nested_type(index: i));
1341 }
1342 // Oneofs.
1343 for (int i = 0; i < descriptor.oneof_decl_count(); ++i) {
1344 FixOptionsForOneof(oneof: *descriptor.oneof_decl(index: i));
1345 }
1346 // Enums.
1347 for (int i = 0; i < descriptor.enum_type_count(); ++i) {
1348 FixOptionsForEnum(enum_descriptor: *descriptor.enum_type(index: i));
1349 }
1350 // Fields.
1351 for (int i = 0; i < descriptor.field_count(); ++i) {
1352 const FieldDescriptor& field = *descriptor.field(index: i);
1353 FixOptionsForField(field);
1354 }
1355 // Extensions.
1356 for (int i = 0; i < descriptor.extension_count(); ++i) {
1357 const FieldDescriptor& field = *descriptor.extension(index: i);
1358 FixOptionsForField(field);
1359 }
1360 // Message option for this message.
1361 std::string message_options =
1362 OptionsValue(serialized_options: descriptor.options().SerializeAsString());
1363 if (message_options != "None") {
1364 std::string descriptor_name = ModuleLevelDescriptorName(descriptor);
1365 PrintDescriptorOptionsFixingCode(descriptor: descriptor_name, options: message_options,
1366 printer: printer_);
1367 }
1368}
1369
1370// If a dependency forwards other files through public dependencies, let's
1371// copy over the corresponding module aliases.
1372void Generator::CopyPublicDependenciesAliases(
1373 const std::string& copy_from, const FileDescriptor* file) const {
1374 for (int i = 0; i < file->public_dependency_count(); ++i) {
1375 std::string module_name = ModuleName(filename: file->public_dependency(index: i)->name());
1376 std::string module_alias = ModuleAlias(filename: file->public_dependency(index: i)->name());
1377 // There's no module alias in the dependent file if it was generated by
1378 // an old protoc (less than 3.0.0-alpha-1). Use module name in this
1379 // situation.
1380 printer_->Print(
1381 text: "try:\n"
1382 " $alias$ = $copy_from$.$alias$\n"
1383 "except AttributeError:\n"
1384 " $alias$ = $copy_from$.$module$\n",
1385 args: "alias", args: module_alias, args: "module", args: module_name, args: "copy_from", args: copy_from);
1386 CopyPublicDependenciesAliases(copy_from, file: file->public_dependency(index: i));
1387 }
1388}
1389
1390} // namespace python
1391} // namespace compiler
1392} // namespace protobuf
1393} // namespace google
1394