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