diff options
author | nechda <nechda@yandex-team.com> | 2024-08-29 23:50:27 +0300 |
---|---|---|
committer | nechda <nechda@yandex-team.com> | 2024-08-30 00:05:25 +0300 |
commit | e10d6638f07a82edae3ea8197b9f5c0affcc07ea (patch) | |
tree | 571c38cec05813766a1ad290c9d51ce7ace52919 /contrib/libs/protoc/src/google/protobuf/compiler/python | |
parent | e79b38f2bbbf78d295d1901d2a79f898022d5224 (diff) | |
download | ydb-e10d6638f07a82edae3ea8197b9f5c0affcc07ea.tar.gz |
Update cpp-protobuf to 22.5
Привет!\
Этот PR переключат cpp & python библиотеки protobuf на версию 22.5
Если у вас возникли проблемы после влития этого PR:
1. Если начали падать канон тесты, то проведите их переканонизацию
2. Прочитайте <https://wiki.yandex-team.ru/users/nechda/obnovlenie-cpp-protobuf-22.5/> страничку с основными изменениями
3. Если страничка в вики не помогла, то пишите в [DEVTOOLSSUPPORT](https://st.yandex-team.ru/DEVTOOLSSUPPORT)
7fecade616c20a841b9e9af7b7998bdfc8d2807d
Diffstat (limited to 'contrib/libs/protoc/src/google/protobuf/compiler/python')
6 files changed, 633 insertions, 511 deletions
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/python/generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/python/generator.cc index d1e4de467b9..aaf5e3f8cb8 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/python/generator.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/python/generator.cc @@ -42,27 +42,33 @@ // performance-minded Python code leverage the fast C++ implementation // directly. -#include <google/protobuf/compiler/python/generator.h> +#include "google/protobuf/compiler/python/generator.h" #include <algorithm> #include <limits> -#include <map> #include <memory> #include <string> #include <utility> #include <vector> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/stringprintf.h> -#include <google/protobuf/stubs/substitute.h> -#include <google/protobuf/compiler/python/helpers.h> -#include <google/protobuf/compiler/python/pyi_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/escaping.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_format.h" +#include "y_absl/strings/str_replace.h" +#include "y_absl/strings/string_view.h" +#include "y_absl/strings/strip.h" +#include "y_absl/strings/substitute.h" +#include "google/protobuf/compiler/python/helpers.h" +#include "google/protobuf/compiler/python/pyi_generator.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/strtod.h" +#include "google/protobuf/io/zero_copy_stream.h" namespace google { namespace protobuf { @@ -72,15 +78,15 @@ namespace python { namespace { // 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 +// third_party/py/google/protobuf/internal/reflection_test.py // to see why we need the alias. -TProtoStringType ModuleAlias(const TProtoStringType& filename) { +TProtoStringType ModuleAlias(y_absl::string_view filename) { TProtoStringType 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); + y_absl::StrReplaceAll({{"_", "__"}}, &module_name); + y_absl::StrReplaceAll({{".", "_dot_"}}, &module_name); return module_name; } @@ -90,29 +96,7 @@ TProtoStringType ModuleAlias(const TProtoStringType& filename) { // in proto2/public/reflection.py. const char kDescriptorKey[] = "DESCRIPTOR"; - -// 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" - "\"\"\"Generated protocol buffer code.\"\"\"\n", - "filename", file->name()); - printer->Print( - "from google.protobuf.internal import builder as _builder\n" - "from google.protobuf import descriptor as _descriptor\n" - "from google.protobuf import descriptor_pool as " - "_descriptor_pool\n" - "from google.protobuf import symbol_database as " - "_symbol_database\n"); - - printer->Print("# @@protoc_insertion_point(imports)\n\n"); - printer->Print("_sym_db = _symbol_database.Default()\n"); - printer->Print("\n\n"); -} +const char kThirdPartyPrefix[] = "google3.third_party.py."; // Returns a Python literal giving the default value for a field. // If the field specifies no explicit default value, we'll return @@ -131,13 +115,13 @@ TProtoStringType StringifyDefaultValue(const FieldDescriptor& field) { switch (field.cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: - return StrCat(field.default_value_int32()); + return y_absl::StrCat(field.default_value_int32()); case FieldDescriptor::CPPTYPE_UINT32: - return StrCat(field.default_value_uint32()); + return y_absl::StrCat(field.default_value_uint32()); case FieldDescriptor::CPPTYPE_INT64: - return StrCat(field.default_value_int64()); + return y_absl::StrCat(field.default_value_int64()); case FieldDescriptor::CPPTYPE_UINT64: - return StrCat(field.default_value_uint64()); + return y_absl::StrCat(field.default_value_uint64()); case FieldDescriptor::CPPTYPE_DOUBLE: { double value = field.default_value_double(); if (value == std::numeric_limits<double>::infinity()) { @@ -151,7 +135,7 @@ TProtoStringType StringifyDefaultValue(const FieldDescriptor& field) { // infinity * 0 = nan return "(1e10000 * 0)"; } else { - return "float(" + SimpleDtoa(value) + ")"; + return y_absl::StrCat("float(", io::SimpleDtoa(value), ")"); } } case FieldDescriptor::CPPTYPE_FLOAT: { @@ -167,24 +151,24 @@ TProtoStringType StringifyDefaultValue(const FieldDescriptor& field) { // infinity - infinity = nan return "(1e10000 * 0)"; } else { - return "float(" + SimpleFtoa(value) + ")"; + return y_absl::StrCat("float(", io::SimpleFtoa(value), ")"); } } case FieldDescriptor::CPPTYPE_BOOL: return field.default_value_bool() ? "True" : "False"; case FieldDescriptor::CPPTYPE_ENUM: - return StrCat(field.default_value_enum()->number()); + return y_absl::StrCat(field.default_value_enum()->number()); case FieldDescriptor::CPPTYPE_STRING: - return "b\"" + CEscape(field.default_value_string()) + - (field.type() != FieldDescriptor::TYPE_STRING - ? "\"" - : "\".decode('utf-8')"); + return y_absl::StrCat("b\"", y_absl::CEscape(field.default_value_string()), + (field.type() != FieldDescriptor::TYPE_STRING + ? "\"" + : "\".decode('utf-8')")); 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."; + Y_ABSL_LOG(FATAL) << "Not reached."; return ""; } @@ -196,8 +180,9 @@ TProtoStringType StringifySyntax(FileDescriptor::Syntax syntax) { return "proto3"; case FileDescriptor::SYNTAX_UNKNOWN: default: - GOOGLE_LOG(FATAL) << "Unsupported syntax; this generator only supports proto2 " - "and proto3 syntax."; + Y_ABSL_LOG(FATAL) + << "Unsupported syntax; this generator only supports proto2 " + "and proto3 syntax."; return ""; } } @@ -212,26 +197,42 @@ uint64_t Generator::GetSupportedFeatures() const { return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL; } +GeneratorOptions Generator::ParseParameter(y_absl::string_view parameter, + TProtoStringType* error) const { + GeneratorOptions options; + + std::vector<std::pair<TProtoStringType, TProtoStringType> > option_pairs; + ParseGeneratorParameter(parameter, &option_pairs); + + for (const std::pair<TProtoStringType, TProtoStringType>& option : option_pairs) { + if (!opensource_runtime_ && + option.first == "no_enforce_api_compatibility") { + // TODO(b/241584880): remove this legacy option, it has no effect. + } else if (!opensource_runtime_ && option.first == "bootstrap") { + options.bootstrap = true; + } else if (option.first == "pyi_out") { + options.generate_pyi = true; + } else if (option.first == "annotate_code") { + options.annotate_pyi = true; + } else { + *error = y_absl::StrCat("Unknown generator option: ", option.first); + } + } + return options; +} + bool Generator::Generate(const FileDescriptor* file, const TProtoStringType& parameter, GeneratorContext* context, TProtoStringType* error) const { // ----------------------------------------------------------------- - // parse generator options - bool cpp_generated_lib_linked = false; - - std::vector<std::pair<TProtoStringType, TProtoStringType> > options; - ParseGeneratorParameter(parameter, &options); - - for (int i = 0; i < options.size(); i++) { - if (options[i].first == "cpp_generated_lib_linked") { - cpp_generated_lib_linked = true; - } else if (options[i].first == "pyi_out") { - python::PyiGenerator pyi_generator; - if (!pyi_generator.Generate(file, "", context, error)) { - return false; - } - } else { - *error = "Unknown generator option: " + options[i].first; + GeneratorOptions options = ParseParameter(parameter, error); + if (!error->empty()) return false; + + // Generate pyi typing information + if (options.generate_pyi) { + python::PyiGenerator pyi_generator; + TProtoStringType pyi_options = options.annotate_pyi ? "annotate_code" : ""; + if (!pyi_generator.Generate(file, pyi_options, context, error)) { return false; } } @@ -243,78 +244,110 @@ bool Generator::Generate(const FileDescriptor* file, // 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_); + y_absl::MutexLock lock(&mutex_); file_ = file; TProtoStringType filename = GetFileName(file, ".py"); - pure_python_workable_ = !cpp_generated_lib_linked; - if (HasPrefixString(file->name(), "google/protobuf/")) { - pure_python_workable_ = true; - } FileDescriptorProto fdp; file_->CopyTo(&fdp); fdp.SerializeToString(&file_descriptor_serialized_); + if (!opensource_runtime_ && GeneratingDescriptorProto()) { + TProtoStringType bootstrap_filename = + "net/proto2/python/internal/descriptor_pb2.py"; + if (options.bootstrap) { + filename = bootstrap_filename; + } else { + std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename)); + io::Printer printer(output.get(), '$'); + printer.Print( + "from $internal_package$ import descriptor_pb2\n" + "\n", + "internal_package", InternalPackage()); + + // For static checkers, we need to explicitly assign to the symbols we + // publicly export. + for (int i = 0; i < file_->message_type_count(); i++) { + const Descriptor* message = file_->message_type(i); + printer.Print("$name$ = descriptor_pb2.$name$\n", "name", + message->name()); + } + + // Sadly some clients access our internal variables (starting with "_"). + // To support them, we iterate over *all* symbols to expose even the + // private ones. Statically type-checked code should (especially) never + // use these, so we don't worry about making them available to pytype + // checks. + printer.Print( + "\n" + "globals().update(descriptor_pb2.__dict__)\n" + "\n"); + + printer.Print( + "# @@protoc_insertion_point(module_scope)\n" + "\n"); + return true; + } + } std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename)); - GOOGLE_CHECK(output.get()); + Y_ABSL_CHECK(output.get()); io::Printer printer(output.get(), '$'); printer_ = &printer; - PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto()); - if (pure_python_workable_) { - PrintImports(); - } + PrintTopBoilerplate(); + PrintImports(); PrintFileDescriptor(); - if (pure_python_workable_) { - if (GeneratingDescriptorProto()) { - printer_->Print("if _descriptor._USE_C_DESCRIPTORS == False:\n"); - printer_->Indent(); - // Create enums before message descriptors - PrintAllNestedEnumsInFile(); - PrintMessageDescriptors(); - FixForeignFieldsInDescriptors(); - printer_->Outdent(); - printer_->Print("else:\n"); - printer_->Indent(); - } - // Find the message descriptors first and then use the message - // descriptor to find enums. - printer_->Print( - "_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())\n"); - if (GeneratingDescriptorProto()) { - printer_->Outdent(); - } + printer_->Print("_globals = globals()\n"); + if (GeneratingDescriptorProto()) { + printer_->Print("if _descriptor._USE_C_DESCRIPTORS == False:\n"); + printer_->Indent(); + // Create enums before message descriptors + PrintAllNestedEnumsInFile(); + PrintMessageDescriptors(); + FixForeignFieldsInDescriptors(); + printer_->Outdent(); + printer_->Print("else:\n"); + printer_->Indent(); + } + // Find the message descriptors first and then use the message + // descriptor to find enums. + printer_->Print( + "_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)\n"); + if (GeneratingDescriptorProto()) { + printer_->Outdent(); } TProtoStringType module_name = ModuleName(file->name()); + if (!opensource_runtime_) { + module_name = + TProtoStringType(y_absl::StripPrefix(module_name, kThirdPartyPrefix)); + } printer_->Print( "_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, '$module_name$', " - "globals())\n", + "_globals)\n", "module_name", module_name); - if (pure_python_workable_) { - printer.Print("if _descriptor._USE_C_DESCRIPTORS == False:\n"); - printer_->Indent(); + printer.Print("if _descriptor._USE_C_DESCRIPTORS == False:\n"); + printer_->Indent(); - // 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(); + // 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(); - // Set serialized_start and serialized_end. - SetSerializedPbInterval(); + // Set serialized_start and serialized_end. + SetSerializedPbInterval(); - printer_->Outdent(); - } + printer_->Outdent(); if (HasGenericServices(file)) { printer_->Print( - "_builder.BuildServices(DESCRIPTOR, '$module_name$', globals())\n", + "_builder.BuildServices(DESCRIPTOR, '$module_name$', _globals)\n", "module_name", module_name); } @@ -323,13 +356,45 @@ bool Generator::Generate(const FileDescriptor* file, return !printer.failed(); } +// file output by this generator. +void Generator::PrintTopBoilerplate() const { + // 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" + "\"\"\"Generated protocol buffer code.\"\"\"\n", + "filename", file_->name()); + if (!opensource_runtime_) { + // This import is needed so that compatibility proto1 compiler output + // inserted at protoc_insertion_point can refer to other protos like + // google3.a.b.c. Code generated by proto2 compiler doesn't do it, and + // instead uses aliases assigned when importing modules. + printer_->Print("import google3\n"); + } + printer_->Print( + "from $internal_package$ import builder as _builder\n" + "from $public_package$ import descriptor as _descriptor\n" + "from $public_package$ import descriptor_pool as _descriptor_pool\n" + "from $public_package$ import symbol_database as _symbol_database\n", + "internal_package", InternalPackage(), "public_package", PublicPackage()); + + printer_->Print("# @@protoc_insertion_point(imports)\n\n"); + printer_->Print("_sym_db = _symbol_database.Default()\n"); + printer_->Print("\n\n"); +} + // Prints Python imports for all modules imported by |file|. void Generator::PrintImports() const { for (int i = 0; i < file_->dependency_count(); ++i) { - const TProtoStringType& filename = file_->dependency(i)->name(); + y_absl::string_view filename = file_->dependency(i)->name(); TProtoStringType module_name = ModuleName(filename); TProtoStringType module_alias = ModuleAlias(filename); + if (!opensource_runtime_) { + module_name = + TProtoStringType(y_absl::StripPrefix(module_name, kThirdPartyPrefix)); + } 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 @@ -339,15 +404,16 @@ void Generator::PrintImports() const { printer_->Print("$alias$ = importlib.import_module('$name$')\n", "alias", module_alias, "name", module_name); } else { - int last_dot_pos = module_name.rfind('.'); + size_t last_dot_pos = module_name.rfind('.'); TProtoStringType import_statement; if (last_dot_pos == TProtoStringType::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; + import_statement = y_absl::StrCat("import ", module_name); } else { - import_statement = "from " + module_name.substr(0, last_dot_pos) + - " import " + module_name.substr(last_dot_pos + 1); + import_statement = + y_absl::StrCat("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); @@ -360,6 +426,10 @@ void Generator::PrintImports() const { // Print public imports. for (int i = 0; i < file_->public_dependency_count(); ++i) { TProtoStringType module_name = ModuleName(file_->public_dependency(i)->name()); + if (!opensource_runtime_) { + module_name = + TProtoStringType(y_absl::StripPrefix(module_name, kThirdPartyPrefix)); + } printer_->Print("from $module$ import *\n", "module", module_name); } printer_->Print("\n"); @@ -367,13 +437,13 @@ void Generator::PrintImports() const { // Prints the single file descriptor for this file. void Generator::PrintFileDescriptor() const { - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["descriptor_name"] = kDescriptorKey; m["name"] = file_->name(); m["package"] = file_->package(); m["syntax"] = StringifySyntax(file_->syntax()); m["options"] = OptionsValue(file_->options().SerializeAsString()); - m["serialized_descriptor"] = strings::CHexEscape(file_descriptor_serialized_); + m["serialized_descriptor"] = y_absl::CHexEscape(file_descriptor_serialized_); if (GeneratingDescriptorProto()) { printer_->Print("if _descriptor._USE_C_DESCRIPTORS == False:\n"); printer_->Indent(); @@ -389,30 +459,26 @@ void Generator::PrintFileDescriptor() const { " create_key=_descriptor._internal_create_key,\n"; printer_->Print(m, file_descriptor_template); printer_->Indent(); - if (pure_python_workable_) { - printer_->Print("serialized_pb=b'$value$'\n", "value", - strings::CHexEscape(file_descriptor_serialized_)); - if (file_->dependency_count() != 0) { - printer_->Print(",\ndependencies=["); - for (int i = 0; i < file_->dependency_count(); ++i) { - TProtoStringType module_alias = ModuleAlias(file_->dependency(i)->name()); - printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias", - module_alias); - } - printer_->Print("]"); + printer_->Print("serialized_pb=b'$value$'\n", "value", + y_absl::CHexEscape(file_descriptor_serialized_)); + if (file_->dependency_count() != 0) { + printer_->Print(",\ndependencies=["); + for (int i = 0; i < file_->dependency_count(); ++i) { + TProtoStringType module_alias = ModuleAlias(file_->dependency(i)->name()); + printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias", + module_alias); } - if (file_->public_dependency_count() > 0) { - printer_->Print(",\npublic_dependencies=["); - for (int i = 0; i < file_->public_dependency_count(); ++i) { - TProtoStringType module_alias = - ModuleAlias(file_->public_dependency(i)->name()); - printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias", - module_alias); - } - printer_->Print("]"); + printer_->Print("]"); + } + if (file_->public_dependency_count() > 0) { + printer_->Print(",\npublic_dependencies=["); + for (int i = 0; i < file_->public_dependency_count(); ++i) { + TProtoStringType module_alias = + ModuleAlias(file_->public_dependency(i)->name()); + printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias", + module_alias); } - } else { - printer_->Print("serialized_pb=''\n"); + printer_->Print("]"); } // TODO(falk): Also print options and fix the message_type, enum_type, @@ -446,7 +512,7 @@ void Generator::PrintAllNestedEnumsInFile() const { // enum name to a Python EnumDescriptor object equivalent to // enum_descriptor. void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; TProtoStringType module_level_descriptor_name = ModuleLevelDescriptorName(enum_descriptor); m["descriptor_name"] = module_level_descriptor_name; @@ -467,11 +533,9 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { printer_->Indent(); printer_->Indent(); - if (pure_python_workable_) { - for (int i = 0; i < enum_descriptor.value_count(); ++i) { - PrintEnumValueDescriptor(*enum_descriptor.value(i)); - printer_->Print(",\n"); - } + for (int i = 0; i < enum_descriptor.value_count(); ++i) { + PrintEnumValueDescriptor(*enum_descriptor.value(i)); + printer_->Print(",\n"); } printer_->Outdent(); @@ -482,10 +546,8 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { EnumDescriptorProto edp; printer_->Outdent(); printer_->Print(")\n"); - if (pure_python_workable_) { - printer_->Print("_sym_db.RegisterEnumDescriptor($name$)\n", "name", - module_level_descriptor_name); - } + printer_->Print("_sym_db.RegisterEnumDescriptor($name$)\n", "name", + module_level_descriptor_name); printer_->Print("\n"); } @@ -525,7 +587,7 @@ void Generator::PrintServices() const { void Generator::PrintServiceDescriptor( const ServiceDescriptor& descriptor) const { - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["service_name"] = ModuleLevelServiceDescriptorName(descriptor); m["name"] = descriptor.name(); m["file"] = kDescriptorKey; @@ -535,13 +597,13 @@ void Generator::PrintServiceDescriptor( void Generator::PrintDescriptorKeyAndModuleName( const ServiceDescriptor& descriptor) const { TProtoStringType name = ModuleLevelServiceDescriptorName(descriptor); - if (!pure_python_workable_) { - name = "_descriptor.ServiceDescriptor(full_name='" + - descriptor.full_name() + "')"; - } printer_->Print("$descriptor_key$ = $descriptor_name$,\n", "descriptor_key", kDescriptorKey, "descriptor_name", name); TProtoStringType module_name = ModuleName(file_->name()); + if (!opensource_runtime_) { + module_name = + TProtoStringType(y_absl::StripPrefix(module_name, kThirdPartyPrefix)); + } printer_->Print("__module__ = '$module_name$'\n", "module_name", module_name); } @@ -575,7 +637,7 @@ void Generator::PrintServiceStub(const ServiceDescriptor& descriptor) const { // // Mutually recursive with PrintNestedDescriptors(). void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["name"] = message_descriptor.name(); m["full_name"] = message_descriptor.full_name(); m["file"] = kDescriptorKey; @@ -634,8 +696,8 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { 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("($start$, $end$), ", "start", y_absl::StrCat(range->start), + "end", y_absl::StrCat(range->end)); } printer_->Print("],\n"); printer_->Print("oneofs=[\n"); @@ -645,12 +707,13 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { m.clear(); m["name"] = desc->name(); m["full_name"] = desc->full_name(); - m["index"] = StrCat(desc->index()); + m["index"] = y_absl::StrCat(desc->index()); options_string = OptionsValue(desc->options().SerializeAsString()); if (options_string == "None") { m["serialized_options"] = ""; } else { - m["serialized_options"] = ", serialized_options=" + options_string; + m["serialized_options"] = + y_absl::StrCat(", serialized_options=", options_string); } printer_->Print(m, "_descriptor.OneofDescriptor(\n" @@ -699,16 +762,16 @@ void Generator::PrintMessages() const { // Mutually recursive with PrintNestedMessages(). // Collect nested message names to_register for the symbol_database. void Generator::PrintMessage(const Descriptor& message_descriptor, - const TProtoStringType& prefix, + y_absl::string_view prefix, std::vector<TProtoStringType>* to_register, bool is_nested) const { TProtoStringType qualified_name; if (is_nested) { if (IsPythonKeyword(message_descriptor.name())) { - qualified_name = - "getattr(" + prefix + ", '" + message_descriptor.name() + "')"; + qualified_name = y_absl::StrCat("getattr(", prefix, ", '", + message_descriptor.name(), "')"); } else { - qualified_name = prefix + "." + message_descriptor.name(); + qualified_name = y_absl::StrCat(prefix, ".", message_descriptor.name()); } printer_->Print( "'$name$' : _reflection.GeneratedProtocolMessageType('$name$', " @@ -726,16 +789,15 @@ void Generator::PrintMessage(const Descriptor& message_descriptor, to_register->push_back(qualified_name); PrintNestedMessages(message_descriptor, qualified_name, to_register); - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["descriptor_key"] = kDescriptorKey; - if (pure_python_workable_) { - m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor); - } else { - m["descriptor_name"] = "_descriptor.Descriptor(full_name='" + - message_descriptor.full_name() + "')"; - } + m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor); printer_->Print(m, "'$descriptor_key$' : $descriptor_name$,\n"); TProtoStringType module_name = ModuleName(file_->name()); + if (!opensource_runtime_) { + module_name = + TProtoStringType(y_absl::StripPrefix(module_name, kThirdPartyPrefix)); + } printer_->Print("'__module__' : '$module_name$'\n", "module_name", module_name); printer_->Print("# @@protoc_insertion_point(class_scope:$full_name$)\n", @@ -747,7 +809,7 @@ void Generator::PrintMessage(const Descriptor& message_descriptor, // Prints all nested messages within |containing_descriptor|. // Mutually recursive with PrintMessage(). void Generator::PrintNestedMessages( - const Descriptor& containing_descriptor, const TProtoStringType& prefix, + const Descriptor& containing_descriptor, y_absl::string_view prefix, std::vector<TProtoStringType>* to_register) const { for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) { printer_->Print("\n"); @@ -782,7 +844,7 @@ void Generator::FixForeignFieldsInDescriptor( FixContainingTypeInDescriptor(enum_descriptor, &descriptor); } for (int i = 0; i < descriptor.oneof_decl_count(); ++i) { - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; const OneofDescriptor* oneof = descriptor.oneof_decl(i); m["descriptor_name"] = ModuleLevelDescriptorName(descriptor); m["oneof_name"] = oneof->name(); @@ -801,7 +863,7 @@ void Generator::FixForeignFieldsInDescriptor( } void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const { - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["descriptor_name"] = kDescriptorKey; m["message_name"] = descriptor.name(); m["message_descriptor_name"] = ModuleLevelDescriptorName(descriptor); @@ -813,7 +875,7 @@ void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const { void Generator::AddServiceToFileDescriptor( const ServiceDescriptor& descriptor) const { - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["descriptor_name"] = kDescriptorKey; m["service_name"] = descriptor.name(); m["service_descriptor_name"] = ModuleLevelServiceDescriptorName(descriptor); @@ -825,7 +887,7 @@ void Generator::AddServiceToFileDescriptor( void Generator::AddEnumToFileDescriptor( const EnumDescriptor& descriptor) const { - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["descriptor_name"] = kDescriptorKey; m["enum_name"] = descriptor.name(); m["enum_descriptor_name"] = ModuleLevelDescriptorName(descriptor); @@ -837,7 +899,7 @@ void Generator::AddEnumToFileDescriptor( void Generator::AddExtensionToFileDescriptor( const FieldDescriptor& descriptor) const { - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["descriptor_name"] = kDescriptorKey; m["field_name"] = descriptor.name(); m["resolved_name"] = ResolveKeyword(descriptor.name()); @@ -858,10 +920,10 @@ void Generator::AddExtensionToFileDescriptor( // is NULL. void Generator::FixForeignFieldsInField( const Descriptor* containing_type, const FieldDescriptor& field, - const TProtoStringType& python_dict_name) const { + y_absl::string_view python_dict_name) const { const TProtoStringType field_referencing_expression = FieldReferencingExpression(containing_type, field, python_dict_name); - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["field_ref"] = field_referencing_expression; const Descriptor* foreign_message_type = field.message_type(); if (foreign_message_type) { @@ -886,15 +948,15 @@ void Generator::FixForeignFieldsInField( // is NULL. TProtoStringType Generator::FieldReferencingExpression( const Descriptor* containing_type, const FieldDescriptor& field, - const TProtoStringType& python_dict_name) const { + y_absl::string_view 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_) + Y_ABSL_CHECK_EQ(field.file(), file_) << field.file()->name() << " vs. " << file_->name(); if (!containing_type) { return ResolveKeyword(field.name()); } - return strings::Substitute("$0.$1['$2']", + return y_absl::Substitute("$0.$1['$2']", ModuleLevelDescriptorName(*containing_type), python_dict_name, field.name()); } @@ -955,9 +1017,9 @@ void Generator::FixForeignFieldsInExtensions() const { void Generator::FixForeignFieldsInExtension( const FieldDescriptor& extension_field) const { - GOOGLE_CHECK(extension_field.is_extension()); + Y_ABSL_CHECK(extension_field.is_extension()); - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> 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 @@ -989,10 +1051,10 @@ void Generator::PrintEnumValueDescriptor( // More circular references. ::sigh:: TProtoStringType options_string; descriptor.options().SerializeToString(&options_string); - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["name"] = descriptor.name(); - m["index"] = StrCat(descriptor.index()); - m["number"] = StrCat(descriptor.number()); + m["index"] = y_absl::StrCat(descriptor.index()); + m["number"] = y_absl::StrCat(descriptor.number()); m["options"] = OptionsValue(options_string); printer_->Print(m, "_descriptor.EnumValueDescriptor(\n" @@ -1004,11 +1066,11 @@ void Generator::PrintEnumValueDescriptor( // Returns a CEscaped string of serialized_options. TProtoStringType Generator::OptionsValue( - const TProtoStringType& serialized_options) const { + y_absl::string_view serialized_options) const { if (serialized_options.length() == 0 || GeneratingDescriptorProto()) { return "None"; } else { - return "b'" + CEscape(serialized_options) + "'"; + return y_absl::StrCat("b'", y_absl::CEscape(serialized_options), "'"); } } @@ -1017,20 +1079,21 @@ void Generator::PrintFieldDescriptor(const FieldDescriptor& field, bool is_extension) const { TProtoStringType options_string; field.options().SerializeToString(&options_string); - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> 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["index"] = y_absl::StrCat(field.index()); + m["number"] = y_absl::StrCat(field.number()); + m["type"] = y_absl::StrCat(field.type()); + m["cpp_type"] = y_absl::StrCat(field.cpp_type()); + m["label"] = y_absl::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() + "'" : ""; + m["json_name"] = field.has_json_name() + ? y_absl::StrCat(", 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()). @@ -1050,8 +1113,8 @@ void Generator::PrintFieldDescriptor(const FieldDescriptor& field, // Helper for Print{Fields,Extensions}InDescriptor(). void Generator::PrintFieldDescriptorsInDescriptor( const Descriptor& message_descriptor, bool is_extension, - const TProtoStringType& list_variable_name, int (Descriptor::*CountFn)() const, - const FieldDescriptor* (Descriptor::*GetterFn)(int)const) const { + y_absl::string_view 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) { @@ -1106,14 +1169,14 @@ TProtoStringType Generator::ModuleLevelDescriptorName( // The C++ implementation doesn't guard against this either. Leaving // it for now... TProtoStringType name = NamePrefixedWithNestedTypes(descriptor, "_"); - ToUpper(&name); + y_absl::AsciiStrToUpper(&name); // Module-private for now. Easy to make public later; almost impossible // to make private later. - name = "_" + name; + name = y_absl::StrCat("_", 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; + name = y_absl::StrCat(ModuleAlias(descriptor.file()->name()), ".", name); } return name; } @@ -1126,7 +1189,7 @@ TProtoStringType Generator::ModuleLevelMessageName( const Descriptor& descriptor) const { TProtoStringType name = NamePrefixedWithNestedTypes(descriptor, "."); if (descriptor.file() != file_) { - name = ModuleAlias(descriptor.file()->name()) + "." + name; + name = y_absl::StrCat(ModuleAlias(descriptor.file()->name()), ".", name); } return name; } @@ -1135,15 +1198,24 @@ TProtoStringType Generator::ModuleLevelMessageName( // descriptor. TProtoStringType Generator::ModuleLevelServiceDescriptorName( const ServiceDescriptor& descriptor) const { - TProtoStringType name = descriptor.name(); - ToUpper(&name); - name = "_" + name; + TProtoStringType name = y_absl::StrCat("_", descriptor.name()); + y_absl::AsciiStrToUpper(&name); if (descriptor.file() != file_) { - name = ModuleAlias(descriptor.file()->name()) + "." + name; + name = y_absl::StrCat(ModuleAlias(descriptor.file()->name()), ".", name); } return name; } +TProtoStringType Generator::PublicPackage() const { + return opensource_runtime_ ? "google.protobuf" + : "google3.net.google.protobuf.python.public"; +} + +TProtoStringType Generator::InternalPackage() const { + return opensource_runtime_ ? "google.protobuf.internal" + : "google3.net.google.protobuf.python.internal"; +} + // Prints standard constructor arguments serialized_start and serialized_end. // Args: // descriptor: The cpp descriptor to have a serialized reference. @@ -1155,23 +1227,23 @@ TProtoStringType Generator::ModuleLevelServiceDescriptorName( template <typename DescriptorT, typename DescriptorProtoT> void Generator::PrintSerializedPbInterval(const DescriptorT& descriptor, DescriptorProtoT& proto, - const TProtoStringType& name) const { + y_absl::string_view name) const { descriptor.CopyTo(&proto); TProtoStringType sp; proto.SerializeToString(&sp); int offset = file_descriptor_serialized_.find(sp); - GOOGLE_CHECK_GE(offset, 0); + Y_ABSL_CHECK_GE(offset, 0); printer_->Print( - "$name$._serialized_start=$serialized_start$\n" - "$name$._serialized_end=$serialized_end$\n", - "name", name, "serialized_start", StrCat(offset), "serialized_end", - StrCat(offset + sp.size())); + "_globals['$name$']._serialized_start=$serialized_start$\n" + "_globals['$name$']._serialized_end=$serialized_end$\n", + "name", name, "serialized_start", y_absl::StrCat(offset), "serialized_end", + y_absl::StrCat(offset + sp.size())); } namespace { -void PrintDescriptorOptionsFixingCode(const TProtoStringType& descriptor, - const TProtoStringType& options, +void PrintDescriptorOptionsFixingCode(y_absl::string_view descriptor, + y_absl::string_view options, io::Printer* printer) { // Reset the _options to None thus DescriptorBase.GetOptions() can // parse _options again after extensions are registered. @@ -1256,7 +1328,7 @@ void Generator::FixAllDescriptorOptions() const { void Generator::FixOptionsForOneof(const OneofDescriptor& oneof) const { TProtoStringType oneof_options = OptionsValue(oneof.options().SerializeAsString()); if (oneof_options != "None") { - TProtoStringType oneof_name = strings::Substitute( + TProtoStringType oneof_name = y_absl::Substitute( "$0.$1['$2']", ModuleLevelDescriptorName(*oneof.containing_type()), "oneofs_by_name", oneof.name()); PrintDescriptorOptionsFixingCode(oneof_name, oneof_options, printer_); @@ -1278,7 +1350,7 @@ void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const { OptionsValue(value_descriptor.options().SerializeAsString()); if (value_options != "None") { PrintDescriptorOptionsFixingCode( - StringPrintf("%s.values_by_name[\"%s\"]", descriptor_name.c_str(), + y_absl::StrFormat("%s.values_by_name[\"%s\"]", descriptor_name.c_str(), value_descriptor.name().c_str()), value_options, printer_); } @@ -1303,8 +1375,8 @@ void Generator::FixOptionsForService( TProtoStringType method_options = OptionsValue(method->options().SerializeAsString()); if (method_options != "None") { - TProtoStringType method_name = - descriptor_name + ".methods_by_name['" + method->name() + "']"; + TProtoStringType method_name = y_absl::StrCat( + descriptor_name, ".methods_by_name['", method->name(), "']"); PrintDescriptorOptionsFixingCode(method_name, method_options, printer_); } } @@ -1370,7 +1442,7 @@ 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 TProtoStringType& copy_from, const FileDescriptor* file) const { + y_absl::string_view copy_from, const FileDescriptor* file) const { for (int i = 0; i < file->public_dependency_count(); ++i) { TProtoStringType module_name = ModuleName(file->public_dependency(i)->name()); TProtoStringType module_alias = ModuleAlias(file->public_dependency(i)->name()); diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/python/generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/python/generator.h index 8111bf733fc..8691b552219 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/python/generator.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/python/generator.h @@ -36,12 +36,14 @@ #define GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__ #include <string> +#include <vector> -#include <google/protobuf/stubs/mutex.h> -#include <google/protobuf/compiler/code_generator.h> +#include "y_absl/strings/string_view.h" +#include "y_absl/synchronization/mutex.h" +#include "google/protobuf/compiler/code_generator.h" // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -64,9 +66,18 @@ namespace python { // If you create your own protocol compiler binary and you want it to support // Python output, you can do so by registering an instance of this // CodeGenerator with the CommandLineInterface in your main() function. + +struct GeneratorOptions { + bool generate_pyi = false; + bool annotate_pyi = false; + bool bootstrap = false; +}; + class PROTOC_EXPORT Generator : public CodeGenerator { public: Generator(); + Generator(const Generator&) = delete; + Generator& operator=(const Generator&) = delete; ~Generator() override; // CodeGenerator methods. @@ -76,7 +87,13 @@ class PROTOC_EXPORT Generator : public CodeGenerator { uint64_t GetSupportedFeatures() const override; + void set_opensource_runtime(bool opensource) { + opensource_runtime_ = opensource; + } + private: + GeneratorOptions ParseParameter(y_absl::string_view parameter, + TProtoStringType* error) const; void PrintImports() const; void PrintFileDescriptor() const; void PrintAllNestedEnumsInFile() const; @@ -87,8 +104,8 @@ class PROTOC_EXPORT Generator : public CodeGenerator { bool is_extension) const; void PrintFieldDescriptorsInDescriptor( const Descriptor& message_descriptor, bool is_extension, - const TProtoStringType& list_variable_name, int (Descriptor::*CountFn)() const, - const FieldDescriptor* (Descriptor::*GetterFn)(int)const) const; + y_absl::string_view list_variable_name, int (Descriptor::*CountFn)() const, + const FieldDescriptor* (Descriptor::*GetterFn)(int) const) const; void PrintFieldsInDescriptor(const Descriptor& message_descriptor) const; void PrintExtensionsInDescriptor(const Descriptor& message_descriptor) const; void PrintMessageDescriptors() const; @@ -97,11 +114,11 @@ class PROTOC_EXPORT Generator : public CodeGenerator { void PrintMessages() const; void PrintMessage(const Descriptor& message_descriptor, - const TProtoStringType& prefix, + y_absl::string_view prefix, std::vector<TProtoStringType>* to_register, bool is_nested) const; void PrintNestedMessages(const Descriptor& containing_descriptor, - const TProtoStringType& prefix, + y_absl::string_view prefix, std::vector<TProtoStringType>* to_register) const; void FixForeignFieldsInDescriptors() const; @@ -110,14 +127,14 @@ class PROTOC_EXPORT Generator : public CodeGenerator { const Descriptor* containing_descriptor) const; void FixForeignFieldsInField(const Descriptor* containing_type, const FieldDescriptor& field, - const TProtoStringType& python_dict_name) const; + y_absl::string_view python_dict_name) const; void AddMessageToFileDescriptor(const Descriptor& descriptor) const; void AddEnumToFileDescriptor(const EnumDescriptor& descriptor) const; void AddExtensionToFileDescriptor(const FieldDescriptor& descriptor) const; void AddServiceToFileDescriptor(const ServiceDescriptor& descriptor) const; TProtoStringType FieldReferencingExpression( const Descriptor* containing_type, const FieldDescriptor& field, - const TProtoStringType& python_dict_name) const; + y_absl::string_view python_dict_name) const; template <typename DescriptorT> void FixContainingTypeInDescriptor( const DescriptorT& descriptor, @@ -128,6 +145,7 @@ class PROTOC_EXPORT Generator : public CodeGenerator { const FieldDescriptor& extension_field) const; void FixForeignFieldsInNestedExtensions(const Descriptor& descriptor) const; + void PrintTopBoilerplate() const; void PrintServices() const; void PrintServiceDescriptors() const; void PrintServiceDescriptor(const ServiceDescriptor& descriptor) const; @@ -137,7 +155,7 @@ class PROTOC_EXPORT Generator : public CodeGenerator { const ServiceDescriptor& descriptor) const; void PrintEnumValueDescriptor(const EnumValueDescriptor& descriptor) const; - TProtoStringType OptionsValue(const TProtoStringType& serialized_options) const; + TProtoStringType OptionsValue(y_absl::string_view serialized_options) const; bool GeneratingDescriptorProto() const; template <typename DescriptorT> @@ -145,11 +163,13 @@ class PROTOC_EXPORT Generator : public CodeGenerator { TProtoStringType ModuleLevelMessageName(const Descriptor& descriptor) const; TProtoStringType ModuleLevelServiceDescriptorName( const ServiceDescriptor& descriptor) const; + TProtoStringType PublicPackage() const; + TProtoStringType InternalPackage() const; template <typename DescriptorT, typename DescriptorProtoT> void PrintSerializedPbInterval(const DescriptorT& descriptor, DescriptorProtoT& proto, - const TProtoStringType& name) const; + y_absl::string_view name) const; void FixAllDescriptorOptions() const; void FixOptionsForField(const FieldDescriptor& field) const; @@ -161,18 +181,17 @@ class PROTOC_EXPORT Generator : public CodeGenerator { void SetSerializedPbInterval() const; void SetMessagePbInterval(const Descriptor& descriptor) const; - void CopyPublicDependenciesAliases(const TProtoStringType& copy_from, + void CopyPublicDependenciesAliases(y_absl::string_view copy_from, const FileDescriptor* file) const; // Very coarse-grained lock to ensure that Generate() is reentrant. // Guards file_, printer_ and file_descriptor_serialized_. - mutable Mutex mutex_; + mutable y_absl::Mutex mutex_; mutable const FileDescriptor* file_; // Set in Generate(). Under mutex_. mutable TProtoStringType file_descriptor_serialized_; mutable io::Printer* printer_; // Set in Generate(). Under mutex_. - mutable bool pure_python_workable_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator); + bool opensource_runtime_ = true; }; } // namespace python @@ -180,6 +199,6 @@ class PROTOC_EXPORT Generator : public CodeGenerator { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/python/helpers.cc b/contrib/libs/protoc/src/google/protobuf/compiler/python/helpers.cc index ee7461bc83c..f41603420cc 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/python/helpers.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/python/helpers.cc @@ -28,36 +28,45 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include <google/protobuf/compiler/python/helpers.h> +#include "google/protobuf/compiler/python/helpers.h" #include <algorithm> - -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> +#include <string> +#include <vector> + +#include "y_absl/log/absl_check.h" +#include "y_absl/strings/escaping.h" +#include "y_absl/strings/match.h" +#include "y_absl/strings/str_replace.h" +#include "y_absl/strings/str_split.h" +#include "y_absl/strings/string_view.h" +#include "y_absl/strings/strip.h" +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" namespace google { namespace protobuf { namespace compiler { namespace python { -TProtoStringType FixEv(const TProtoStringType& filename) { - if (HasSuffixString(filename, ".ev")) { - return StripSuffixString(filename, ".ev") + "_ev.proto"; - } - return filename; +TProtoStringType FixEv(TProtoStringType filename) { + constexpr auto kSuffixLen = 3; + if (filename.EndsWith(".ev")) { + return filename.substr(0, filename.length() - kSuffixLen) + "_ev.proto"; + } + return filename; } // Returns the Python module name expected for a given .proto filename. -TProtoStringType ModuleName(const TProtoStringType& filename) { - TProtoStringType basename = StripProto(FixEv(filename)); - ReplaceCharacters(&basename, "-", '_'); - ReplaceCharacters(&basename, "/", '.'); - return basename + "_pb2"; +TProtoStringType ModuleName(y_absl::string_view filename) { + TProtoStringType str(std::string{filename}); + TProtoStringType basename = StripProto(FixEv(str)); + y_absl::StrReplaceAll({{"-", "_"}, {"/", "."}}, &basename); + return y_absl::StrCat(basename, "_pb2"); } -TProtoStringType StrippedModuleName(const TProtoStringType& filename) { +TProtoStringType StrippedModuleName(y_absl::string_view filename) { TProtoStringType module_name = ModuleName(filename); return module_name; } @@ -74,8 +83,8 @@ const char* const kKeywords[] = { const char* const* kKeywordsEnd = kKeywords + (sizeof(kKeywords) / sizeof(kKeywords[0])); -bool ContainsPythonKeyword(const TProtoStringType& module_name) { - std::vector<TProtoStringType> tokens = Split(module_name, "."); +bool ContainsPythonKeyword(y_absl::string_view module_name) { + std::vector<y_absl::string_view> tokens = y_absl::StrSplit(module_name, '.'); for (int i = 0; i < static_cast<int>(tokens.size()); ++i) { if (std::find(kKeywords, kKeywordsEnd, tokens[i]) != kKeywordsEnd) { return true; @@ -84,23 +93,23 @@ bool ContainsPythonKeyword(const TProtoStringType& module_name) { return false; } -bool IsPythonKeyword(const TProtoStringType& name) { +bool IsPythonKeyword(y_absl::string_view name) { return (std::find(kKeywords, kKeywordsEnd, name) != kKeywordsEnd); } -TProtoStringType ResolveKeyword(const TProtoStringType& name) { +TProtoStringType ResolveKeyword(y_absl::string_view name) { if (IsPythonKeyword(name)) { - return "globals()['" + name + "']"; + return y_absl::StrCat("globals()['", name, "']"); } - return name; + return TProtoStringType(name); } TProtoStringType GetFileName(const FileDescriptor* file_des, - const TProtoStringType& suffix) { + y_absl::string_view suffix) { TProtoStringType module_name = ModuleName(file_des->name()); TProtoStringType filename = module_name; - ReplaceCharacters(&filename, ".", '/'); - filename += suffix; + y_absl::StrReplaceAll({{".", "/"}}, &filename); + y_absl::StrAppend(&filename, suffix); return filename; } @@ -108,17 +117,23 @@ bool HasGenericServices(const FileDescriptor* file) { return file->service_count() > 0 && file->options().py_generic_services(); } +TProtoStringType GeneratedCodeToBase64(const GeneratedCodeInfo& annotations) { + TProtoStringType result; + y_absl::Base64Escape(annotations.SerializeAsString(), &result); + return result; +} + template <typename DescriptorT> TProtoStringType NamePrefixedWithNestedTypes(const DescriptorT& descriptor, - const TProtoStringType& separator) { + y_absl::string_view separator) { TProtoStringType name = descriptor.name(); const Descriptor* parent = descriptor.containing_type(); if (parent != nullptr) { TProtoStringType prefix = NamePrefixedWithNestedTypes(*parent, separator); if (separator == "." && IsPythonKeyword(name)) { - return "getattr(" + prefix + ", '" + name + "')"; + return y_absl::StrCat("getattr(", prefix, ", '", name, "')"); } else { - return prefix + separator + name; + return y_absl::StrCat(prefix, separator, name); } } if (separator == ".") { @@ -128,9 +143,9 @@ TProtoStringType NamePrefixedWithNestedTypes(const DescriptorT& descriptor, } template TProtoStringType NamePrefixedWithNestedTypes<Descriptor>( - const Descriptor& descriptor, const TProtoStringType& separator); + const Descriptor& descriptor, y_absl::string_view separator); template TProtoStringType NamePrefixedWithNestedTypes<EnumDescriptor>( - const EnumDescriptor& descriptor, const TProtoStringType& separator); + const EnumDescriptor& descriptor, y_absl::string_view separator); } // namespace python } // namespace compiler diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/python/helpers.h b/contrib/libs/protoc/src/google/protobuf/compiler/python/helpers.h index 8745698acf6..5d77d73394f 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/python/helpers.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/python/helpers.h @@ -33,26 +33,29 @@ #include <string> -#include <google/protobuf/descriptor.h> +#include "y_absl/strings/str_replace.h" +#include "y_absl/strings/string_view.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" namespace google { namespace protobuf { namespace compiler { namespace python { - -TProtoStringType ModuleName(const TProtoStringType& filename); -TProtoStringType StrippedModuleName(const TProtoStringType& filename); -bool ContainsPythonKeyword(const TProtoStringType& module_name); -bool IsPythonKeyword(const TProtoStringType& name); -TProtoStringType ResolveKeyword(const TProtoStringType& name); +TProtoStringType ModuleName(y_absl::string_view filename); +TProtoStringType StrippedModuleName(y_absl::string_view filename); +bool ContainsPythonKeyword(y_absl::string_view module_name); +bool IsPythonKeyword(y_absl::string_view name); +TProtoStringType ResolveKeyword(y_absl::string_view name); TProtoStringType GetFileName(const FileDescriptor* file_des, - const TProtoStringType& suffix); + y_absl::string_view suffix); bool HasGenericServices(const FileDescriptor* file); +TProtoStringType GeneratedCodeToBase64(const GeneratedCodeInfo& annotations); template <typename DescriptorT> TProtoStringType NamePrefixedWithNestedTypes(const DescriptorT& descriptor, - const TProtoStringType& separator); + y_absl::string_view separator); } // namespace python } // namespace compiler diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/python/pyi_generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/python/pyi_generator.cc index 242cdd71f2c..3e7c2538958 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/python/pyi_generator.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/python/pyi_generator.cc @@ -28,61 +28,61 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#include <google/protobuf/compiler/python/pyi_generator.h> +#include "google/protobuf/compiler/python/pyi_generator.h" #include <string> - -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/python/helpers.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> +#include <utility> +#include <vector> + +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/match.h" +#include "y_absl/strings/str_split.h" +#include "google/protobuf/compiler/python/helpers.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/zero_copy_stream.h" namespace google { namespace protobuf { namespace compiler { namespace python { -template <typename DescriptorT> -struct SortByName { - bool operator()(const DescriptorT* l, const DescriptorT* r) const { - return l->name() < r->name(); - } -}; - PyiGenerator::PyiGenerator() : file_(nullptr) {} PyiGenerator::~PyiGenerator() {} -void PyiGenerator::PrintItemMap( - const std::map<TProtoStringType, TProtoStringType>& item_map) const { - for (const auto& entry : item_map) { - printer_->Print("$key$: $value$\n", "key", entry.first, "value", - entry.second); - } -} - template <typename DescriptorT> -TProtoStringType PyiGenerator::ModuleLevelName( - const DescriptorT& descriptor, - const std::map<TProtoStringType, TProtoStringType>& import_map) const { +TProtoStringType PyiGenerator::ModuleLevelName(const DescriptorT& descriptor) const { TProtoStringType name = NamePrefixedWithNestedTypes(descriptor, "."); if (descriptor.file() != file_) { TProtoStringType module_alias; TProtoStringType filename = descriptor.file()->name(); - if (import_map.find(filename) == import_map.end()) { + if (import_map_.find(filename) == import_map_.end()) { TProtoStringType module_name = ModuleName(descriptor.file()->name()); - std::vector<TProtoStringType> tokens = Split(module_name, "."); - module_alias = "_" + tokens.back(); + std::vector<y_absl::string_view> tokens = y_absl::StrSplit(module_name, '.'); + module_alias = y_absl::StrCat("_", tokens.back()); } else { - module_alias = import_map.at(filename); + module_alias = import_map_.at(filename); } - name = module_alias + "." + name; + name = y_absl::StrCat(module_alias, ".", name); } return name; } +TProtoStringType PyiGenerator::PublicPackage() const { + return opensource_runtime_ ? "google.protobuf" + : "google3.net.google.protobuf.python.public"; +} + +TProtoStringType PyiGenerator::InternalPackage() const { + return opensource_runtime_ ? "google.protobuf.internal" + : "google3.net.google.protobuf.python.internal"; +} + struct ImportModules { bool has_repeated = false; // _containers bool has_iterable = false; // typing.Iterable @@ -156,41 +156,40 @@ void CheckImportModules(const Descriptor* descriptor, void PyiGenerator::PrintImportForDescriptor( const FileDescriptor& desc, - std::map<TProtoStringType, TProtoStringType>* import_map, - std::set<TProtoStringType>* seen_aliases) const { + y_absl::flat_hash_set<TProtoStringType>* seen_aliases) const { const TProtoStringType& filename = desc.name(); - TProtoStringType module_name = StrippedModuleName(filename); + TProtoStringType module_name_owned = StrippedModuleName(filename); + y_absl::string_view module_name(module_name_owned); size_t last_dot_pos = module_name.rfind('.'); TProtoStringType import_statement; if (last_dot_pos == TProtoStringType::npos) { - import_statement = "import " + module_name; + import_statement = y_absl::StrCat("import ", module_name); } else { - import_statement = "from " + module_name.substr(0, last_dot_pos) + - " import " + module_name.substr(last_dot_pos + 1); + import_statement = + y_absl::StrCat("from ", module_name.substr(0, last_dot_pos), " import ", + module_name.substr(last_dot_pos + 1)); module_name = module_name.substr(last_dot_pos + 1); } - TProtoStringType alias = "_" + module_name; + TProtoStringType alias = y_absl::StrCat("_", module_name); // Generate a unique alias by adding _1 suffixes until we get an unused alias. while (seen_aliases->find(alias) != seen_aliases->end()) { - alias = alias + "_1"; + y_absl::StrAppend(&alias, "_1"); } printer_->Print("$statement$ as $alias$\n", "statement", import_statement, "alias", alias); - (*import_map)[filename] = alias; + import_map_[filename] = alias; seen_aliases->insert(alias); } -void PyiGenerator::PrintImports( - std::map<TProtoStringType, TProtoStringType>* item_map, - std::map<TProtoStringType, TProtoStringType>* import_map) const { +void PyiGenerator::PrintImports() const { // Prints imported dependent _pb2 files. - std::set<TProtoStringType> seen_aliases; + y_absl::flat_hash_set<TProtoStringType> seen_aliases; for (int i = 0; i < file_->dependency_count(); ++i) { const FileDescriptor* dep = file_->dependency(i); - PrintImportForDescriptor(*dep, import_map, &seen_aliases); + PrintImportForDescriptor(*dep, &seen_aliases); for (int j = 0; j < dep->public_dependency_count(); ++j) { PrintImportForDescriptor( - *dep->public_dependency(j), import_map, &seen_aliases); + *dep->public_dependency(j), &seen_aliases); } } @@ -202,6 +201,10 @@ void PyiGenerator::PrintImports( if (file_->enum_type_count() > 0) { import_modules.has_enums = true; } + if (!opensource_runtime_ && file_->service_count() > 0) { + import_modules.has_optional = true; + import_modules.has_union = true; + } for (int i = 0; i < file_->message_type_count(); i++) { CheckImportModules(file_->message_type(i), &import_modules); } @@ -210,37 +213,50 @@ void PyiGenerator::PrintImports( // required in the proto file. if (import_modules.has_repeated) { printer_->Print( - "from google.protobuf.internal import containers as " - "_containers\n"); + "from $internal_package$ import containers as _containers\n", + "internal_package", InternalPackage()); } if (import_modules.has_enums) { printer_->Print( - "from google.protobuf.internal import enum_type_wrapper" - " as _enum_type_wrapper\n"); + "from $internal_package$ import enum_type_wrapper as " + "_enum_type_wrapper\n", + "internal_package", InternalPackage()); } if (import_modules.has_extendable) { printer_->Print( - "from google.protobuf.internal import python_message" - " as _python_message\n"); + "from $internal_package$ import python_message as _python_message\n", + "internal_package", InternalPackage()); } if (import_modules.has_well_known_type) { printer_->Print( - "from google.protobuf.internal import well_known_types" - " as _well_known_types\n"); + "from $internal_package$ import well_known_types as " + "_well_known_types\n", + "internal_package", InternalPackage()); } - printer_->Print( - "from google.protobuf import" - " descriptor as _descriptor\n"); + printer_->Print("from $public_package$ import descriptor as _descriptor\n", + "public_package", PublicPackage()); if (import_modules.has_messages) { - printer_->Print( - "from google.protobuf import message as _message\n"); + printer_->Print("from $public_package$ import message as _message\n", + "public_package", PublicPackage()); } - if (HasGenericServices(file_)) { - printer_->Print( - "from google.protobuf import service as" - " _service\n"); + if (opensource_runtime_) { + if (HasGenericServices(file_)) { + printer_->Print("from $public_package$ import service as _service\n", + "public_package", PublicPackage()); + } + } else { + if (file_->service_count() > 0) { + printer_->Print( + "from google3.net.rpc.python import proto_python_api_2_stub as " + "_proto_python_api_2_stub\n" + "from google3.net.rpc.python import pywraprpc as _pywraprpc\n" + "from google3.net.rpc.python import rpcserver as _rpcserver\n"); + } } printer_->Print("from typing import "); + if (!opensource_runtime_ && file_->service_count() > 0) { + printer_->Print("Any as _Any, "); + } printer_->Print("ClassVar as _ClassVar"); if (import_modules.has_iterable) { printer_->Print(", Iterable as _Iterable"); @@ -254,7 +270,7 @@ void PyiGenerator::PrintImports( if (import_modules.has_union) { printer_->Print(", Union as _Union"); } - printer_->Print("\n\n"); + printer_->Print("\n"); // Public imports for (int i = 0; i < file_->public_dependency_count(); ++i) { @@ -272,17 +288,16 @@ void PyiGenerator::PrintImports( module_name, "enum_class", public_dep->enum_type(i)->name()); } - // Enum values for public imports - for (int i = 0; i < public_dep->enum_type_count(); ++i) { - const EnumDescriptor* enum_descriptor = public_dep->enum_type(i); - for (int j = 0; j < enum_descriptor->value_count(); ++j) { - (*item_map)[enum_descriptor->value(j)->name()] = - ModuleLevelName(*enum_descriptor, *import_map); - } - } - // Top level extensions for public imports - AddExtensions(*public_dep, item_map); } +printer_->Print("\n"); +} + +// Annotate wrapper for debugging purposes +// Print a message after Annotate to see what is annotated. +template <typename DescriptorT> +void PyiGenerator::Annotate(const TProtoStringType& label, + const DescriptorT* descriptor) const { +printer_->Annotate(label.c_str(), descriptor); } void PyiGenerator::PrintEnum(const EnumDescriptor& enum_descriptor) const { @@ -291,22 +306,31 @@ void PyiGenerator::PrintEnum(const EnumDescriptor& enum_descriptor) const { "class $enum_name$(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):\n" " __slots__ = []\n", "enum_name", enum_name); + Annotate("enum_name", &enum_descriptor); + printer_->Indent(); + PrintEnumValues(enum_descriptor, /* is_classvar = */ true); + printer_->Outdent(); } -// Adds enum value to item map which will be ordered and printed later. -void PyiGenerator::AddEnumValue( - const EnumDescriptor& enum_descriptor, - std::map<TProtoStringType, TProtoStringType>* item_map, - const std::map<TProtoStringType, TProtoStringType>& import_map) const { +void PyiGenerator::PrintEnumValues(const EnumDescriptor& enum_descriptor, + bool is_classvar) const { // enum values - TProtoStringType module_enum_name = ModuleLevelName(enum_descriptor, import_map); + TProtoStringType module_enum_name = ModuleLevelName(enum_descriptor); for (int j = 0; j < enum_descriptor.value_count(); ++j) { const EnumValueDescriptor* value_descriptor = enum_descriptor.value(j); - (*item_map)[value_descriptor->name()] = module_enum_name; + if (is_classvar) { + printer_->Print("$name$: _ClassVar[$module_enum_name$]\n", "name", + value_descriptor->name(), "module_enum_name", + module_enum_name); + } else { + printer_->Print("$name$: $module_enum_name$\n", "name", + value_descriptor->name(), "module_enum_name", + module_enum_name); + } + Annotate("name", value_descriptor); } } -// Prints top level enums void PyiGenerator::PrintTopLevelEnums() const { for (int i = 0; i < file_->enum_type_count(); ++i) { printer_->Print("\n"); @@ -314,25 +338,24 @@ void PyiGenerator::PrintTopLevelEnums() const { } } -// Add top level extensions to item_map which will be ordered and -// printed later. template <typename DescriptorT> -void PyiGenerator::AddExtensions( - const DescriptorT& descriptor, - std::map<TProtoStringType, TProtoStringType>* item_map) const { +void PyiGenerator::PrintExtensions(const DescriptorT& descriptor) const { for (int i = 0; i < descriptor.extension_count(); ++i) { const FieldDescriptor* extension_field = descriptor.extension(i); - TProtoStringType constant_name = extension_field->name() + "_FIELD_NUMBER"; - ToUpper(&constant_name); - (*item_map)[constant_name] = "_ClassVar[int]"; - (*item_map)[extension_field->name()] = "_descriptor.FieldDescriptor"; + TProtoStringType constant_name = + y_absl::StrCat(extension_field->name(), "_FIELD_NUMBER"); + y_absl::AsciiStrToUpper(&constant_name); + printer_->Print("$constant_name$: _ClassVar[int]\n", + "constant_name", constant_name); + printer_->Print("$name$: _descriptor.FieldDescriptor\n", + "name", extension_field->name()); + Annotate("name", extension_field); } } // Returns the string format of a field's cpp_type TProtoStringType PyiGenerator::GetFieldType( - const FieldDescriptor& field_des, const Descriptor& containing_des, - const std::map<TProtoStringType, TProtoStringType>& import_map) const { + const FieldDescriptor& field_des, const Descriptor& containing_des) const { switch (field_des.cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: case FieldDescriptor::CPPTYPE_UINT32: @@ -345,7 +368,7 @@ TProtoStringType PyiGenerator::GetFieldType( case FieldDescriptor::CPPTYPE_BOOL: return "bool"; case FieldDescriptor::CPPTYPE_ENUM: - return ModuleLevelName(*field_des.enum_type(), import_map); + return ModuleLevelName(*field_des.enum_type()); case FieldDescriptor::CPPTYPE_STRING: if (field_des.type() == FieldDescriptor::TYPE_STRING) { return "str"; @@ -356,23 +379,22 @@ TProtoStringType PyiGenerator::GetFieldType( // If the field is inside a nested message and the nested message has the // same name as a top-level message, then we need to prefix the field type // with the module name for disambiguation. - TProtoStringType name = ModuleLevelName(*field_des.message_type(), import_map); + TProtoStringType name = ModuleLevelName(*field_des.message_type()); if ((containing_des.containing_type() != nullptr && name == containing_des.name())) { TProtoStringType module = ModuleName(field_des.file()->name()); - name = module + "." + name; + name = y_absl::StrCat(module, ".", name); } return name; } default: - GOOGLE_LOG(FATAL) << "Unsupported field type."; + Y_ABSL_LOG(FATAL) << "Unsupported field type."; } return ""; } void PyiGenerator::PrintMessage( - const Descriptor& message_descriptor, bool is_nested, - const std::map<TProtoStringType, TProtoStringType>& import_map) const { + const Descriptor& message_descriptor, bool is_nested) const { if (!is_nested) { printer_->Print("\n"); } @@ -381,26 +403,21 @@ void PyiGenerator::PrintMessage( // A well-known type needs to inherit from its corresponding base class in // net/proto2/python/internal/well_known_types. if (IsWellKnownType(message_descriptor.full_name())) { - extra_base = ", _well_known_types." + message_descriptor.name(); + extra_base = + y_absl::StrCat(", _well_known_types.", message_descriptor.name()); } else { extra_base = ""; } printer_->Print("class $class_name$(_message.Message$extra_base$):\n", "class_name", class_name, "extra_base", extra_base); + Annotate("class_name", &message_descriptor); printer_->Indent(); - printer_->Indent(); - - std::vector<const FieldDescriptor*> fields; - fields.reserve(message_descriptor.field_count()); - for (int i = 0; i < message_descriptor.field_count(); ++i) { - fields.push_back(message_descriptor.field(i)); - } - std::sort(fields.begin(), fields.end(), SortByName<FieldDescriptor>()); // Prints slots printer_->Print("__slots__ = [", "class_name", class_name); bool first_item = true; - for (const auto& field_des : fields) { + for (int i = 0; i < message_descriptor.field_count(); ++i) { + const FieldDescriptor* field_des = message_descriptor.field(i); if (IsPythonKeyword(field_des->name())) { continue; } @@ -413,48 +430,34 @@ void PyiGenerator::PrintMessage( } printer_->Print("]\n"); - std::map<TProtoStringType, TProtoStringType> item_map; // Prints Extensions for extendable messages if (message_descriptor.extension_range_count() > 0) { - item_map["Extensions"] = "_python_message._ExtensionDict"; + printer_->Print("Extensions: _python_message._ExtensionDict\n"); } // Prints nested enums - std::vector<const EnumDescriptor*> nested_enums; - nested_enums.reserve(message_descriptor.enum_type_count()); for (int i = 0; i < message_descriptor.enum_type_count(); ++i) { - nested_enums.push_back(message_descriptor.enum_type(i)); - } - std::sort(nested_enums.begin(), nested_enums.end(), - SortByName<EnumDescriptor>()); - - for (const auto& entry : nested_enums) { - PrintEnum(*entry); - // Adds enum value to item_map which will be ordered and printed later - AddEnumValue(*entry, &item_map, import_map); + PrintEnum(*message_descriptor.enum_type(i)); + PrintEnumValues(*message_descriptor.enum_type(i)); } // Prints nested messages - std::vector<const Descriptor*> nested_messages; - nested_messages.reserve(message_descriptor.nested_type_count()); for (int i = 0; i < message_descriptor.nested_type_count(); ++i) { - nested_messages.push_back(message_descriptor.nested_type(i)); + PrintMessage(*message_descriptor.nested_type(i), true); } - std::sort(nested_messages.begin(), nested_messages.end(), - SortByName<Descriptor>()); - for (const auto& entry : nested_messages) { - PrintMessage(*entry, true, import_map); - } - - // Adds extensions to item_map which will be ordered and printed later - AddExtensions(message_descriptor, &item_map); + PrintExtensions(message_descriptor); - // Adds field number and field descriptor to item_map + // Prints field number + for (int i = 0; i < message_descriptor.field_count(); ++i) { + const FieldDescriptor& field_des = *message_descriptor.field(i); + printer_->Print( + "$field_number_name$: _ClassVar[int]\n", "field_number_name", + y_absl::StrCat(y_absl::AsciiStrToUpper(field_des.name()), "_FIELD_NUMBER")); + } + // Prints field name and type for (int i = 0; i < message_descriptor.field_count(); ++i) { const FieldDescriptor& field_des = *message_descriptor.field(i); - item_map[ToUpper(field_des.name()) + "_FIELD_NUMBER"] = - "_ClassVar[int]"; if (IsPythonKeyword(field_des.name())) { continue; } @@ -462,30 +465,29 @@ void PyiGenerator::PrintMessage( if (field_des.is_map()) { const FieldDescriptor* key_des = field_des.message_type()->field(0); const FieldDescriptor* value_des = field_des.message_type()->field(1); - field_type = (value_des->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE - ? "_containers.MessageMap[" - : "_containers.ScalarMap["); - field_type += GetFieldType(*key_des, message_descriptor, import_map); - field_type += ", "; - field_type += GetFieldType(*value_des, message_descriptor, import_map); + field_type = + y_absl::StrCat(value_des->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE + ? "_containers.MessageMap[" + : "_containers.ScalarMap[", + GetFieldType(*key_des, message_descriptor), ", ", + GetFieldType(*value_des, message_descriptor)); } else { if (field_des.is_repeated()) { field_type = (field_des.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ? "_containers.RepeatedCompositeFieldContainer[" : "_containers.RepeatedScalarFieldContainer["); } - field_type += GetFieldType(field_des, message_descriptor, import_map); + field_type += GetFieldType(field_des, message_descriptor); } if (field_des.is_repeated()) { - field_type += "]"; + y_absl::StrAppend(&field_type, "]"); } - item_map[field_des.name()] = field_type; + printer_->Print("$name$: $type$\n", + "name", field_des.name(), "type", field_type); + Annotate("name", &field_des); } - // Prints all items in item_map - PrintItemMap(item_map); - // Prints __init__ printer_->Print("def __init__(self"); bool has_key_words = false; @@ -505,6 +507,7 @@ void PyiGenerator::PrintMessage( } is_first = false; printer_->Print(", $field_name$: ", "field_name", field_name); + Annotate("field_name", field_des); if (field_des->is_repeated() || field_des->cpp_type() != FieldDescriptor::CPPTYPE_BOOL) { printer_->Print("_Optional["); @@ -513,9 +516,9 @@ void PyiGenerator::PrintMessage( const Descriptor* map_entry = field_des->message_type(); printer_->Print( "_Mapping[$key_type$, $value_type$]", "key_type", - GetFieldType(*map_entry->field(0), message_descriptor, import_map), + GetFieldType(*map_entry->field(0), message_descriptor), "value_type", - GetFieldType(*map_entry->field(1), message_descriptor, import_map)); + GetFieldType(*map_entry->field(1), message_descriptor)); } else { if (field_des->is_repeated()) { printer_->Print("_Iterable["); @@ -523,15 +526,15 @@ void PyiGenerator::PrintMessage( if (field_des->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { printer_->Print( "_Union[$type_name$, _Mapping]", "type_name", - GetFieldType(*field_des, message_descriptor, import_map)); + GetFieldType(*field_des, message_descriptor)); } else { if (field_des->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { printer_->Print("_Union[$type_name$, str]", "type_name", - ModuleLevelName(*field_des->enum_type(), import_map)); + ModuleLevelName(*field_des->enum_type())); } else { printer_->Print( "$type_name$", "type_name", - GetFieldType(*field_des, message_descriptor, import_map)); + GetFieldType(*field_des, message_descriptor)); } } if (field_des->is_repeated()) { @@ -548,83 +551,92 @@ void PyiGenerator::PrintMessage( printer_->Print(", **kwargs"); } printer_->Print(") -> None: ...\n"); - - printer_->Outdent(); printer_->Outdent(); } -void PyiGenerator::PrintMessages( - const std::map<TProtoStringType, TProtoStringType>& import_map) const { +void PyiGenerator::PrintMessages() const { // Deterministically order the descriptors. - std::vector<const Descriptor*> messages; - messages.reserve(file_->message_type_count()); for (int i = 0; i < file_->message_type_count(); ++i) { - messages.push_back(file_->message_type(i)); - } - std::sort(messages.begin(), messages.end(), SortByName<Descriptor>()); - - for (const auto& entry : messages) { - PrintMessage(*entry, false, import_map); + PrintMessage(*file_->message_type(i), false); } } void PyiGenerator::PrintServices() const { - std::vector<const ServiceDescriptor*> services; - services.reserve(file_->service_count()); - for (int i = 0; i < file_->service_count(); ++i) { - services.push_back(file_->service(i)); - } - std::sort(services.begin(), services.end(), SortByName<ServiceDescriptor>()); - // Prints $Service$ and $Service$_Stub classes - for (const auto& entry : services) { + for (int i = 0; i < file_->service_count(); ++i) { printer_->Print("\n"); printer_->Print( "class $service_name$(_service.service): ...\n\n" "class $service_name$_Stub($service_name$): ...\n", - "service_name", entry->name()); + "service_name", file_->service(i)->name()); } } + bool PyiGenerator::Generate(const FileDescriptor* file, const TProtoStringType& parameter, GeneratorContext* context, TProtoStringType* error) const { - MutexLock lock(&mutex_); + y_absl::MutexLock lock(&mutex_); + import_map_.clear(); // Calculate file name. file_ = file; - TProtoStringType filename = - parameter.empty() ? GetFileName(file, ".pyi") : parameter; + // In google3, devtools/python/blaze/pytype/pytype_impl.bzl uses --pyi_out to + // directly set the output file name. + std::vector<std::pair<TProtoStringType, TProtoStringType> > options; + ParseGeneratorParameter(parameter, &options); + + TProtoStringType filename; + bool annotate_code = false; + for (const std::pair<TProtoStringType, TProtoStringType>& option : options) { + if (option.first == "annotate_code") { + annotate_code = true; + } else if (y_absl::EndsWith(option.first, ".pyi")) { + filename = option.first; + } else { + *error = y_absl::StrCat("Unknown generator option: ", option.first); + return false; + } + } + + if (filename.empty()) { + filename = GetFileName(file, ".pyi"); + } std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename)); - GOOGLE_CHECK(output.get()); - io::Printer printer(output.get(), '$'); + Y_ABSL_CHECK(output.get()); + GeneratedCodeInfo annotations; + io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector( + &annotations); + io::Printer::Options printer_opt( + '$', annotate_code ? &annotation_collector : nullptr); + printer_opt.spaces_per_indent = 4; + io::Printer printer(output.get(), printer_opt); printer_ = &printer; - // item map will store "DESCRIPTOR", top level extensions, top level enum - // values. The items will be sorted and printed later. - std::map<TProtoStringType, TProtoStringType> item_map; - - // Adds "DESCRIPTOR" into item_map. - item_map["DESCRIPTOR"] = "_descriptor.FileDescriptor"; + PrintImports(); + printer_->Print("DESCRIPTOR: _descriptor.FileDescriptor\n"); - // import_map will be a mapping from filename to module alias, e.g. - // "google3/foo/bar.py" -> "_bar" - std::map<TProtoStringType, TProtoStringType> import_map; + // Prints extensions and enums from imports. + for (int i = 0; i < file_->public_dependency_count(); ++i) { + const FileDescriptor* public_dep = file_->public_dependency(i); + PrintExtensions(*public_dep); + for (int i = 0; i < public_dep->enum_type_count(); ++i) { + const EnumDescriptor* enum_descriptor = public_dep->enum_type(i); + PrintEnumValues(*enum_descriptor); + } + } - PrintImports(&item_map, &import_map); - // Adds top level enum values to item_map. + PrintTopLevelEnums(); + // Prints top level enum values for (int i = 0; i < file_->enum_type_count(); ++i) { - AddEnumValue(*file_->enum_type(i), &item_map, import_map); + PrintEnumValues(*file_->enum_type(i)); } - // Adds top level extensions to item_map. - AddExtensions(*file_, &item_map); - // Prints item map - PrintItemMap(item_map); + // Prints top level Extensions + PrintExtensions(*file_); + PrintMessages(); - PrintMessages(import_map); - PrintTopLevelEnums(); - if (HasGenericServices(file)) { + if (opensource_runtime_ && HasGenericServices(file)) { PrintServices(); } return true; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/python/pyi_generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/python/pyi_generator.h index c9bf2961665..091a252c4bd 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/python/pyi_generator.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/python/pyi_generator.h @@ -35,15 +35,15 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_PYTHON_PYI_GENERATOR_H__ #define GOOGLE_PROTOBUF_COMPILER_PYTHON_PYI_GENERATOR_H__ -#include <map> -#include <set> #include <string> -#include <google/protobuf/stubs/mutex.h> -#include <google/protobuf/compiler/code_generator.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/synchronization/mutex.h" +#include "google/protobuf/compiler/code_generator.h" // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -63,6 +63,8 @@ namespace python { class PROTOC_EXPORT PyiGenerator : public google::protobuf::compiler::CodeGenerator { public: PyiGenerator(); + PyiGenerator(const PyiGenerator&) = delete; + PyiGenerator& operator=(const PyiGenerator&) = delete; ~PyiGenerator() override; // CodeGenerator methods. @@ -75,39 +77,38 @@ class PROTOC_EXPORT PyiGenerator : public google::protobuf::compiler::CodeGenera TProtoStringType* error) const override; private: - void PrintImportForDescriptor(const FileDescriptor& desc, - std::map<TProtoStringType, TProtoStringType>* import_map, - std::set<TProtoStringType>* seen_aliases) const; - void PrintImports(std::map<TProtoStringType, TProtoStringType>* item_map, - std::map<TProtoStringType, TProtoStringType>* import_map) const; - void PrintEnum(const EnumDescriptor& enum_descriptor) const; - void AddEnumValue(const EnumDescriptor& enum_descriptor, - std::map<TProtoStringType, TProtoStringType>* item_map, - const std::map<TProtoStringType, TProtoStringType>& import_map) const; + void PrintImportForDescriptor( + const FileDescriptor& desc, + y_absl::flat_hash_set<TProtoStringType>* seen_aliases) const; + template <typename DescriptorT> + void Annotate(const TProtoStringType& label, const DescriptorT* descriptor) const; + void PrintImports() const; void PrintTopLevelEnums() const; + void PrintEnum(const EnumDescriptor& enum_descriptor) const; + void PrintEnumValues(const EnumDescriptor& enum_descriptor, + bool is_classvar = false) const; template <typename DescriptorT> - void AddExtensions(const DescriptorT& descriptor, - std::map<TProtoStringType, TProtoStringType>* item_map) const; - void PrintMessages( - const std::map<TProtoStringType, TProtoStringType>& import_map) const; - void PrintMessage(const Descriptor& message_descriptor, bool is_nested, - const std::map<TProtoStringType, TProtoStringType>& import_map) const; + void PrintExtensions(const DescriptorT& descriptor) const; + void PrintMessages() const; + void PrintMessage(const Descriptor& message_descriptor, bool is_nested) const; void PrintServices() const; - void PrintItemMap(const std::map<TProtoStringType, TProtoStringType>& item_map) const; TProtoStringType GetFieldType( - const FieldDescriptor& field_des, const Descriptor& containing_des, - const std::map<TProtoStringType, TProtoStringType>& import_map) const; + const FieldDescriptor& field_des, const Descriptor& containing_des) const; template <typename DescriptorT> - TProtoStringType ModuleLevelName( - const DescriptorT& descriptor, - const std::map<TProtoStringType, TProtoStringType>& import_map) const; + TProtoStringType ModuleLevelName(const DescriptorT& descriptor) const; + TProtoStringType PublicPackage() const; + TProtoStringType InternalPackage() const; + + bool opensource_runtime_ = true; // Very coarse-grained lock to ensure that Generate() is reentrant. - // Guards file_ and printer_. - mutable Mutex mutex_; + // Guards file_, printer_, and import_map_. + mutable y_absl::Mutex mutex_; mutable const FileDescriptor* file_; // Set in Generate(). Under mutex_. mutable io::Printer* printer_; // Set in Generate(). Under mutex_. - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PyiGenerator); + // import_map will be a mapping from filename to module alias, e.g. + // "google3/foo/bar.py" -> "_bar" + mutable y_absl::flat_hash_map<TProtoStringType, TProtoStringType> import_map_; }; } // namespace python @@ -115,6 +116,6 @@ class PROTOC_EXPORT PyiGenerator : public google::protobuf::compiler::CodeGenera } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_PYTHON_PYI_GENERATOR_H__ |