123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449 |
- // Protocol Buffers - Google's data interchange format
- // Copyright 2008 Google Inc. All rights reserved.
- // 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
- // met:
- //
- // * Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above
- // copyright notice, this list of conditions and the following disclaimer
- // in the documentation and/or other materials provided with the
- // distribution.
- // * Neither the name of Google Inc. nor the names of its
- // contributors may be used to endorse or promote products derived from
- // this software without specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- // (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
- // largely be constructed at runtime via the metaclass in reflection.py.
- // In other words, our job is basically to output a Python equivalent
- // of the C++ *Descriptor objects, and fix up all circular references
- // within these objects.
- //
- // Note that the runtime performance of protocol message classes created in
- // this way is expected to be lousy. The plan is to create an alternate
- // generator that outputs a Python/C extension module that lets
- // performance-minded Python code leverage the fast C++ implementation
- // directly.
- #include <algorithm>
- #include <limits>
- #include <map>
- #include <memory>
- #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>
- #include <google/protobuf/io/zero_copy_stream.h>
- #include <google/protobuf/descriptor.h>
- #include <google/protobuf/stubs/strutil.h>
- #include <google/protobuf/stubs/substitute.h>
- namespace google {
- namespace protobuf {
- namespace compiler {
- namespace python {
- namespace {
- bool StrEndsWith(StringPiece sp, StringPiece x) {
- return sp.size() >= x.size() && sp.substr(sp.size() - x.size()) == x;
- }
- // Returns a copy of |filename| with any trailing ".protodevel" or ".proto
- // suffix stripped.
- // TODO(robinson): Unify with copy in compiler/cpp/internal/helpers.cc.
- string StripProto(const string& filename) {
- const char* suffix =
- StrEndsWith(filename, ".protodevel") ? ".protodevel" : ".proto";
- return StripSuffixString(filename, suffix);
- }
- // Returns the Python module name expected for a given .proto filename.
- string ModuleName(const string& filename) {
- string basename = StripProto(filename);
- ReplaceCharacters(&basename, "-", '_');
- ReplaceCharacters(&basename, "/", '.');
- return basename + "_pb2";
- }
- // Returns the alias we assign to the module of the given .proto filename
- // when importing. See testPackageInitializationImport in
- // net/proto2/python/internal/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;
- }
- // Keywords reserved by the Python language.
- const char* const kKeywords[] = {
- "False", "None", "True", "and", "as", "assert", "break",
- "class", "continue", "def", "del", "elif", "else", "except",
- "finally", "for", "from", "global", "if", "import", "in",
- "is", "lambda", "nonlocal", "not", "or", "pass", "raise",
- "return", "try", "while", "with", "yield",
- };
- const char* const* kKeywordsEnd =
- kKeywords + (sizeof(kKeywords) / sizeof(kKeywords[0]));
- bool ContainsPythonKeyword(const string& module_name) {
- std::vector<string> tokens = Split(module_name, ".");
- for (int i = 0; i < tokens.size(); ++i) {
- if (std::find(kKeywords, kKeywordsEnd, tokens[i]) != kKeywordsEnd) {
- return true;
- }
- }
- return false;
- }
- // 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|.
- template <typename DescriptorT>
- string NamePrefixedWithNestedTypes(const DescriptorT& descriptor,
- const string& separator) {
- string name = descriptor.name();
- for (const Descriptor* current = descriptor.containing_type();
- current != NULL; current = current->containing_type()) {
- name = current->name() + separator + name;
- }
- return name;
- }
- // Name of the class attribute where we store the Python
- // descriptor.Descriptor instance for the generated class.
- // Must stay consistent with the _DESCRIPTOR_KEY constant
- // in proto2/public/reflection.py.
- 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 &&
- file->options().py_generic_services();
- }
- // Prints the common boilerplate needed at the top of every .py
- // file output by this generator.
- void PrintTopBoilerplate(
- io::Printer* printer, const FileDescriptor* file, bool descriptor_proto) {
- // TODO(robinson): Allow parameterization of Python version?
- printer->Print(
- "# -*- coding: utf-8 -*-\n"
- "# 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)) {
- 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"
- "from google.protobuf import symbol_database as "
- "_symbol_database\n");
- if (HasGenericServices(file)) {
- printer->Print(
- "from google.protobuf import service as _service\n"
- "from google.protobuf import service_reflection\n");
- }
- printer->Print(
- "# @@protoc_insertion_point(imports)\n\n"
- "_sym_db = _symbol_database.Default()\n");
- printer->Print("\n\n");
- }
- // Returns a Python literal giving the default value for a field.
- // If the field specifies no explicit default value, we'll return
- // the default default value for the field type (zero for numbers,
- // empty string for strings, empty list for repeated fields, and
- // None for non-repeated, composite fields).
- //
- // TODO(robinson): Unify with code from
- // //compiler/cpp/internal/primitive_field.cc
- // //compiler/cpp/internal/enum_field.cc
- // //compiler/cpp/internal/string_field.cc
- string StringifyDefaultValue(const FieldDescriptor& field) {
- if (field.is_repeated()) {
- return "[]";
- }
- switch (field.cpp_type()) {
- case FieldDescriptor::CPPTYPE_INT32:
- return StrCat(field.default_value_int32());
- case FieldDescriptor::CPPTYPE_UINT32:
- return StrCat(field.default_value_uint32());
- case FieldDescriptor::CPPTYPE_INT64:
- return StrCat(field.default_value_int64());
- case FieldDescriptor::CPPTYPE_UINT64:
- return StrCat(field.default_value_uint64());
- case FieldDescriptor::CPPTYPE_DOUBLE: {
- double value = field.default_value_double();
- if (value == std::numeric_limits<double>::infinity()) {
- // Python pre-2.6 on Windows does not parse "inf" correctly. However,
- // a numeric literal that is too big for a double will become infinity.
- return "1e10000";
- } else if (value == -std::numeric_limits<double>::infinity()) {
- // See above.
- return "-1e10000";
- } else if (value != value) {
- // infinity * 0 = nan
- return "(1e10000 * 0)";
- } else {
- return "float(" + SimpleDtoa(value) + ")";
- }
- }
- case FieldDescriptor::CPPTYPE_FLOAT: {
- float value = field.default_value_float();
- if (value == std::numeric_limits<float>::infinity()) {
- // Python pre-2.6 on Windows does not parse "inf" correctly. However,
- // a numeric literal that is too big for a double will become infinity.
- return "1e10000";
- } else if (value == -std::numeric_limits<float>::infinity()) {
- // See above.
- return "-1e10000";
- } else if (value != value) {
- // infinity - infinity = nan
- return "(1e10000 * 0)";
- } else {
- return "float(" + SimpleFtoa(value) + ")";
- }
- }
- case FieldDescriptor::CPPTYPE_BOOL:
- return field.default_value_bool() ? "True" : "False";
- case FieldDescriptor::CPPTYPE_ENUM:
- return StrCat(field.default_value_enum()->number());
- case FieldDescriptor::CPPTYPE_STRING:
- //##!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.)
- GOOGLE_LOG(FATAL) << "Not reached.";
- 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
- Generator::Generator() : file_(NULL) {
- }
- Generator::~Generator() {
- }
- bool Generator::Generate(const FileDescriptor* file,
- const string& parameter,
- GeneratorContext* context,
- string* error) const {
- // Completely serialize all Generate() calls on this instance. The
- // thread-safety constraints of the CodeGenerator interface aren't clear so
- // just be as conservative as possible. It's easier to relax this later if
- // we need to, but I doubt it will be an issue.
- // TODO(kenton): The proper thing to do would be to allocate any state on
- // the stack and use that, so that the Generator class itself does not need
- // to have any mutable members. Then it is implicitly thread-safe.
- MutexLock lock(&mutex_);
- file_ = file;
- string module_name = ModuleName(file->name());
- string filename = module_name;
- ReplaceCharacters(&filename, ".", '/');
- filename += ".py";
- FileDescriptorProto fdp;
- file_->CopyTo(&fdp);
- fdp.SerializeToString(&file_descriptor_serialized_);
- std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
- GOOGLE_CHECK(output.get());
- io::Printer printer(output.get(), '$');
- printer_ = &printer;
- PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto());
- PrintImports();
- PrintFileDescriptor();
- PrintTopLevelEnums();
- PrintTopLevelExtensions();
- PrintAllNestedEnumsInFile();
- PrintMessageDescriptors();
- FixForeignFieldsInDescriptors();
- PrintMessages();
- // We have to fix up the extensions after the message classes themselves,
- // 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.
- // This does not apply to services because they are not used by extensions.
- FixAllDescriptorOptions();
- PrintServiceDescriptors();
- if (HasGenericServices(file)) {
- PrintServices();
- }
- printer.Print(
- "# @@protoc_insertion_point(module_scope)\n");
- return !printer.failed();
- }
- // BEGIN GOOGLE-INTERNAL
- // Strip the google3.third_party.py. prefix off of a module name as we
- // NEVER want that invalid module import path to be generated in google3.
- // Our sys.path has google3/third_party/py/ in it. All modules from
- // that tree need to be imported using just their own name.
- // See http://go/ThirdPartyPython
- void StripThirdPartyPy(string* module_name) {
- const string third_party_py_prefix = "google3.third_party.py.";
- int len = third_party_py_prefix.length();
- if (module_name->compare(0, len,
- third_party_py_prefix, 0,
- len) == 0) {
- *module_name = module_name->erase(0, len);
- }
- }
- // END GOOGLE-INTERNAL
- // Prints Python imports for all modules imported by |file|.
- void Generator::PrintImports() const {
- for (int i = 0; i < file_->dependency_count(); ++i) {
- const string& filename = file_->dependency(i)->name();
- string module_name = ModuleName(filename);
- string module_alias = ModuleAlias(filename);
- // BEGIN GOOGLE-INTERNAL
- StripThirdPartyPy(&module_name);
- // END GOOGLE-INTERNAL
- if (ContainsPythonKeyword(module_name)) {
- // If the module path contains a Python keyword, we have to quote the
- // module name and import it using importlib. Otherwise the usual kind of
- // import statement would result in a syntax error from the presence of
- // the keyword.
- printer_->Print("import importlib\n");
- printer_->Print("$alias$ = importlib.import_module('$name$')\n", "alias",
- module_alias, "name", module_name);
- } else {
- int last_dot_pos = module_name.rfind('.');
- string import_statement;
- 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.
- import_statement = "import " + module_name;
- } else {
- import_statement = "from " + module_name.substr(0, last_dot_pos) +
- " import " + module_name.substr(last_dot_pos + 1);
- }
- printer_->Print("$statement$ as $alias$\n", "statement", import_statement,
- "alias", module_alias);
- }
- CopyPublicDependenciesAliases(module_alias, file_->dependency(i));
- }
- 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());
- // BEGIN GOOGLE-INTERNAL
- StripThirdPartyPy(&module_name);
- // END GOOGLE-INTERNAL
- printer_->Print("from $module$ import *\n", "module", module_name);
- }
- printer_->Print("\n");
- }
- // Prints the single file descriptor for this file.
- void Generator::PrintFileDescriptor() const {
- std::map<string, string> m;
- m["descriptor_name"] = kDescriptorKey;
- m["name"] = file_->name();
- m["package"] = file_->package();
- m["syntax"] = StringifySyntax(file_->syntax());
- m["options"] = OptionsValue(file_->options().SerializeAsString());
- const char file_descriptor_template[] =
- "$descriptor_name$ = _descriptor.FileDescriptor(\n"
- " name='$name$',\n"
- " package='$package$',\n"
- " syntax='$syntax$',\n"
- " serialized_options=$options$,\n";
- printer_->Print(m, file_descriptor_template);
- printer_->Indent();
- printer_->Print(
- //##!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("]");
- }
- if (file_->public_dependency_count() > 0) {
- printer_->Print(",\npublic_dependencies=[");
- for (int i = 0; i < file_->public_dependency_count(); ++i) {
- string module_alias = ModuleAlias(file_->public_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("\n");
- }
- // Prints descriptors and module-level constants for all top-level
- // enums defined in |file|.
- void Generator::PrintTopLevelEnums() const {
- std::vector<std::pair<string, int> > top_level_enum_values;
- 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) {
- const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(j);
- top_level_enum_values.push_back(
- std::make_pair(value_descriptor.name(), value_descriptor.number()));
- }
- }
- for (int i = 0; i < top_level_enum_values.size(); ++i) {
- printer_->Print("$name$ = $value$\n", "name",
- top_level_enum_values[i].first, "value",
- StrCat(top_level_enum_values[i].second));
- }
- printer_->Print("\n");
- }
- // Prints all enums contained in all message types in |file|.
- void Generator::PrintAllNestedEnumsInFile() const {
- for (int i = 0; i < file_->message_type_count(); ++i) {
- PrintNestedEnums(*file_->message_type(i));
- }
- }
- // Prints a Python statement assigning the appropriate module-level
- // enum name to a Python EnumDescriptor object equivalent to
- // enum_descriptor.
- void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const {
- std::map<string, string> m;
- 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;
- const char enum_descriptor_template[] =
- "$descriptor_name$ = _descriptor.EnumDescriptor(\n"
- " name='$name$',\n"
- " full_name='$full_name$',\n"
- " filename=None,\n"
- " file=$file$,\n"
- " values=[\n";
- string options_string;
- enum_descriptor.options().SerializeToString(&options_string);
- printer_->Print(m, enum_descriptor_template);
- printer_->Indent();
- printer_->Indent();
- for (int i = 0; i < enum_descriptor.value_count(); ++i) {
- PrintEnumValueDescriptor(*enum_descriptor.value(i));
- printer_->Print(",\n");
- }
- printer_->Outdent();
- printer_->Print("],\n");
- printer_->Print("containing_type=None,\n");
- printer_->Print("serialized_options=$options_value$,\n",
- "options_value",
- OptionsValue(options_string));
- EnumDescriptorProto edp;
- PrintSerializedPbInterval(enum_descriptor, edp);
- printer_->Outdent();
- printer_->Print(")\n");
- printer_->Print("_sym_db.RegisterEnumDescriptor($name$)\n", "name",
- module_level_descriptor_name);
- printer_->Print("\n");
- }
- // Recursively prints enums in nested types within descriptor, then
- // prints enums contained at the top level in descriptor.
- void Generator::PrintNestedEnums(const Descriptor& descriptor) const {
- for (int i = 0; i < descriptor.nested_type_count(); ++i) {
- PrintNestedEnums(*descriptor.nested_type(i));
- }
- for (int i = 0; i < descriptor.enum_type_count(); ++i) {
- PrintEnum(*descriptor.enum_type(i));
- }
- }
- void Generator::PrintTopLevelExtensions() const {
- const bool is_extension = true;
- for (int i = 0; i < file_->extension_count(); ++i) {
- const FieldDescriptor& extension_field = *file_->extension(i);
- string constant_name = extension_field.name() + "_FIELD_NUMBER";
- UpperString(&constant_name);
- printer_->Print("$constant_name$ = $number$\n", "constant_name",
- constant_name, "number",
- StrCat(extension_field.number()));
- printer_->Print("$name$ = ", "name", extension_field.name());
- PrintFieldDescriptor(extension_field, is_extension);
- printer_->Print("\n");
- }
- printer_->Print("\n");
- }
- // Prints Python equivalents of all Descriptors in |file|.
- void Generator::PrintMessageDescriptors() const {
- for (int i = 0; i < file_->message_type_count(); ++i) {
- PrintDescriptor(*file_->message_type(i));
- printer_->Print("\n");
- }
- }
- void Generator::PrintServiceDescriptors() const {
- for (int i = 0; i < file_->service_count(); ++i) {
- PrintServiceDescriptor(*file_->service(i));
- AddServiceToFileDescriptor(*file_->service(i));
- printer_->Print("\n");
- }
- }
- void Generator::PrintServices() const {
- for (int i = 0; i < file_->service_count(); ++i) {
- PrintServiceClass(*file_->service(i));
- PrintServiceStub(*file_->service(i));
- printer_->Print("\n");
- }
- }
- void Generator::PrintServiceDescriptor(
- const ServiceDescriptor& descriptor) const {
- printer_->Print("\n");
- string service_name = ModuleLevelServiceDescriptorName(descriptor);
- string options_string;
- descriptor.options().SerializeToString(&options_string);
- printer_->Print(
- "$service_name$ = _descriptor.ServiceDescriptor(\n",
- "service_name", service_name);
- printer_->Indent();
- std::map<string, string> m;
- m["name"] = descriptor.name();
- m["full_name"] = descriptor.full_name();
- m["file"] = kDescriptorKey;
- m["index"] = StrCat(descriptor.index());
- m["options_value"] = OptionsValue(options_string);
- const char required_function_arguments[] =
- "name='$name$',\n"
- "full_name='$full_name$',\n"
- "file=$file$,\n"
- "index=$index$,\n"
- "serialized_options=$options_value$,\n";
- printer_->Print(m, required_function_arguments);
- ServiceDescriptorProto sdp;
- PrintSerializedPbInterval(descriptor, sdp);
- printer_->Print("methods=[\n");
- for (int i = 0; i < descriptor.method_count(); ++i) {
- const MethodDescriptor* method = descriptor.method(i);
- method->options().SerializeToString(&options_string);
- m.clear();
- m["name"] = method->name();
- m["full_name"] = method->full_name();
- m["index"] = StrCat(method->index());
- m["serialized_options"] = CEscape(options_string);
- m["input_type"] = ModuleLevelDescriptorName(*(method->input_type()));
- m["output_type"] = ModuleLevelDescriptorName(*(method->output_type()));
- m["options_value"] = OptionsValue(options_string);
- printer_->Print("_descriptor.MethodDescriptor(\n");
- printer_->Indent();
- printer_->Print(
- m,
- "name='$name$',\n"
- "full_name='$full_name$',\n"
- "index=$index$,\n"
- "containing_service=None,\n"
- "input_type=$input_type$,\n"
- "output_type=$output_type$,\n"
- "serialized_options=$options_value$,\n");
- printer_->Outdent();
- printer_->Print("),\n");
- }
- printer_->Outdent();
- printer_->Print("])\n");
- printer_->Print("_sym_db.RegisterServiceDescriptor($name$)\n", "name",
- service_name);
- printer_->Print("\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_name$ = service_reflection.GeneratedServiceType("
- "'$class_name$', (_service.Service,), dict(\n",
- "class_name", descriptor.name());
- printer_->Indent();
- Generator::PrintDescriptorKeyAndModuleName(descriptor);
- printer_->Print("))\n\n");
- printer_->Outdent();
- }
- void Generator::PrintServiceStub(const ServiceDescriptor& descriptor) const {
- // Print the service stub.
- printer_->Print("$class_name$_Stub = "
- "service_reflection.GeneratedServiceStubType("
- "'$class_name$_Stub', ($class_name$,), dict(\n",
- "class_name", descriptor.name());
- printer_->Indent();
- Generator::PrintDescriptorKeyAndModuleName(descriptor);
- printer_->Print("))\n\n");
- printer_->Outdent();
- }
- // Prints statement assigning ModuleLevelDescriptorName(message_descriptor)
- // to a Python Descriptor object for message_descriptor.
- //
- // Mutually recursive with PrintNestedDescriptors().
- void Generator::PrintDescriptor(const Descriptor& message_descriptor) const {
- PrintNestedDescriptors(message_descriptor);
- printer_->Print("\n");
- printer_->Print("$descriptor_name$ = _descriptor.Descriptor(\n",
- "descriptor_name",
- ModuleLevelDescriptorName(message_descriptor));
- printer_->Indent();
- std::map<string, string> m;
- m["name"] = message_descriptor.name();
- m["full_name"] = message_descriptor.full_name();
- m["file"] = kDescriptorKey;
- const char required_function_arguments[] =
- "name='$name$',\n"
- "full_name='$full_name$',\n"
- "filename=None,\n"
- "file=$file$,\n"
- "containing_type=None,\n";
- printer_->Print(m, required_function_arguments);
- PrintFieldsInDescriptor(message_descriptor);
- PrintExtensionsInDescriptor(message_descriptor);
- // Nested types
- printer_->Print("nested_types=[");
- for (int i = 0; i < message_descriptor.nested_type_count(); ++i) {
- const string nested_name = ModuleLevelDescriptorName(
- *message_descriptor.nested_type(i));
- printer_->Print("$name$, ", "name", nested_name);
- }
- printer_->Print("],\n");
- // Enum types
- printer_->Print("enum_types=[\n");
- printer_->Indent();
- for (int i = 0; i < message_descriptor.enum_type_count(); ++i) {
- const string descriptor_name = ModuleLevelDescriptorName(
- *message_descriptor.enum_type(i));
- printer_->Print(descriptor_name.c_str());
- printer_->Print(",\n");
- }
- printer_->Outdent();
- printer_->Print("],\n");
- string options_string;
- message_descriptor.options().SerializeToString(&options_string);
- printer_->Print(
- "serialized_options=$options_value$,\n"
- "is_extendable=$extendable$,\n"
- "syntax='$syntax$'",
- "options_value", OptionsValue(options_string),
- "extendable", message_descriptor.extension_range_count() > 0 ?
- "True" : "False",
- "syntax", StringifySyntax(message_descriptor.file()->syntax()));
- printer_->Print(",\n");
- // Extension ranges
- printer_->Print("extension_ranges=[");
- for (int i = 0; i < message_descriptor.extension_range_count(); ++i) {
- const Descriptor::ExtensionRange* range =
- message_descriptor.extension_range(i);
- printer_->Print("($start$, $end$), ", "start", StrCat(range->start),
- "end", StrCat(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);
- std::map<string, string> m;
- m["name"] = desc->name();
- m["full_name"] = desc->full_name();
- m["index"] = StrCat(desc->index());
- string options_string =
- OptionsValue(desc->options().SerializeAsString());
- if (options_string == "None") {
- m["serialized_options"] = "";
- } else {
- m["serialized_options"] = ", serialized_options=" + options_string;
- }
- printer_->Print(
- m,
- "_descriptor.OneofDescriptor(\n"
- " name='$name$', full_name='$full_name$',\n"
- " index=$index$, containing_type=None, "
- "fields=[]$serialized_options$),\n");
- }
- printer_->Outdent();
- printer_->Print("],\n");
- // Serialization of proto
- DescriptorProto edp;
- PrintSerializedPbInterval(message_descriptor, edp);
- printer_->Outdent();
- printer_->Print(")\n");
- }
- // Prints Python Descriptor objects for all nested types contained in
- // message_descriptor.
- //
- // Mutually recursive with PrintDescriptor().
- void Generator::PrintNestedDescriptors(
- const Descriptor& containing_descriptor) const {
- for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) {
- PrintDescriptor(*containing_descriptor.nested_type(i));
- }
- }
- // Prints all messages in |file|.
- void Generator::PrintMessages() const {
- for (int i = 0; i < file_->message_type_count(); ++i) {
- std::vector<string> to_register;
- PrintMessage(*file_->message_type(i), "", &to_register, false);
- for (int j = 0; j < to_register.size(); ++j) {
- printer_->Print("_sym_db.RegisterMessage($name$)\n", "name",
- to_register[j]);
- }
- printer_->Print("\n");
- }
- }
- // Prints a Python class for the given message descriptor. We defer to the
- // metaclass to do almost all of the work of actually creating a useful class.
- // The purpose of this function and its many helper functions above is merely
- // to output a Python version of the descriptors, which the metaclass in
- // reflection.py will use to construct the meat of the class itself.
- //
- // Mutually recursive with PrintNestedMessages().
- // Collect nested message names to_register for the symbol_database.
- void Generator::PrintMessage(const Descriptor& message_descriptor,
- const string& prefix,
- std::vector<string>* to_register,
- bool is_nested) const {
- string qualified_name(prefix + message_descriptor.name());
- to_register->push_back(qualified_name);
- if (is_nested) {
- printer_->Print(
- "'$name$' : _reflection.GeneratedProtocolMessageType('$name$', "
- "(_message.Message,), {\n",
- "name", message_descriptor.name());
- } else {
- printer_->Print(
- "$name$ = _reflection.GeneratedProtocolMessageType('$name$', "
- "(_message.Message,), {\n",
- "name", message_descriptor.name());
- }
- printer_->Indent();
- PrintNestedMessages(message_descriptor, qualified_name + ".", to_register);
- std::map<string, string> m;
- m["descriptor_key"] = kDescriptorKey;
- m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor);
- 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 string& prefix,
- std::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), prefix, to_register,
- true);
- printer_->Print(",\n");
- }
- }
- // Recursively fixes foreign fields in all nested types in |descriptor|, then
- // sets the message_type and enum_type of all message and enum fields to point
- // to their respective descriptors.
- // Args:
- // descriptor: descriptor to print fields for.
- // containing_descriptor: if descriptor is a nested type, this is its
- // containing type, or NULL if this is a root/top-level type.
- void Generator::FixForeignFieldsInDescriptor(
- const Descriptor& descriptor,
- const Descriptor* containing_descriptor) const {
- for (int i = 0; i < descriptor.nested_type_count(); ++i) {
- FixForeignFieldsInDescriptor(*descriptor.nested_type(i), &descriptor);
- }
- for (int i = 0; i < descriptor.field_count(); ++i) {
- const FieldDescriptor& field_descriptor = *descriptor.field(i);
- FixForeignFieldsInField(&descriptor, field_descriptor, "fields_by_name");
- }
- FixContainingTypeInDescriptor(descriptor, containing_descriptor);
- for (int i = 0; i < descriptor.enum_type_count(); ++i) {
- const EnumDescriptor& enum_descriptor = *descriptor.enum_type(i);
- FixContainingTypeInDescriptor(enum_descriptor, &descriptor);
- }
- for (int i = 0; i < descriptor.oneof_decl_count(); ++i) {
- std::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 {
- std::map<string, string> m;
- m["descriptor_name"] = kDescriptorKey;
- m["message_name"] = descriptor.name();
- m["message_descriptor_name"] = ModuleLevelDescriptorName(descriptor);
- const char file_descriptor_template[] =
- "$descriptor_name$.message_types_by_name['$message_name$'] = "
- "$message_descriptor_name$\n";
- printer_->Print(m, file_descriptor_template);
- }
- void Generator::AddServiceToFileDescriptor(
- const ServiceDescriptor& descriptor) const {
- std::map<string, string> m;
- m["descriptor_name"] = kDescriptorKey;
- m["service_name"] = descriptor.name();
- m["service_descriptor_name"] = ModuleLevelServiceDescriptorName(descriptor);
- const char file_descriptor_template[] =
- "$descriptor_name$.services_by_name['$service_name$'] = "
- "$service_descriptor_name$\n";
- printer_->Print(m, file_descriptor_template);
- }
- void Generator::AddEnumToFileDescriptor(
- const EnumDescriptor& descriptor) const {
- std::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 {
- std::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|.
- //
- // containing_type may be NULL, in which case this is a module-level field.
- //
- // python_dict_name is the name of the Python dict where we should
- // look the field up in the containing type. (e.g., fields_by_name
- // or extensions_by_name). We ignore python_dict_name if containing_type
- // is NULL.
- void Generator::FixForeignFieldsInField(const Descriptor* containing_type,
- const FieldDescriptor& field,
- const string& python_dict_name) const {
- const string field_referencing_expression = FieldReferencingExpression(
- containing_type, field, python_dict_name);
- std::map<string, string> m;
- m["field_ref"] = field_referencing_expression;
- const Descriptor* foreign_message_type = field.message_type();
- if (foreign_message_type) {
- m["foreign_type"] = ModuleLevelDescriptorName(*foreign_message_type);
- printer_->Print(m, "$field_ref$.message_type = $foreign_type$\n");
- }
- const EnumDescriptor* enum_type = field.enum_type();
- if (enum_type) {
- m["enum_type"] = ModuleLevelDescriptorName(*enum_type);
- printer_->Print(m, "$field_ref$.enum_type = $enum_type$\n");
- }
- }
- // Returns the module-level expression for the given FieldDescriptor.
- // Only works for fields in the .proto file this Generator is generating for.
- //
- // containing_type may be NULL, in which case this is a module-level field.
- //
- // python_dict_name is the name of the Python dict where we should
- // look the field up in the containing type. (e.g., fields_by_name
- // or extensions_by_name). We ignore python_dict_name if containing_type
- // is NULL.
- string Generator::FieldReferencingExpression(
- const Descriptor* containing_type,
- const FieldDescriptor& field,
- const string& python_dict_name) const {
- // We should only ever be looking up fields in the current file.
- // The only things we refer to from other files are message descriptors.
- GOOGLE_CHECK_EQ(field.file(), file_) << field.file()->name() << " vs. "
- << file_->name();
- if (!containing_type) {
- return field.name();
- }
- return strings::Substitute(
- "$0.$1['$2']",
- ModuleLevelDescriptorName(*containing_type),
- python_dict_name, field.name());
- }
- // Prints containing_type for nested descriptors or enum descriptors.
- template <typename DescriptorT>
- void Generator::FixContainingTypeInDescriptor(
- const DescriptorT& descriptor,
- const Descriptor* containing_descriptor) const {
- if (containing_descriptor != NULL) {
- const string nested_name = ModuleLevelDescriptorName(descriptor);
- const string parent_name = ModuleLevelDescriptorName(
- *containing_descriptor);
- printer_->Print(
- "$nested_name$.containing_type = $parent_name$\n",
- "nested_name", nested_name,
- "parent_name", parent_name);
- }
- }
- // Prints statements setting the message_type and enum_type fields in the
- // Python descriptor objects we've already output in ths file. We must
- // do this in a separate step due to circular references (otherwise, we'd
- // just set everything in the initial assignment statements).
- void Generator::FixForeignFieldsInDescriptors() const {
- for (int i = 0; i < file_->message_type_count(); ++i) {
- FixForeignFieldsInDescriptor(*file_->message_type(i), NULL);
- }
- 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));
- }
- // TODO(jieluo): Move this register to PrintFileDescriptor() when
- // FieldDescriptor.file is added in generated file.
- printer_->Print("_sym_db.RegisterFileDescriptor($name$)\n", "name",
- kDescriptorKey);
- printer_->Print("\n");
- }
- // We need to not only set any necessary message_type fields, but
- // also need to call RegisterExtension() on each message we're
- // extending.
- void Generator::FixForeignFieldsInExtensions() const {
- // Top-level extensions.
- for (int i = 0; i < file_->extension_count(); ++i) {
- FixForeignFieldsInExtension(*file_->extension(i));
- }
- // Nested extensions.
- for (int i = 0; i < file_->message_type_count(); ++i) {
- FixForeignFieldsInNestedExtensions(*file_->message_type(i));
- }
- printer_->Print("\n");
- }
- void Generator::FixForeignFieldsInExtension(
- const FieldDescriptor& extension_field) const {
- GOOGLE_CHECK(extension_field.is_extension());
- // extension_scope() will be NULL for top-level extensions, which is
- // exactly what FixForeignFieldsInField() wants.
- FixForeignFieldsInField(extension_field.extension_scope(), extension_field,
- "extensions_by_name");
- std::map<string, string> m;
- // Confusingly, for FieldDescriptors that happen to be extensions,
- // containing_type() means "extended type."
- // On the other hand, extension_scope() will give us what we normally
- // mean by containing_type().
- m["extended_message_class"] = ModuleLevelMessageName(
- *extension_field.containing_type());
- m["field"] = FieldReferencingExpression(extension_field.extension_scope(),
- extension_field,
- "extensions_by_name");
- printer_->Print(m, "$extended_message_class$.RegisterExtension($field$)\n");
- }
- void Generator::FixForeignFieldsInNestedExtensions(
- const Descriptor& descriptor) const {
- // Recursively fix up extensions in all nested types.
- for (int i = 0; i < descriptor.nested_type_count(); ++i) {
- FixForeignFieldsInNestedExtensions(*descriptor.nested_type(i));
- }
- // Fix up extensions directly contained within this type.
- for (int i = 0; i < descriptor.extension_count(); ++i) {
- FixForeignFieldsInExtension(*descriptor.extension(i));
- }
- }
- // Returns a Python expression that instantiates a Python EnumValueDescriptor
- // object for the given C++ descriptor.
- void Generator::PrintEnumValueDescriptor(
- const EnumValueDescriptor& descriptor) const {
- // TODO(robinson): Fix up EnumValueDescriptor "type" fields.
- // More circular references. ::sigh::
- string options_string;
- descriptor.options().SerializeToString(&options_string);
- std::map<string, string> m;
- m["name"] = descriptor.name();
- m["index"] = StrCat(descriptor.index());
- m["number"] = StrCat(descriptor.number());
- m["options"] = OptionsValue(options_string);
- printer_->Print(
- m,
- "_descriptor.EnumValueDescriptor(\n"
- " name='$name$', index=$index$, number=$number$,\n"
- " serialized_options=$options$,\n"
- " type=None)");
- }
- // Returns a CEscaped string of serialized_options.
- string Generator::OptionsValue(const string& serialized_options) const {
- if (serialized_options.length() == 0 || GeneratingDescriptorProto()) {
- return "None";
- } else {
- //##!PY25 return "b'('" + CEscape(serialized_options)+ "')";
- return "_b('"+ CEscape(serialized_options) + "')"; //##PY25
- }
- }
- // Prints an expression for a Python FieldDescriptor for |field|.
- void Generator::PrintFieldDescriptor(
- const FieldDescriptor& field, bool is_extension) const {
- string options_string;
- field.options().SerializeToString(&options_string);
- std::map<string, string> m;
- m["name"] = field.name();
- m["full_name"] = field.full_name();
- m["index"] = StrCat(field.index());
- m["number"] = StrCat(field.number());
- m["type"] = StrCat(field.type());
- m["cpp_type"] = StrCat(field.cpp_type());
- m["label"] = StrCat(field.label());
- m["has_default_value"] = field.has_default_value() ? "True" : "False";
- m["default_value"] = StringifyDefaultValue(field);
- m["is_extension"] = is_extension ? "True" : "False";
- m["serialized_options"] = OptionsValue(options_string);
- m["json_name"] = field.has_json_name() ?
- ", json_name='" + field.json_name() + "'": "";
- // We always set message_type and enum_type to None at this point, and then
- // these fields in correctly after all referenced descriptors have been
- // defined and/or imported (see FixForeignFieldsInDescriptors()).
- const char field_descriptor_decl[] =
- "_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"
- " message_type=None, enum_type=None, containing_type=None,\n"
- " is_extension=$is_extension$, extension_scope=None,\n"
- " serialized_options=$serialized_options$$json_name$, file=DESCRIPTOR)";
- printer_->Print(m, field_descriptor_decl);
- }
- // Helper for Print{Fields,Extensions}InDescriptor().
- void Generator::PrintFieldDescriptorsInDescriptor(
- const Descriptor& message_descriptor,
- bool is_extension,
- const string& list_variable_name,
- int (Descriptor::*CountFn)() const,
- const FieldDescriptor* (Descriptor::*GetterFn)(int) const) const {
- printer_->Print("$list$=[\n", "list", list_variable_name);
- printer_->Indent();
- for (int i = 0; i < (message_descriptor.*CountFn)(); ++i) {
- PrintFieldDescriptor(*(message_descriptor.*GetterFn)(i),
- is_extension);
- printer_->Print(",\n");
- }
- printer_->Outdent();
- printer_->Print("],\n");
- }
- // Prints a statement assigning "fields" to a list of Python FieldDescriptors,
- // one for each field present in message_descriptor.
- void Generator::PrintFieldsInDescriptor(
- const Descriptor& message_descriptor) const {
- const bool is_extension = false;
- PrintFieldDescriptorsInDescriptor(
- message_descriptor, is_extension, "fields",
- &Descriptor::field_count, &Descriptor::field);
- }
- // Prints a statement assigning "extensions" to a list of Python
- // FieldDescriptors, one for each extension present in message_descriptor.
- void Generator::PrintExtensionsInDescriptor(
- const Descriptor& message_descriptor) const {
- const bool is_extension = true;
- PrintFieldDescriptorsInDescriptor(
- message_descriptor, is_extension, "extensions",
- &Descriptor::extension_count, &Descriptor::extension);
- }
- bool Generator::GeneratingDescriptorProto() const {
- return file_->name() == "net/proto2/proto/descriptor.proto" ||
- file_->name() == "google/protobuf/descriptor.proto";
- }
- // Returns the unique Python module-level identifier given to a descriptor.
- // This name is module-qualified iff the given descriptor describes an
- // entity that doesn't come from the current file.
- template <typename DescriptorT>
- string Generator::ModuleLevelDescriptorName(
- const DescriptorT& descriptor) const {
- // FIXME(robinson):
- // We currently don't worry about collisions with underscores in the type
- // names, so these would collide in nasty ways if found in the same file:
- // OuterProto.ProtoA.ProtoB
- // OuterProto_ProtoA.ProtoB # Underscore instead of period.
- // As would these:
- // OuterProto.ProtoA_.ProtoB
- // OuterProto.ProtoA._ProtoB # Leading vs. trailing underscore.
- // (Contrived, but certainly possible).
- //
- // The C++ implementation doesn't guard against this either. Leaving
- // it for now...
- string name = NamePrefixedWithNestedTypes(descriptor, "_");
- UpperString(&name);
- // Module-private for now. Easy to make public later; almost impossible
- // to make private later.
- name = "_" + name;
- // 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 = ModuleAlias(descriptor.file()->name()) + "." + name;
- }
- return name;
- }
- // Returns the name of the message class itself, not the descriptor.
- // Like ModuleLevelDescriptorName(), module-qualifies the name iff
- // the given descriptor describes an entity that doesn't come from
- // the current file.
- string Generator::ModuleLevelMessageName(const Descriptor& descriptor) const {
- string name = NamePrefixedWithNestedTypes(descriptor, ".");
- if (descriptor.file() != file_) {
- name = ModuleAlias(descriptor.file()->name()) + "." + name;
- }
- return name;
- }
- // Returns the unique Python module-level identifier given to a service
- // descriptor.
- string Generator::ModuleLevelServiceDescriptorName(
- const ServiceDescriptor& descriptor) const {
- string name = descriptor.name();
- UpperString(&name);
- name = "_" + name;
- if (descriptor.file() != file_) {
- name = ModuleAlias(descriptor.file()->name()) + "." + name;
- }
- return name;
- }
- // Prints standard constructor arguments serialized_start and serialized_end.
- // Args:
- // descriptor: The cpp descriptor to have a serialized reference.
- // proto: A proto
- // Example printer output:
- // serialized_start=41,
- // serialized_end=43,
- //
- template <typename DescriptorT, typename DescriptorProtoT>
- void Generator::PrintSerializedPbInterval(
- const DescriptorT& descriptor, DescriptorProtoT& proto) const {
- descriptor.CopyTo(&proto);
- string sp;
- proto.SerializeToString(&sp);
- int offset = file_descriptor_serialized_.find(sp);
- GOOGLE_CHECK_GE(offset, 0);
- printer_->Print(
- "serialized_start=$serialized_start$,\n"
- "serialized_end=$serialized_end$,\n",
- "serialized_start", StrCat(offset), "serialized_end",
- StrCat(offset + sp.size()));
- }
- namespace {
- void PrintDescriptorOptionsFixingCode(const string& descriptor,
- const string& options,
- io::Printer* printer) {
- // Reset the _options to None thus DescriptorBase.GetOptions() can
- // parse _options again after extensions are registered.
- printer->Print(
- "$descriptor$._options = None\n",
- "descriptor", descriptor);
- }
- } // 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(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));
- }
- }
- void Generator::FixOptionsForOneof(const OneofDescriptor& oneof) const {
- string oneof_options = OptionsValue(oneof.options().SerializeAsString());
- if (oneof_options != "None") {
- string oneof_name = strings::Substitute(
- "$0.$1['$2']",
- ModuleLevelDescriptorName(*oneof.containing_type()),
- "oneofs_by_name", oneof.name());
- PrintDescriptorOptionsFixingCode(oneof_name, oneof_options, printer_);
- }
- }
- // 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(
- 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(
- 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(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));
- }
- // Oneofs.
- for (int i = 0; i < descriptor.oneof_decl_count(); ++i) {
- FixOptionsForOneof(*descriptor.oneof_decl(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(
- descriptor.options().SerializeAsString());
- if (message_options != "None") {
- string descriptor_name = ModuleLevelDescriptorName(descriptor);
- PrintDescriptorOptionsFixingCode(descriptor_name,
- message_options,
- printer_);
- }
- }
- // 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_name = ModuleName(file->public_dependency(i)->name());
- string module_alias = ModuleAlias(file->public_dependency(i)->name());
- // There's no module alias in the dependent file if it was generated by
- // an old protoc (less than 3.0.0-alpha-1). Use module name in this
- // situation.
- printer_->Print("try:\n"
- " $alias$ = $copy_from$.$alias$\n"
- "except AttributeError:\n"
- " $alias$ = $copy_from$.$module$\n",
- "alias", module_alias,
- "module", module_name,
- "copy_from", copy_from);
- CopyPublicDependenciesAliases(copy_from, file->public_dependency(i));
- }
- }
- } // namespace python
- } // namespace compiler
- } // namespace protobuf
- } // namespace google
|