Index: third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc |
diff --git a/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc b/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc |
index 211ac70c096b2812522168dc61b3243589254036..4d500f90e9cc591a676ceef90fb6d37f6da41072 100644 |
--- a/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc |
+++ b/third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc |
@@ -1,6 +1,6 @@ |
// Protocol Buffers - Google's data interchange format |
// Copyright 2008 Google Inc. All rights reserved. |
-// http://code.google.com/p/protobuf/ |
+// https://developers.google.com/protocol-buffers/ |
// |
// Redistribution and use in source and binary forms, with or without |
// modification, are permitted provided that the following conditions are |
@@ -28,6 +28,8 @@ |
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+//#PY25 compatible generated code for GAE. |
+// Copyright 2007 Google Inc. All Rights Reserved. |
// Author: robinson@google.com (Will Robinson) |
// |
// This module outputs pure-Python protocol message classes that will |
@@ -42,15 +44,21 @@ |
// performance-minded Python code leverage the fast C++ implementation |
// directly. |
+#include <google/protobuf/stubs/hash.h> |
#include <limits> |
#include <map> |
-#include <utility> |
+#include <memory> |
+#ifndef _SHARED_PTR_H |
+#include <google/protobuf/stubs/shared_ptr.h> |
+#endif |
#include <string> |
+#include <utility> |
#include <vector> |
#include <google/protobuf/compiler/python/python_generator.h> |
#include <google/protobuf/descriptor.pb.h> |
+#include <google/protobuf/stubs/logging.h> |
#include <google/protobuf/stubs/common.h> |
#include <google/protobuf/stubs/stringprintf.h> |
#include <google/protobuf/io/printer.h> |
@@ -85,6 +93,37 @@ string ModuleName(const string& filename) { |
} |
+// Returns the alias we assign to the module of the given .proto filename |
+// when importing. See testPackageInitializationImport in |
+// google/protobuf/python/reflection_test.py |
+// to see why we need the alias. |
+string ModuleAlias(const string& filename) { |
+ string module_name = ModuleName(filename); |
+ // We can't have dots in the module name, so we replace each with _dot_. |
+ // But that could lead to a collision between a.b and a_dot_b, so we also |
+ // duplicate each underscore. |
+ GlobalReplaceSubstring("_", "__", &module_name); |
+ GlobalReplaceSubstring(".", "_dot_", &module_name); |
+ return module_name; |
+} |
+ |
+ |
+// Returns an import statement of form "from X.Y.Z import T" for the given |
+// .proto filename. |
+string ModuleImportStatement(const string& filename) { |
+ string module_name = ModuleName(filename); |
+ int last_dot_pos = module_name.rfind('.'); |
+ if (last_dot_pos == string::npos) { |
+ // NOTE(petya): this is not tested as it would require a protocol buffer |
+ // outside of any package, and I don't think that is easily achievable. |
+ return "import " + module_name; |
+ } else { |
+ return "from " + module_name.substr(0, last_dot_pos) + " import " + |
+ module_name.substr(last_dot_pos + 1); |
+ } |
+} |
+ |
+ |
// Returns the name of all containing types for descriptor, |
// in order from outermost to innermost, followed by descriptor's |
// own name. Each name is separated by |separator|. |
@@ -128,6 +167,7 @@ void PrintTopBoilerplate( |
printer->Print( |
"# Generated by the protocol buffer compiler. DO NOT EDIT!\n" |
"# source: $filename$\n" |
+ "\nimport sys\n_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))" //##PY25 |
"\n", |
"filename", file->name()); |
if (HasTopLevelEnums(file)) { |
@@ -138,7 +178,8 @@ void PrintTopBoilerplate( |
"from google.protobuf import descriptor as _descriptor\n" |
"from google.protobuf import message as _message\n" |
"from google.protobuf import reflection as _reflection\n" |
- ); |
+ "from google.protobuf import symbol_database as " |
+ "_symbol_database\n"); |
if (HasGenericServices(file)) { |
printer->Print( |
"from google.protobuf import service as _service\n" |
@@ -151,7 +192,8 @@ void PrintTopBoilerplate( |
"from google.protobuf import descriptor_pb2\n"); |
} |
printer->Print( |
- "# @@protoc_insertion_point(imports)\n"); |
+ "# @@protoc_insertion_point(imports)\n\n" |
+ "_sym_db = _symbol_database.Default()\n"); |
printer->Print("\n\n"); |
} |
@@ -217,14 +259,14 @@ string StringifyDefaultValue(const FieldDescriptor& field) { |
case FieldDescriptor::CPPTYPE_ENUM: |
return SimpleItoa(field.default_value_enum()->number()); |
case FieldDescriptor::CPPTYPE_STRING: |
- if (field.type() == FieldDescriptor::TYPE_STRING) { |
- return "unicode(\"" + CEscape(field.default_value_string()) + |
- "\", \"utf-8\")"; |
- } else { |
- return "\"" + CEscape(field.default_value_string()) + "\""; |
- } |
- case FieldDescriptor::CPPTYPE_MESSAGE: |
- return "None"; |
+//##!PY25 return "b\"" + CEscape(field.default_value_string()) + |
+//##!PY25 (field.type() != FieldDescriptor::TYPE_STRING ? "\"" : |
+//##!PY25 "\".decode('utf-8')"); |
+ return "_b(\"" + CEscape(field.default_value_string()) + //##PY25 |
+ (field.type() != FieldDescriptor::TYPE_STRING ? "\")" : //##PY25 |
+ "\").decode('utf-8')"); //##PY25 |
+ 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.) |
@@ -232,6 +274,19 @@ string StringifyDefaultValue(const FieldDescriptor& field) { |
return ""; |
} |
+string StringifySyntax(FileDescriptor::Syntax syntax) { |
+ switch (syntax) { |
+ case FileDescriptor::SYNTAX_PROTO2: |
+ return "proto2"; |
+ case FileDescriptor::SYNTAX_PROTO3: |
+ return "proto3"; |
+ case FileDescriptor::SYNTAX_UNKNOWN: |
+ default: |
+ GOOGLE_LOG(FATAL) << "Unsupported syntax; this generator only supports proto2 " |
+ "and proto3 syntax."; |
+ return ""; |
+ } |
+} |
} // namespace |
@@ -267,7 +322,7 @@ bool Generator::Generate(const FileDescriptor* file, |
fdp.SerializeToString(&file_descriptor_serialized_); |
- scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename)); |
+ google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename)); |
GOOGLE_CHECK(output.get()); |
io::Printer printer(output.get(), '$'); |
printer_ = &printer; |
@@ -303,9 +358,12 @@ bool Generator::Generate(const FileDescriptor* file, |
// Prints Python imports for all modules imported by |file|. |
void Generator::PrintImports() const { |
for (int i = 0; i < file_->dependency_count(); ++i) { |
- string module_name = ModuleName(file_->dependency(i)->name()); |
- printer_->Print("import $module$\n", "module", |
- module_name); |
+ const string& filename = file_->dependency(i)->name(); |
+ string import_statement = ModuleImportStatement(filename); |
+ string module_alias = ModuleAlias(filename); |
+ printer_->Print("$statement$ as $alias$\n", "statement", |
+ import_statement, "alias", module_alias); |
+ CopyPublicDependenciesAliases(module_alias, file_->dependency(i)); |
} |
printer_->Print("\n"); |
@@ -323,21 +381,35 @@ void Generator::PrintFileDescriptor() const { |
m["descriptor_name"] = kDescriptorKey; |
m["name"] = file_->name(); |
m["package"] = file_->package(); |
+ m["syntax"] = StringifySyntax(file_->syntax()); |
const char file_descriptor_template[] = |
"$descriptor_name$ = _descriptor.FileDescriptor(\n" |
" name='$name$',\n" |
- " package='$package$',\n"; |
+ " package='$package$',\n" |
+ " syntax='$syntax$',\n"; |
printer_->Print(m, file_descriptor_template); |
printer_->Indent(); |
printer_->Print( |
- "serialized_pb='$value$'", |
+//##!PY25 "serialized_pb=b'$value$'\n", |
+ "serialized_pb=_b('$value$')\n", //##PY25 |
"value", strings::CHexEscape(file_descriptor_serialized_)); |
+ if (file_->dependency_count() != 0) { |
+ printer_->Print(",\ndependencies=["); |
+ for (int i = 0; i < file_->dependency_count(); ++i) { |
+ string module_alias = ModuleAlias(file_->dependency(i)->name()); |
+ printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias", |
+ module_alias); |
+ } |
+ printer_->Print("]"); |
+ } |
// TODO(falk): Also print options and fix the message_type, enum_type, |
// service and extension later in the generation. |
printer_->Outdent(); |
printer_->Print(")\n"); |
+ printer_->Print("_sym_db.RegisterFileDescriptor($name$)\n", "name", |
+ kDescriptorKey); |
printer_->Print("\n"); |
} |
@@ -358,7 +430,7 @@ void Generator::PrintTopLevelEnums() const { |
for (int j = 0; j < enum_descriptor.value_count(); ++j) { |
const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(j); |
top_level_enum_values.push_back( |
- make_pair(value_descriptor.name(), value_descriptor.number())); |
+ std::make_pair(value_descriptor.name(), value_descriptor.number())); |
} |
} |
@@ -382,7 +454,9 @@ void Generator::PrintAllNestedEnumsInFile() const { |
// enum_descriptor. |
void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { |
map<string, string> m; |
- m["descriptor_name"] = ModuleLevelDescriptorName(enum_descriptor); |
+ string module_level_descriptor_name = |
+ ModuleLevelDescriptorName(enum_descriptor); |
+ m["descriptor_name"] = module_level_descriptor_name; |
m["name"] = enum_descriptor.name(); |
m["full_name"] = enum_descriptor.full_name(); |
m["file"] = kDescriptorKey; |
@@ -412,6 +486,8 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { |
PrintSerializedPbInterval(enum_descriptor, edp); |
printer_->Outdent(); |
printer_->Print(")\n"); |
+ printer_->Print("_sym_db.RegisterEnumDescriptor($name$)\n", "name", |
+ module_level_descriptor_name); |
printer_->Print("\n"); |
} |
@@ -520,29 +596,38 @@ void Generator::PrintServiceDescriptor( |
printer_->Print("])\n\n"); |
} |
+ |
+void Generator::PrintDescriptorKeyAndModuleName( |
+ const ServiceDescriptor& descriptor) const { |
+ printer_->Print( |
+ "$descriptor_key$ = $descriptor_name$,\n", |
+ "descriptor_key", kDescriptorKey, |
+ "descriptor_name", ModuleLevelServiceDescriptorName(descriptor)); |
+ printer_->Print( |
+ "__module__ = '$module_name$'\n", |
+ "module_name", ModuleName(file_->name())); |
+} |
+ |
void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const { |
// Print the service. |
- printer_->Print("class $class_name$(_service.Service):\n", |
+ printer_->Print("$class_name$ = service_reflection.GeneratedServiceType(" |
+ "'$class_name$', (_service.Service,), dict(\n", |
"class_name", descriptor.name()); |
printer_->Indent(); |
- printer_->Print( |
- "__metaclass__ = service_reflection.GeneratedServiceType\n" |
- "$descriptor_key$ = $descriptor_name$\n", |
- "descriptor_key", kDescriptorKey, |
- "descriptor_name", ModuleLevelServiceDescriptorName(descriptor)); |
+ Generator::PrintDescriptorKeyAndModuleName(descriptor); |
+ printer_->Print("))\n\n"); |
printer_->Outdent(); |
} |
void Generator::PrintServiceStub(const ServiceDescriptor& descriptor) const { |
// Print the service stub. |
- printer_->Print("class $class_name$_Stub($class_name$):\n", |
+ printer_->Print("$class_name$_Stub = " |
+ "service_reflection.GeneratedServiceStubType(" |
+ "'$class_name$_Stub', ($class_name$,), dict(\n", |
"class_name", descriptor.name()); |
printer_->Indent(); |
- printer_->Print( |
- "__metaclass__ = service_reflection.GeneratedServiceStubType\n" |
- "$descriptor_key$ = $descriptor_name$\n", |
- "descriptor_key", kDescriptorKey, |
- "descriptor_name", ModuleLevelServiceDescriptorName(descriptor)); |
+ Generator::PrintDescriptorKeyAndModuleName(descriptor); |
+ printer_->Print("))\n\n"); |
printer_->Outdent(); |
} |
@@ -596,10 +681,12 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { |
message_descriptor.options().SerializeToString(&options_string); |
printer_->Print( |
"options=$options_value$,\n" |
- "is_extendable=$extendable$", |
+ "is_extendable=$extendable$,\n" |
+ "syntax='$syntax$'", |
"options_value", OptionsValue("MessageOptions", options_string), |
"extendable", message_descriptor.extension_range_count() > 0 ? |
- "True" : "False"); |
+ "True" : "False", |
+ "syntax", StringifySyntax(message_descriptor.file()->syntax())); |
printer_->Print(",\n"); |
// Extension ranges |
@@ -612,7 +699,22 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { |
"end", SimpleItoa(range->end)); |
} |
printer_->Print("],\n"); |
- |
+ printer_->Print("oneofs=[\n"); |
+ printer_->Indent(); |
+ for (int i = 0; i < message_descriptor.oneof_decl_count(); ++i) { |
+ const OneofDescriptor* desc = message_descriptor.oneof_decl(i); |
+ map<string, string> m; |
+ m["name"] = desc->name(); |
+ m["full_name"] = desc->full_name(); |
+ m["index"] = SimpleItoa(desc->index()); |
+ printer_->Print( |
+ m, |
+ "_descriptor.OneofDescriptor(\n" |
+ " name='$name$', full_name='$full_name$',\n" |
+ " index=$index$, containing_type=None, fields=[]),\n"); |
+ } |
+ printer_->Outdent(); |
+ printer_->Print("],\n"); |
// Serialization of proto |
DescriptorProto edp; |
PrintSerializedPbInterval(message_descriptor, edp); |
@@ -635,7 +737,12 @@ void Generator::PrintNestedDescriptors( |
// Prints all messages in |file|. |
void Generator::PrintMessages() const { |
for (int i = 0; i < file_->message_type_count(); ++i) { |
- PrintMessage(*file_->message_type(i)); |
+ vector<string> to_register; |
+ PrintMessage(*file_->message_type(i), "", &to_register); |
+ for (int j = 0; j < to_register.size(); ++j) { |
+ printer_->Print("_sym_db.RegisterMessage($name$)\n", "name", |
+ to_register[j]); |
+ } |
printer_->Print("\n"); |
} |
} |
@@ -647,33 +754,40 @@ void Generator::PrintMessages() const { |
// reflection.py will use to construct the meat of the class itself. |
// |
// Mutually recursive with PrintNestedMessages(). |
-void Generator::PrintMessage( |
- const Descriptor& message_descriptor) const { |
- printer_->Print("class $name$(_message.Message):\n", "name", |
- message_descriptor.name()); |
+// Collect nested message names to_register for the symbol_database. |
+void Generator::PrintMessage(const Descriptor& message_descriptor, |
+ const string& prefix, |
+ vector<string>* to_register) const { |
+ string qualified_name(prefix + message_descriptor.name()); |
+ to_register->push_back(qualified_name); |
+ printer_->Print( |
+ "$name$ = _reflection.GeneratedProtocolMessageType('$name$', " |
+ "(_message.Message,), dict(\n", |
+ "name", message_descriptor.name()); |
printer_->Indent(); |
- printer_->Print("__metaclass__ = _reflection.GeneratedProtocolMessageType\n"); |
- PrintNestedMessages(message_descriptor); |
+ |
+ PrintNestedMessages(message_descriptor, qualified_name + ".", to_register); |
map<string, string> m; |
m["descriptor_key"] = kDescriptorKey; |
m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor); |
- printer_->Print(m, "$descriptor_key$ = $descriptor_name$\n"); |
- |
- printer_->Print( |
- "\n" |
- "# @@protoc_insertion_point(class_scope:$full_name$)\n", |
- "full_name", message_descriptor.full_name()); |
- |
+ printer_->Print(m, "$descriptor_key$ = $descriptor_name$,\n"); |
+ printer_->Print("__module__ = '$module_name$'\n", |
+ "module_name", ModuleName(file_->name())); |
+ printer_->Print("# @@protoc_insertion_point(class_scope:$full_name$)\n", |
+ "full_name", message_descriptor.full_name()); |
+ printer_->Print("))\n"); |
printer_->Outdent(); |
} |
// Prints all nested messages within |containing_descriptor|. |
// Mutually recursive with PrintMessage(). |
-void Generator::PrintNestedMessages( |
- const Descriptor& containing_descriptor) const { |
+void Generator::PrintNestedMessages(const Descriptor& containing_descriptor, |
+ const string& prefix, |
+ vector<string>* to_register) const { |
for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) { |
printer_->Print("\n"); |
- PrintMessage(*containing_descriptor.nested_type(i)); |
+ PrintMessage(*containing_descriptor.nested_type(i), prefix, to_register); |
+ printer_->Print(",\n"); |
} |
} |
@@ -701,6 +815,23 @@ void Generator::FixForeignFieldsInDescriptor( |
const EnumDescriptor& enum_descriptor = *descriptor.enum_type(i); |
FixContainingTypeInDescriptor(enum_descriptor, &descriptor); |
} |
+ for (int i = 0; i < descriptor.oneof_decl_count(); ++i) { |
+ map<string, string> m; |
+ const OneofDescriptor* oneof = descriptor.oneof_decl(i); |
+ m["descriptor_name"] = ModuleLevelDescriptorName(descriptor); |
+ m["oneof_name"] = oneof->name(); |
+ for (int j = 0; j < oneof->field_count(); ++j) { |
+ m["field_name"] = oneof->field(j)->name(); |
+ printer_->Print( |
+ m, |
+ "$descriptor_name$.oneofs_by_name['$oneof_name$'].fields.append(\n" |
+ " $descriptor_name$.fields_by_name['$field_name$'])\n"); |
+ printer_->Print( |
+ m, |
+ "$descriptor_name$.fields_by_name['$field_name$'].containing_oneof = " |
+ "$descriptor_name$.oneofs_by_name['$oneof_name$']\n"); |
+ } |
+ } |
} |
void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const { |
@@ -714,6 +845,29 @@ void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const { |
printer_->Print(m, file_descriptor_template); |
} |
+void Generator::AddEnumToFileDescriptor( |
+ const EnumDescriptor& descriptor) const { |
+ map<string, string> m; |
+ m["descriptor_name"] = kDescriptorKey; |
+ m["enum_name"] = descriptor.name(); |
+ m["enum_descriptor_name"] = ModuleLevelDescriptorName(descriptor); |
+ const char file_descriptor_template[] = |
+ "$descriptor_name$.enum_types_by_name['$enum_name$'] = " |
+ "$enum_descriptor_name$\n"; |
+ printer_->Print(m, file_descriptor_template); |
+} |
+ |
+void Generator::AddExtensionToFileDescriptor( |
+ const FieldDescriptor& descriptor) const { |
+ map<string, string> m; |
+ m["descriptor_name"] = kDescriptorKey; |
+ m["field_name"] = descriptor.name(); |
+ const char file_descriptor_template[] = |
+ "$descriptor_name$.extensions_by_name['$field_name$'] = " |
+ "$field_name$\n"; |
+ printer_->Print(m, file_descriptor_template); |
+} |
+ |
// Sets any necessary message_type and enum_type attributes |
// for the Python version of |field|. |
// |
@@ -778,7 +932,7 @@ void Generator::FixContainingTypeInDescriptor( |
const string parent_name = ModuleLevelDescriptorName( |
*containing_descriptor); |
printer_->Print( |
- "$nested_name$.containing_type = $parent_name$;\n", |
+ "$nested_name$.containing_type = $parent_name$\n", |
"nested_name", nested_name, |
"parent_name", parent_name); |
} |
@@ -795,6 +949,12 @@ void Generator::FixForeignFieldsInDescriptors() const { |
for (int i = 0; i < file_->message_type_count(); ++i) { |
AddMessageToFileDescriptor(*file_->message_type(i)); |
} |
+ for (int i = 0; i < file_->enum_type_count(); ++i) { |
+ AddEnumToFileDescriptor(*file_->enum_type(i)); |
+ } |
+ for (int i = 0; i < file_->extension_count(); ++i) { |
+ AddExtensionToFileDescriptor(*file_->extension(i)); |
+ } |
printer_->Print("\n"); |
} |
@@ -875,8 +1035,10 @@ string Generator::OptionsValue( |
return "None"; |
} else { |
string full_class_name = "descriptor_pb2." + class_name; |
- return "_descriptor._ParseOptions(" + full_class_name + "(), '" |
- + CEscape(serialized_options)+ "')"; |
+//##!PY25 return "_descriptor._ParseOptions(" + full_class_name + "(), b'" |
+//##!PY25 + CEscape(serialized_options)+ "')"; |
+ return "_descriptor._ParseOptions(" + full_class_name + "(), _b('" //##PY25 |
+ + CEscape(serialized_options)+ "'))"; //##PY25 |
} |
} |
@@ -979,7 +1141,7 @@ string Generator::ModuleLevelDescriptorName( |
// We now have the name relative to its own module. Also qualify with |
// the module name iff this descriptor is from a different .proto file. |
if (descriptor.file() != file_) { |
- name = ModuleName(descriptor.file()->name()) + "." + name; |
+ name = ModuleAlias(descriptor.file()->name()) + "." + name; |
} |
return name; |
} |
@@ -991,7 +1153,7 @@ string Generator::ModuleLevelDescriptorName( |
string Generator::ModuleLevelMessageName(const Descriptor& descriptor) const { |
string name = NamePrefixedWithNestedTypes(descriptor, "."); |
if (descriptor.file() != file_) { |
- name = ModuleName(descriptor.file()->name()) + "." + name; |
+ name = ModuleAlias(descriptor.file()->name()) + "." + name; |
} |
return name; |
} |
@@ -1004,7 +1166,7 @@ string Generator::ModuleLevelServiceDescriptorName( |
UpperString(&name); |
name = "_" + name; |
if (descriptor.file() != file_) { |
- name = ModuleName(descriptor.file()->name()) + "." + name; |
+ name = ModuleAlias(descriptor.file()->name()) + "." + name; |
} |
return name; |
} |
@@ -1151,6 +1313,18 @@ void Generator::FixOptionsForMessage(const Descriptor& descriptor) const { |
} |
} |
+// If a dependency forwards other files through public dependencies, let's |
+// copy over the corresponding module aliases. |
+void Generator::CopyPublicDependenciesAliases( |
+ const string& copy_from, const FileDescriptor* file) const { |
+ for (int i = 0; i < file->public_dependency_count(); ++i) { |
+ string module_alias = ModuleAlias(file->public_dependency(i)->name()); |
+ printer_->Print("$alias$ = $copy_from$.$alias$\n", "alias", module_alias, |
+ "copy_from", copy_from); |
+ CopyPublicDependenciesAliases(copy_from, file->public_dependency(i)); |
+ } |
+} |
+ |
} // namespace python |
} // namespace compiler |
} // namespace protobuf |