| Index: third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc
|
| ===================================================================
|
| --- third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc (revision 216642)
|
| +++ third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc (working copy)
|
| @@ -52,6 +52,7 @@
|
| #include <google/protobuf/descriptor.pb.h>
|
|
|
| #include <google/protobuf/stubs/common.h>
|
| +#include <google/protobuf/stubs/stringprintf.h>
|
| #include <google/protobuf/io/printer.h>
|
| #include <google/protobuf/descriptor.h>
|
| #include <google/protobuf/io/zero_copy_stream.h>
|
| @@ -106,6 +107,12 @@
|
| const char kDescriptorKey[] = "DESCRIPTOR";
|
|
|
|
|
| +// Does the file have top-level enums?
|
| +inline bool HasTopLevelEnums(const FileDescriptor *file) {
|
| + return file->enum_type_count() > 0;
|
| +}
|
| +
|
| +
|
| // Should we generate generic services for this file?
|
| inline bool HasGenericServices(const FileDescriptor *file) {
|
| return file->service_count() > 0 &&
|
| @@ -120,13 +127,21 @@
|
| // TODO(robinson): Allow parameterization of Python version?
|
| printer->Print(
|
| "# Generated by the protocol buffer compiler. DO NOT EDIT!\n"
|
| - "\n"
|
| - "from google.protobuf import descriptor\n"
|
| - "from google.protobuf import message\n"
|
| - "from google.protobuf import reflection\n");
|
| + "# source: $filename$\n"
|
| + "\n",
|
| + "filename", file->name());
|
| + if (HasTopLevelEnums(file)) {
|
| + printer->Print(
|
| + "from google.protobuf.internal import enum_type_wrapper\n");
|
| + }
|
| + printer->Print(
|
| + "from google.protobuf import descriptor as _descriptor\n"
|
| + "from google.protobuf import message as _message\n"
|
| + "from google.protobuf import reflection as _reflection\n"
|
| + );
|
| if (HasGenericServices(file)) {
|
| printer->Print(
|
| - "from google.protobuf import service\n"
|
| + "from google.protobuf import service as _service\n"
|
| "from google.protobuf import service_reflection\n");
|
| }
|
|
|
| @@ -204,12 +219,12 @@
|
| case FieldDescriptor::CPPTYPE_STRING:
|
| if (field.type() == FieldDescriptor::TYPE_STRING) {
|
| return "unicode(\"" + CEscape(field.default_value_string()) +
|
| - "\", \"utf-8\")";
|
| + "\", \"utf-8\")";
|
| } else {
|
| return "\"" + CEscape(field.default_value_string()) + "\"";
|
| }
|
| - case FieldDescriptor::CPPTYPE_MESSAGE:
|
| - return "None";
|
| + case FieldDescriptor::CPPTYPE_MESSAGE:
|
| + return "None";
|
| }
|
| // (We could add a default case above but then we wouldn't get the nice
|
| // compiler warning when a new type is added.)
|
| @@ -270,6 +285,11 @@
|
| // since they need to call static RegisterExtension() methods on these
|
| // classes.
|
| FixForeignFieldsInExtensions();
|
| + // Descriptor options may have custom extensions. These custom options
|
| + // can only be successfully parsed after we register corresponding
|
| + // extensions. Therefore we parse all options again here to recognize
|
| + // custom options that may be unknown when we define the descriptors.
|
| + FixAllDescriptorOptions();
|
| if (HasGenericServices(file)) {
|
| PrintServices();
|
| }
|
| @@ -288,6 +308,13 @@
|
| module_name);
|
| }
|
| printer_->Print("\n");
|
| +
|
| + // Print public imports.
|
| + for (int i = 0; i < file_->public_dependency_count(); ++i) {
|
| + string module_name = ModuleName(file_->public_dependency(i)->name());
|
| + printer_->Print("from $module$ import *\n", "module", module_name);
|
| + }
|
| + printer_->Print("\n");
|
| }
|
|
|
| // Prints the single file descriptor for this file.
|
| @@ -297,7 +324,7 @@
|
| m["name"] = file_->name();
|
| m["package"] = file_->package();
|
| const char file_descriptor_template[] =
|
| - "$descriptor_name$ = descriptor.FileDescriptor(\n"
|
| + "$descriptor_name$ = _descriptor.FileDescriptor(\n"
|
| " name='$name$',\n"
|
| " package='$package$',\n";
|
| printer_->Print(m, file_descriptor_template);
|
| @@ -321,6 +348,11 @@
|
| for (int i = 0; i < file_->enum_type_count(); ++i) {
|
| const EnumDescriptor& enum_descriptor = *file_->enum_type(i);
|
| PrintEnum(enum_descriptor);
|
| + printer_->Print("$name$ = "
|
| + "enum_type_wrapper.EnumTypeWrapper($descriptor_name$)",
|
| + "name", enum_descriptor.name(),
|
| + "descriptor_name",
|
| + ModuleLevelDescriptorName(enum_descriptor));
|
| printer_->Print("\n");
|
|
|
| for (int j = 0; j < enum_descriptor.value_count(); ++j) {
|
| @@ -355,7 +387,7 @@
|
| m["full_name"] = enum_descriptor.full_name();
|
| m["file"] = kDescriptorKey;
|
| const char enum_descriptor_template[] =
|
| - "$descriptor_name$ = descriptor.EnumDescriptor(\n"
|
| + "$descriptor_name$ = _descriptor.EnumDescriptor(\n"
|
| " name='$name$',\n"
|
| " full_name='$full_name$',\n"
|
| " filename=None,\n"
|
| @@ -436,7 +468,7 @@
|
| descriptor.options().SerializeToString(&options_string);
|
|
|
| printer_->Print(
|
| - "$service_name$ = descriptor.ServiceDescriptor(\n",
|
| + "$service_name$ = _descriptor.ServiceDescriptor(\n",
|
| "service_name", service_name);
|
| printer_->Indent();
|
| map<string, string> m;
|
| @@ -459,7 +491,6 @@
|
| printer_->Print("methods=[\n");
|
| for (int i = 0; i < descriptor.method_count(); ++i) {
|
| const MethodDescriptor* method = descriptor.method(i);
|
| - string options_string;
|
| method->options().SerializeToString(&options_string);
|
|
|
| m.clear();
|
| @@ -470,7 +501,7 @@
|
| m["input_type"] = ModuleLevelDescriptorName(*(method->input_type()));
|
| m["output_type"] = ModuleLevelDescriptorName(*(method->output_type()));
|
| m["options_value"] = OptionsValue("MethodOptions", options_string);
|
| - printer_->Print("descriptor.MethodDescriptor(\n");
|
| + printer_->Print("_descriptor.MethodDescriptor(\n");
|
| printer_->Indent();
|
| printer_->Print(
|
| m,
|
| @@ -491,7 +522,7 @@
|
|
|
| void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const {
|
| // Print the service.
|
| - printer_->Print("class $class_name$(service.Service):\n",
|
| + printer_->Print("class $class_name$(_service.Service):\n",
|
| "class_name", descriptor.name());
|
| printer_->Indent();
|
| printer_->Print(
|
| @@ -523,7 +554,7 @@
|
| PrintNestedDescriptors(message_descriptor);
|
|
|
| printer_->Print("\n");
|
| - printer_->Print("$descriptor_name$ = descriptor.Descriptor(\n",
|
| + printer_->Print("$descriptor_name$ = _descriptor.Descriptor(\n",
|
| "descriptor_name",
|
| ModuleLevelDescriptorName(message_descriptor));
|
| printer_->Indent();
|
| @@ -618,10 +649,10 @@
|
| // Mutually recursive with PrintNestedMessages().
|
| void Generator::PrintMessage(
|
| const Descriptor& message_descriptor) const {
|
| - printer_->Print("class $name$(message.Message):\n", "name",
|
| + printer_->Print("class $name$(_message.Message):\n", "name",
|
| message_descriptor.name());
|
| printer_->Indent();
|
| - printer_->Print("__metaclass__ = reflection.GeneratedProtocolMessageType\n");
|
| + printer_->Print("__metaclass__ = _reflection.GeneratedProtocolMessageType\n");
|
| PrintNestedMessages(message_descriptor);
|
| map<string, string> m;
|
| m["descriptor_key"] = kDescriptorKey;
|
| @@ -779,6 +810,7 @@
|
| for (int i = 0; i < file_->message_type_count(); ++i) {
|
| FixForeignFieldsInNestedExtensions(*file_->message_type(i));
|
| }
|
| + printer_->Print("\n");
|
| }
|
|
|
| void Generator::FixForeignFieldsInExtension(
|
| @@ -829,7 +861,7 @@
|
| m["options"] = OptionsValue("EnumValueOptions", options_string);
|
| printer_->Print(
|
| m,
|
| - "descriptor.EnumValueDescriptor(\n"
|
| + "_descriptor.EnumValueDescriptor(\n"
|
| " name='$name$', index=$index$, number=$number$,\n"
|
| " options=$options$,\n"
|
| " type=None)");
|
| @@ -843,7 +875,7 @@
|
| return "None";
|
| } else {
|
| string full_class_name = "descriptor_pb2." + class_name;
|
| - return "descriptor._ParseOptions(" + full_class_name + "(), '"
|
| + return "_descriptor._ParseOptions(" + full_class_name + "(), '"
|
| + CEscape(serialized_options)+ "')";
|
| }
|
| }
|
| @@ -869,7 +901,7 @@
|
| // these fields in correctly after all referenced descriptors have been
|
| // defined and/or imported (see FixForeignFieldsInDescriptors()).
|
| const char field_descriptor_decl[] =
|
| - "descriptor.FieldDescriptor(\n"
|
| + "_descriptor.FieldDescriptor(\n"
|
| " name='$name$', full_name='$full_name$', index=$index$,\n"
|
| " number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n"
|
| " has_default_value=$has_default_value$, default_value=$default_value$,\n"
|
| @@ -1000,6 +1032,125 @@
|
| "serialized_end", SimpleItoa(offset + sp.size()));
|
| }
|
|
|
| +namespace {
|
| +void PrintDescriptorOptionsFixingCode(const string& descriptor,
|
| + const string& options,
|
| + io::Printer* printer) {
|
| + // TODO(xiaofeng): I have added a method _SetOptions() to DescriptorBase
|
| + // in proto2 python runtime but it couldn't be used here because appengine
|
| + // uses a snapshot version of the library in which the new method is not
|
| + // yet present. After appengine has synced their runtime library, the code
|
| + // below should be cleaned up to use _SetOptions().
|
| + printer->Print(
|
| + "$descriptor$.has_options = True\n"
|
| + "$descriptor$._options = $options$\n",
|
| + "descriptor", descriptor, "options", options);
|
| +}
|
| +} // namespace
|
| +
|
| +// Prints expressions that set the options field of all descriptors.
|
| +void Generator::FixAllDescriptorOptions() const {
|
| + // Prints an expression that sets the file descriptor's options.
|
| + string file_options = OptionsValue(
|
| + "FileOptions", file_->options().SerializeAsString());
|
| + if (file_options != "None") {
|
| + PrintDescriptorOptionsFixingCode(kDescriptorKey, file_options, printer_);
|
| + }
|
| + // Prints expressions that set the options for all top level enums.
|
| + for (int i = 0; i < file_->enum_type_count(); ++i) {
|
| + const EnumDescriptor& enum_descriptor = *file_->enum_type(i);
|
| + FixOptionsForEnum(enum_descriptor);
|
| + }
|
| + // Prints expressions that set the options for all top level extensions.
|
| + for (int i = 0; i < file_->extension_count(); ++i) {
|
| + const FieldDescriptor& field = *file_->extension(i);
|
| + FixOptionsForField(field);
|
| + }
|
| + // Prints expressions that set the options for all messages, nested enums,
|
| + // nested extensions and message fields.
|
| + for (int i = 0; i < file_->message_type_count(); ++i) {
|
| + FixOptionsForMessage(*file_->message_type(i));
|
| + }
|
| +}
|
| +
|
| +// Prints expressions that set the options for an enum descriptor and its
|
| +// value descriptors.
|
| +void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const {
|
| + string descriptor_name = ModuleLevelDescriptorName(enum_descriptor);
|
| + string enum_options = OptionsValue(
|
| + "EnumOptions", enum_descriptor.options().SerializeAsString());
|
| + if (enum_options != "None") {
|
| + PrintDescriptorOptionsFixingCode(descriptor_name, enum_options, printer_);
|
| + }
|
| + for (int i = 0; i < enum_descriptor.value_count(); ++i) {
|
| + const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(i);
|
| + string value_options = OptionsValue(
|
| + "EnumValueOptions", value_descriptor.options().SerializeAsString());
|
| + if (value_options != "None") {
|
| + PrintDescriptorOptionsFixingCode(
|
| + StringPrintf("%s.values_by_name[\"%s\"]", descriptor_name.c_str(),
|
| + value_descriptor.name().c_str()),
|
| + value_options, printer_);
|
| + }
|
| + }
|
| +}
|
| +
|
| +// Prints expressions that set the options for field descriptors (including
|
| +// extensions).
|
| +void Generator::FixOptionsForField(
|
| + const FieldDescriptor& field) const {
|
| + string field_options = OptionsValue(
|
| + "FieldOptions", field.options().SerializeAsString());
|
| + if (field_options != "None") {
|
| + string field_name;
|
| + if (field.is_extension()) {
|
| + if (field.extension_scope() == NULL) {
|
| + // Top level extensions.
|
| + field_name = field.name();
|
| + } else {
|
| + field_name = FieldReferencingExpression(
|
| + field.extension_scope(), field, "extensions_by_name");
|
| + }
|
| + } else {
|
| + field_name = FieldReferencingExpression(
|
| + field.containing_type(), field, "fields_by_name");
|
| + }
|
| + PrintDescriptorOptionsFixingCode(field_name, field_options, printer_);
|
| + }
|
| +}
|
| +
|
| +// Prints expressions that set the options for a message and all its inner
|
| +// types (nested messages, nested enums, extensions, fields).
|
| +void Generator::FixOptionsForMessage(const Descriptor& descriptor) const {
|
| + // Nested messages.
|
| + for (int i = 0; i < descriptor.nested_type_count(); ++i) {
|
| + FixOptionsForMessage(*descriptor.nested_type(i));
|
| + }
|
| + // Enums.
|
| + for (int i = 0; i < descriptor.enum_type_count(); ++i) {
|
| + FixOptionsForEnum(*descriptor.enum_type(i));
|
| + }
|
| + // Fields.
|
| + for (int i = 0; i < descriptor.field_count(); ++i) {
|
| + const FieldDescriptor& field = *descriptor.field(i);
|
| + FixOptionsForField(field);
|
| + }
|
| + // Extensions.
|
| + for (int i = 0; i < descriptor.extension_count(); ++i) {
|
| + const FieldDescriptor& field = *descriptor.extension(i);
|
| + FixOptionsForField(field);
|
| + }
|
| + // Message option for this message.
|
| + string message_options = OptionsValue(
|
| + "MessageOptions", descriptor.options().SerializeAsString());
|
| + if (message_options != "None") {
|
| + string descriptor_name = ModuleLevelDescriptorName(descriptor);
|
| + PrintDescriptorOptionsFixingCode(descriptor_name,
|
| + message_options,
|
| + printer_);
|
| + }
|
| +}
|
| +
|
| } // namespace python
|
| } // namespace compiler
|
| } // namespace protobuf
|
|
|