summaryrefslogtreecommitdiffstats
path: root/contrib/libs/protoc/src/google/protobuf/compiler/python
diff options
context:
space:
mode:
authormikhnenko <[email protected]>2024-06-25 08:50:35 +0300
committermikhnenko <[email protected]>2024-06-25 09:00:27 +0300
commit509c9fc9e7b9c3b8be7307d72a4c966e5f9aa194 (patch)
tree4b8a6a44009906ac852e59efa0bc78bb12043a5b /contrib/libs/protoc/src/google/protobuf/compiler/python
parent7688f2313619a39a60ef3c2734d8efbc49a0a6db (diff)
Update protobuf to 3.20.2 and pyprotobuf to 3.20.3
Если это pull-request что-то сломал, то: - если это тест с канонизацией и еще нет pr с переканонизацией, то переканонизируйте пожалуйста сами - проверьте, что тест не флапает - приходите в [DEVTOOLSSUPPORT](https://st.yandex-team.ru/createTicket?queue=DEVTOOLSSUPPORT) - там вам обязательно помогут 987be5ed151f827f7f292f32420470b04b71a91d
Diffstat (limited to 'contrib/libs/protoc/src/google/protobuf/compiler/python')
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/python/python_generator.cc271
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/python/python_generator.h24
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/python/python_helpers.cc138
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/python/python_helpers.h62
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/python/python_pyi_generator.cc558
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/python/python_pyi_generator.h104
6 files changed, 913 insertions, 244 deletions
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/python/python_generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/python/python_generator.cc
index ba79c259089..7c723febb38 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/python/python_generator.cc
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/python/python_generator.cc
@@ -54,13 +54,15 @@
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/compiler/python/python_helpers.h>
+#include <google/protobuf/compiler/python/python_pyi_generator.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/stringprintf.h>
#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/descriptor.pb.h>
namespace google {
namespace protobuf {
@@ -68,22 +70,6 @@ namespace compiler {
namespace python {
namespace {
-
-TProtoStringType FixEv(const TProtoStringType& filename) {
- if (HasSuffixString(filename, ".ev")) {
- return StripSuffixString(filename, ".ev") + "_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";
-}
-
// 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
@@ -98,78 +84,18 @@ TProtoStringType ModuleAlias(const TProtoStringType& filename) {
return module_name;
}
-// Keywords reserved by the Python language.
-const char* const kKeywords[] = {
- "False", "None", "True", "and", "as", "assert",
- "async", "await", "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", "print",
-};
-const char* const* kKeywordsEnd =
- kKeywords + (sizeof(kKeywords) / sizeof(kKeywords[0]));
-
-bool ContainsPythonKeyword(const TProtoStringType& module_name) {
- std::vector<TProtoStringType> tokens = Split(module_name, ".");
- for (int i = 0; i < tokens.size(); ++i) {
- if (std::find(kKeywords, kKeywordsEnd, tokens[i]) != kKeywordsEnd) {
- return true;
- }
- }
- return false;
-}
-
-inline bool IsPythonKeyword(const TProtoStringType& name) {
- return (std::find(kKeywords, kKeywordsEnd, name) != kKeywordsEnd);
-}
-
-TProtoStringType ResolveKeyword(const TProtoStringType& name) {
- if (IsPythonKeyword(name)) {
- return "globals()['" + name + "']";
- }
- return name;
-}
-
-// 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>
-TProtoStringType NamePrefixedWithNestedTypes(const DescriptorT& descriptor,
- const TProtoStringType& 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 + "')";
- } else {
- return prefix + separator + name;
- }
- }
- if (separator == ".") {
- name = ResolveKeyword(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) {
@@ -180,27 +106,16 @@ void PrintTopBoilerplate(io::Printer* printer, const FileDescriptor* file,
"# source: $filename$\n"
"\"\"\"Generated protocol buffer code.\"\"\"\n",
"filename", file->name());
- if (HasTopLevelEnums(file)) {
- printer->Print(
- "from google.protobuf.internal import enum_type_wrapper\n");
- }
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 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("# @@protoc_insertion_point(imports)\n\n");
+ printer->Print("_sym_db = _symbol_database.Default()\n");
printer->Print("\n\n");
}
@@ -315,6 +230,11 @@ bool Generator::Generate(const FileDescriptor* file,
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;
return false;
@@ -330,11 +250,8 @@ bool Generator::Generate(const FileDescriptor* file,
// to have any mutable members. Then it is implicitly thread-safe.
MutexLock lock(&mutex_);
file_ = file;
- TProtoStringType module_name = ModuleName(file->name());
- TProtoStringType filename = module_name;
- ReplaceCharacters(&filename, ".", '/');
- filename += ".py";
+ TProtoStringType filename = GetFileName(file, ".py");
pure_python_workable_ = !cpp_generated_lib_linked;
if (HasPrefixString(file->name(), "google/protobuf/")) {
pure_python_workable_ = true;
@@ -355,15 +272,13 @@ bool Generator::Generate(const FileDescriptor* file,
PrintImports();
}
PrintFileDescriptor();
- PrintTopLevelEnums();
- PrintTopLevelExtensions();
if (pure_python_workable_) {
if (GeneratingDescriptorProto()) {
printer_->Print("if _descriptor._USE_C_DESCRIPTORS == False:\n");
printer_->Indent();
// Create enums before message descriptors
- PrintAllNestedEnumsInFile(StripPrintDescriptor::kCreate);
- PrintMessageDescriptors(StripPrintDescriptor::kCreate);
+ PrintAllNestedEnumsInFile();
+ PrintMessageDescriptors();
FixForeignFieldsInDescriptors();
printer_->Outdent();
printer_->Print("else:\n");
@@ -371,16 +286,18 @@ bool Generator::Generate(const FileDescriptor* file,
}
// Find the message descriptors first and then use the message
// descriptor to find enums.
- PrintMessageDescriptors(StripPrintDescriptor::kFind);
- PrintAllNestedEnumsInFile(StripPrintDescriptor::kFind);
+ printer_->Print(
+ "_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())\n");
if (GeneratingDescriptorProto()) {
printer_->Outdent();
}
}
- PrintMessages();
+ TProtoStringType module_name = ModuleName(file->name());
+ printer_->Print(
+ "_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, '$module_name$', "
+ "globals())\n",
+ "module_name", module_name);
if (pure_python_workable_) {
- PrintServiceDescriptors();
-
printer.Print("if _descriptor._USE_C_DESCRIPTORS == False:\n");
printer_->Indent();
@@ -401,7 +318,9 @@ bool Generator::Generate(const FileDescriptor* file,
printer_->Outdent();
}
if (HasGenericServices(file)) {
- PrintServices();
+ printer_->Print(
+ "_builder.BuildServices(DESCRIPTOR, '$module_name$', globals())\n",
+ "module_name", module_name);
}
printer.Print("# @@protoc_insertion_point(module_scope)\n");
@@ -409,7 +328,6 @@ bool Generator::Generate(const FileDescriptor* file,
return !printer.failed();
}
-
// Prints Python imports for all modules imported by |file|.
void Generator::PrintImports() const {
for (int i = 0; i < file_->dependency_count(); ++i) {
@@ -522,47 +440,17 @@ void Generator::PrintFileDescriptor() const {
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<TProtoStringType, int> > top_level_enum_values;
- for (int i = 0; i < file_->enum_type_count(); ++i) {
- const EnumDescriptor& enum_descriptor = *file_->enum_type(i);
- PrintFindEnum(enum_descriptor);
- printer_->Print(
- "$name$ = "
- "enum_type_wrapper.EnumTypeWrapper($descriptor_name$)",
- "name", ResolveKeyword(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",
- ResolveKeyword(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(
- StripPrintDescriptor print_mode) const {
+void Generator::PrintAllNestedEnumsInFile() const {
for (int i = 0; i < file_->message_type_count(); ++i) {
- PrintNestedEnums(*file_->message_type(i), print_mode);
+ 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::PrintCreateEnum(const EnumDescriptor& enum_descriptor) const {
+void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const {
std::map<TProtoStringType, TProtoStringType> m;
TProtoStringType module_level_descriptor_name =
ModuleLevelDescriptorName(enum_descriptor);
@@ -606,68 +494,23 @@ void Generator::PrintCreateEnum(const EnumDescriptor& enum_descriptor) const {
printer_->Print("\n");
}
-void Generator::PrintFindEnum(const EnumDescriptor& enum_descriptor) const {
- std::map<TProtoStringType, TProtoStringType> m;
- m["descriptor_name"] = ModuleLevelDescriptorName(enum_descriptor);
- m["name"] = enum_descriptor.name();
- m["file"] = kDescriptorKey;
- if (enum_descriptor.containing_type()) {
- m["containing_type"] =
- ModuleLevelDescriptorName(*enum_descriptor.containing_type());
- printer_->Print(m,
- "$descriptor_name$ = "
- "$containing_type$.enum_types_by_name['$name$']\n");
- } else {
- printer_->Print(
- m, "$descriptor_name$ = $file$.enum_types_by_name['$name$']\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,
- StripPrintDescriptor print_mode) const {
+void Generator::PrintNestedEnums(const Descriptor& descriptor) const {
for (int i = 0; i < descriptor.nested_type_count(); ++i) {
- PrintNestedEnums(*descriptor.nested_type(i), print_mode);
+ PrintNestedEnums(*descriptor.nested_type(i));
}
for (int i = 0; i < descriptor.enum_type_count(); ++i) {
- if (print_mode == StripPrintDescriptor::kCreate) {
- PrintCreateEnum(*descriptor.enum_type(i));
- } else {
- PrintFindEnum(*descriptor.enum_type(i));
- }
+ PrintEnum(*descriptor.enum_type(i));
}
}
-void Generator::PrintTopLevelExtensions() const {
- for (int i = 0; i < file_->extension_count(); ++i) {
- const FieldDescriptor& extension_field = *file_->extension(i);
- TProtoStringType constant_name = extension_field.name() + "_FIELD_NUMBER";
- ToUpper(&constant_name);
- printer_->Print("$constant_name$ = $number$\n", "constant_name",
- constant_name, "number",
- StrCat(extension_field.number()));
- printer_->Print(
- "$resolved_name$ = "
- "$file$.extensions_by_name['$name$']\n",
- "resolved_name", ResolveKeyword(extension_field.name()), "file",
- kDescriptorKey, "name", extension_field.name());
- }
- printer_->Print("\n");
-}
-
// Prints Python equivalents of all Descriptors in |file|.
-void Generator::PrintMessageDescriptors(StripPrintDescriptor print_mode) const {
- if (print_mode == StripPrintDescriptor::kCreate) {
- for (int i = 0; i < file_->message_type_count(); ++i) {
- PrintCreateDescriptor(*file_->message_type(i));
- printer_->Print("\n");
- }
- } else {
- for (int i = 0; i < file_->message_type_count(); ++i) {
- PrintFindDescriptor(*file_->message_type(i));
- }
+void Generator::PrintMessageDescriptors() const {
+ for (int i = 0; i < file_->message_type_count(); ++i) {
+ PrintDescriptor(*file_->message_type(i));
+ printer_->Print("\n");
}
}
@@ -736,14 +579,13 @@ void Generator::PrintServiceStub(const ServiceDescriptor& descriptor) const {
// to a Python Descriptor object for message_descriptor.
//
// Mutually recursive with PrintNestedDescriptors().
-void Generator::PrintCreateDescriptor(
- const Descriptor& message_descriptor) const {
+void Generator::PrintDescriptor(const Descriptor& message_descriptor) const {
std::map<TProtoStringType, TProtoStringType> m;
m["name"] = message_descriptor.name();
m["full_name"] = message_descriptor.full_name();
m["file"] = kDescriptorKey;
- PrintNestedDescriptors(message_descriptor, StripPrintDescriptor::kCreate);
+ PrintNestedDescriptors(message_descriptor);
printer_->Print("\n");
printer_->Print("$descriptor_name$ = _descriptor.Descriptor(\n",
@@ -829,41 +671,14 @@ void Generator::PrintCreateDescriptor(
printer_->Print(")\n");
}
-void Generator::PrintFindDescriptor(
- const Descriptor& message_descriptor) const {
- std::map<TProtoStringType, TProtoStringType> m;
- m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor);
- m["name"] = message_descriptor.name();
-
- if (message_descriptor.containing_type()) {
- m["containing_type"] =
- ModuleLevelDescriptorName(*message_descriptor.containing_type());
- printer_->Print(m,
- "$descriptor_name$ = "
- "$containing_type$.nested_types_by_name['$name$']\n");
- } else {
- m["file"] = kDescriptorKey;
- printer_->Print(
- m, "$descriptor_name$ = $file$.message_types_by_name['$name$']\n");
- }
-
- PrintNestedDescriptors(message_descriptor, StripPrintDescriptor::kFind);
-}
-
// Prints Python Descriptor objects for all nested types contained in
// message_descriptor.
//
// Mutually recursive with PrintDescriptor().
-void Generator::PrintNestedDescriptors(const Descriptor& containing_descriptor,
- StripPrintDescriptor print_mode) const {
- if (print_mode == StripPrintDescriptor::kCreate) {
- for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) {
- PrintCreateDescriptor(*containing_descriptor.nested_type(i));
- }
- } else {
- for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) {
- PrintFindDescriptor(*containing_descriptor.nested_type(i));
- }
+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));
}
}
@@ -1469,7 +1284,7 @@ void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const {
if (value_options != "None") {
PrintDescriptorOptionsFixingCode(
StringPrintf("%s.values_by_name[\"%s\"]", descriptor_name.c_str(),
- value_descriptor.name().c_str()),
+ value_descriptor.name().c_str()),
value_options, printer_);
}
}
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/python/python_generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/python/python_generator.h
index d5af959fceb..359d802aeea 100644
--- a/contrib/libs/protoc/src/google/protobuf/compiler/python/python_generator.h
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/python/python_generator.h
@@ -40,6 +40,7 @@
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/stubs/mutex.h>
+// Must be included last.
#include <google/protobuf/port_def.inc>
namespace google {
@@ -59,8 +60,6 @@ class Printer;
namespace compiler {
namespace python {
-enum class StripPrintDescriptor { kCreate, kFind };
-
// CodeGenerator implementation for generated Python protocol buffer classes.
// 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
@@ -68,7 +67,7 @@ enum class StripPrintDescriptor { kCreate, kFind };
class PROTOC_EXPORT Generator : public CodeGenerator {
public:
Generator();
- virtual ~Generator();
+ ~Generator() override;
// CodeGenerator methods.
bool Generate(const FileDescriptor* file, const TProtoStringType& parameter,
@@ -80,14 +79,9 @@ class PROTOC_EXPORT Generator : public CodeGenerator {
private:
void PrintImports() const;
void PrintFileDescriptor() const;
- void PrintTopLevelEnums() const;
- void PrintAllNestedEnumsInFile(StripPrintDescriptor print_mode) const;
- void PrintNestedEnums(const Descriptor& descriptor,
- StripPrintDescriptor print_mode) const;
- void PrintCreateEnum(const EnumDescriptor& enum_descriptor) const;
- void PrintFindEnum(const EnumDescriptor& enum_descriptor) const;
-
- void PrintTopLevelExtensions() const;
+ void PrintAllNestedEnumsInFile() const;
+ void PrintNestedEnums(const Descriptor& descriptor) const;
+ void PrintEnum(const EnumDescriptor& enum_descriptor) const;
void PrintFieldDescriptor(const FieldDescriptor& field,
bool is_extension) const;
@@ -97,11 +91,9 @@ class PROTOC_EXPORT Generator : public CodeGenerator {
const FieldDescriptor* (Descriptor::*GetterFn)(int)const) const;
void PrintFieldsInDescriptor(const Descriptor& message_descriptor) const;
void PrintExtensionsInDescriptor(const Descriptor& message_descriptor) const;
- void PrintMessageDescriptors(StripPrintDescriptor print_mode) const;
- void PrintCreateDescriptor(const Descriptor& message_descriptor) const;
- void PrintFindDescriptor(const Descriptor& message_descriptor) const;
- void PrintNestedDescriptors(const Descriptor& containing_descriptor,
- StripPrintDescriptor print_mode) const;
+ void PrintMessageDescriptors() const;
+ void PrintDescriptor(const Descriptor& message_descriptor) const;
+ void PrintNestedDescriptors(const Descriptor& containing_descriptor) const;
void PrintMessages() const;
void PrintMessage(const Descriptor& message_descriptor,
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/python/python_helpers.cc b/contrib/libs/protoc/src/google/protobuf/compiler/python/python_helpers.cc
new file mode 100644
index 00000000000..7a9721c02ca
--- /dev/null
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/python/python_helpers.cc
@@ -0,0 +1,138 @@
+// 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.
+
+#include <google/protobuf/compiler/python/python_helpers.h>
+
+#include <algorithm>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/stubs/strutil.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;
+}
+
+// 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 StrippedModuleName(const TProtoStringType& filename) {
+ TProtoStringType module_name = ModuleName(filename);
+ return module_name;
+}
+
+// Keywords reserved by the Python language.
+const char* const kKeywords[] = {
+ "False", "None", "True", "and", "as", "assert",
+ "async", "await", "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", "print",
+};
+const char* const* kKeywordsEnd =
+ kKeywords + (sizeof(kKeywords) / sizeof(kKeywords[0]));
+
+bool ContainsPythonKeyword(const TProtoStringType& module_name) {
+ std::vector<TProtoStringType> tokens = Split(module_name, ".");
+ for (int i = 0; i < static_cast<int>(tokens.size()); ++i) {
+ if (std::find(kKeywords, kKeywordsEnd, tokens[i]) != kKeywordsEnd) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool IsPythonKeyword(const TProtoStringType& name) {
+ return (std::find(kKeywords, kKeywordsEnd, name) != kKeywordsEnd);
+}
+
+TProtoStringType ResolveKeyword(const TProtoStringType& name) {
+ if (IsPythonKeyword(name)) {
+ return "globals()['" + name + "']";
+ }
+ return name;
+}
+
+TProtoStringType GetFileName(const FileDescriptor* file_des,
+ const TProtoStringType& suffix) {
+ TProtoStringType module_name = ModuleName(file_des->name());
+ TProtoStringType filename = module_name;
+ ReplaceCharacters(&filename, ".", '/');
+ filename += suffix;
+ return filename;
+}
+
+bool HasGenericServices(const FileDescriptor* file) {
+ return file->service_count() > 0 && file->options().py_generic_services();
+}
+
+template <typename DescriptorT>
+TProtoStringType NamePrefixedWithNestedTypes(const DescriptorT& descriptor,
+ const TProtoStringType& 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 + "')";
+ } else {
+ return prefix + separator + name;
+ }
+ }
+ if (separator == ".") {
+ name = ResolveKeyword(name);
+ }
+ return name;
+}
+
+template TProtoStringType NamePrefixedWithNestedTypes<Descriptor>(
+ const Descriptor& descriptor, const TProtoStringType& separator);
+template TProtoStringType NamePrefixedWithNestedTypes<EnumDescriptor>(
+ const EnumDescriptor& descriptor, const TProtoStringType& separator);
+
+} // namespace python
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/python/python_helpers.h b/contrib/libs/protoc/src/google/protobuf/compiler/python/python_helpers.h
new file mode 100644
index 00000000000..8745698acf6
--- /dev/null
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/python/python_helpers.h
@@ -0,0 +1,62 @@
+// 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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_PYTHON_HELPERS_H__
+#define GOOGLE_PROTOBUF_COMPILER_PYTHON_HELPERS_H__
+
+#include <string>
+
+#include <google/protobuf/descriptor.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 GetFileName(const FileDescriptor* file_des,
+ const TProtoStringType& suffix);
+bool HasGenericServices(const FileDescriptor* file);
+
+template <typename DescriptorT>
+TProtoStringType NamePrefixedWithNestedTypes(const DescriptorT& descriptor,
+ const TProtoStringType& separator);
+
+} // namespace python
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_PYTHON_HELPERS_H__
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/python/python_pyi_generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/python/python_pyi_generator.cc
new file mode 100644
index 00000000000..89cfbf86fe6
--- /dev/null
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/python/python_pyi_generator.cc
@@ -0,0 +1,558 @@
+// 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.
+
+#include <google/protobuf/compiler/python/python_pyi_generator.h>
+
+#include <string>
+
+#include <google/protobuf/compiler/python/python_helpers.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/descriptor.pb.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 {
+ TProtoStringType name = NamePrefixedWithNestedTypes(descriptor, ".");
+ if (descriptor.file() != file_) {
+ TProtoStringType module_name = ModuleName(descriptor.file()->name());
+ std::vector<TProtoStringType> tokens = Split(module_name, ".");
+ name = "_" + tokens.back() + "." + name;
+ }
+ return name;
+}
+
+struct ImportModules {
+ bool has_repeated = false; // _containers
+ bool has_iterable = false; // typing.Iterable
+ bool has_messages = false; // _message
+ bool has_enums = false; // _enum_type_wrapper
+ bool has_extendable = false; // _python_message
+ bool has_mapping = false; // typing.Mapping
+ bool has_optional = false; // typing.Optional
+ bool has_union = false; // typing.Uion
+};
+
+// Checks what modules should be imported for this message
+// descriptor.
+void CheckImportModules(const Descriptor* descriptor,
+ ImportModules* import_modules) {
+ if (descriptor->extension_range_count() > 0) {
+ import_modules->has_extendable = true;
+ }
+ if (descriptor->enum_type_count() > 0) {
+ import_modules->has_enums = true;
+ }
+ for (int i = 0; i < descriptor->field_count(); ++i) {
+ const FieldDescriptor* field = descriptor->field(i);
+ if (IsPythonKeyword(field->name())) {
+ continue;
+ }
+ import_modules->has_optional = true;
+ if (field->is_repeated()) {
+ import_modules->has_repeated = true;
+ }
+ if (field->is_map()) {
+ import_modules->has_mapping = true;
+ const FieldDescriptor* value_des = field->message_type()->field(1);
+ if (value_des->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
+ value_des->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ import_modules->has_union = true;
+ }
+ } else {
+ if (field->is_repeated()) {
+ import_modules->has_iterable = true;
+ }
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ import_modules->has_union = true;
+ import_modules->has_mapping = true;
+ }
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ import_modules->has_union = true;
+ }
+ }
+ }
+ for (int i = 0; i < descriptor->nested_type_count(); ++i) {
+ CheckImportModules(descriptor->nested_type(i), import_modules);
+ }
+}
+
+void PyiGenerator::PrintImports(
+ std::map<TProtoStringType, TProtoStringType>* item_map) const {
+ // Prints imported dependent _pb2 files.
+ for (int i = 0; i < file_->dependency_count(); ++i) {
+ const TProtoStringType& filename = file_->dependency(i)->name();
+ TProtoStringType module_name = StrippedModuleName(filename);
+ size_t last_dot_pos = module_name.rfind('.');
+ TProtoStringType import_statement;
+ if (last_dot_pos == TProtoStringType::npos) {
+ import_statement = "import " + module_name;
+ } else {
+ import_statement = "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);
+ }
+ printer_->Print("$statement$ as _$module_name$\n", "statement",
+ import_statement, "module_name", module_name);
+ }
+
+ // Checks what modules should be imported.
+ ImportModules import_modules;
+ if (file_->message_type_count() > 0) {
+ import_modules.has_messages = true;
+ }
+ if (file_->enum_type_count() > 0) {
+ import_modules.has_enums = true;
+ }
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ CheckImportModules(file_->message_type(i), &import_modules);
+ }
+
+ // Prints modules (e.g. _containers, _messages, typing) that are
+ // required in the proto file.
+ if (import_modules.has_repeated) {
+ printer_->Print(
+ "from google.protobuf.internal import containers as "
+ "_containers\n");
+ }
+ if (import_modules.has_enums) {
+ printer_->Print(
+ "from google.protobuf.internal import enum_type_wrapper"
+ " as _enum_type_wrapper\n");
+ }
+ if (import_modules.has_extendable) {
+ printer_->Print(
+ "from google.protobuf.internal import python_message"
+ " as _python_message\n");
+ }
+ printer_->Print(
+ "from google.protobuf import"
+ " descriptor as _descriptor\n");
+ if (import_modules.has_messages) {
+ printer_->Print(
+ "from google.protobuf import message as _message\n");
+ }
+ if (HasGenericServices(file_)) {
+ printer_->Print(
+ "from google.protobuf import service as"
+ " _service\n");
+ }
+ printer_->Print("from typing import ");
+ printer_->Print("ClassVar");
+ if (import_modules.has_iterable) {
+ printer_->Print(", Iterable");
+ }
+ if (import_modules.has_mapping) {
+ printer_->Print(", Mapping");
+ }
+ if (import_modules.has_optional) {
+ printer_->Print(", Optional");
+ }
+ if (file_->service_count() > 0) {
+ printer_->Print(", Text");
+ }
+ if (import_modules.has_union) {
+ printer_->Print(", Union");
+ }
+ printer_->Print("\n\n");
+
+ // Public imports
+ for (int i = 0; i < file_->public_dependency_count(); ++i) {
+ const FileDescriptor* public_dep = file_->public_dependency(i);
+ TProtoStringType module_name = StrippedModuleName(public_dep->name());
+ // Top level messages in public imports
+ for (int i = 0; i < public_dep->message_type_count(); ++i) {
+ printer_->Print("from $module$ import $message_class$\n", "module",
+ module_name, "message_class",
+ public_dep->message_type(i)->name());
+ }
+ // Top level enums for public imports
+ for (int i = 0; i < public_dep->enum_type_count(); ++i) {
+ printer_->Print("from $module$ import $enum_class$\n", "module",
+ 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);
+ }
+ }
+ // Top level extensions for public imports
+ AddExtensions(*public_dep, item_map);
+ }
+}
+
+void PyiGenerator::PrintEnum(const EnumDescriptor& enum_descriptor) const {
+ TProtoStringType enum_name = enum_descriptor.name();
+ printer_->Print(
+ "class $enum_name$(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):\n"
+ " __slots__ = []\n",
+ "enum_name", enum_name);
+}
+
+// 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 {
+ // enum values
+ 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;
+ }
+}
+
+// Prints top level enums
+void PyiGenerator::PrintTopLevelEnums() const {
+ for (int i = 0; i < file_->enum_type_count(); ++i) {
+ printer_->Print("\n");
+ PrintEnum(*file_->enum_type(i));
+ }
+}
+
+// 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 {
+ 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";
+ }
+}
+
+// Returns the string format of a field's cpp_type
+TProtoStringType PyiGenerator::GetFieldType(const FieldDescriptor& field_des) const {
+ switch (field_des.cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ case FieldDescriptor::CPPTYPE_UINT32:
+ case FieldDescriptor::CPPTYPE_INT64:
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return "int";
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return "float";
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return "bool";
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return ModuleLevelName(*field_des.enum_type());
+ case FieldDescriptor::CPPTYPE_STRING:
+ if (field_des.type() == FieldDescriptor::TYPE_STRING) {
+ return "str";
+ } else {
+ return "bytes";
+ }
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return ModuleLevelName(*field_des.message_type());
+ default:
+ GOOGLE_LOG(FATAL) << "Unsuppoted field type.";
+ }
+ return "";
+}
+
+void PyiGenerator::PrintMessage(const Descriptor& message_descriptor,
+ bool is_nested) const {
+ if (!is_nested) {
+ printer_->Print("\n");
+ }
+ TProtoStringType class_name = message_descriptor.name();
+ printer_->Print("class $class_name$(_message.Message):\n", "class_name",
+ class_name);
+ 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) {
+ if (IsPythonKeyword(field_des->name())) {
+ continue;
+ }
+ if (first_item) {
+ first_item = false;
+ } else {
+ printer_->Print(", ");
+ }
+ printer_->Print("\"$field_name$\"", "field_name", field_des->name());
+ }
+ 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";
+ }
+
+ // 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);
+ }
+
+ // 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));
+ }
+ std::sort(nested_messages.begin(), nested_messages.end(),
+ SortByName<Descriptor>());
+
+ for (const auto& entry : nested_messages) {
+ PrintMessage(*entry, true);
+ }
+
+ // Adds extensions to item_map which will be ordered and printed later
+ AddExtensions(message_descriptor, &item_map);
+
+ // Adds field number and field descriptor to item_map
+ 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;
+ }
+ TProtoStringType field_type = "";
+ 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);
+ field_type += ", ";
+ field_type += GetFieldType(*value_des);
+ } else {
+ if (field_des.is_repeated()) {
+ field_type = (field_des.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
+ ? "_containers.RepeatedCompositeFieldContainer["
+ : "_containers.RepeatedScalarFieldContainer[");
+ }
+ field_type += GetFieldType(field_des);
+ }
+
+ if (field_des.is_repeated()) {
+ field_type += "]";
+ }
+ item_map[field_des.name()] = field_type;
+ }
+
+ // Prints all items in item_map
+ PrintItemMap(item_map);
+
+ // Prints __init__
+ printer_->Print("def __init__(self");
+ bool has_key_words = false;
+ bool is_first = true;
+ for (int i = 0; i < message_descriptor.field_count(); ++i) {
+ const FieldDescriptor* field_des = message_descriptor.field(i);
+ if (IsPythonKeyword(field_des->name())) {
+ has_key_words = true;
+ continue;
+ }
+ TProtoStringType field_name = field_des->name();
+ if (is_first && field_name == "self") {
+ // See b/144146793 for an example of real code that generates a (self,
+ // self) method signature. Since repeating a parameter name is illegal in
+ // Python, we rename the duplicate self.
+ field_name = "self_";
+ }
+ is_first = false;
+ printer_->Print(", $field_name$: ", "field_name", field_name);
+ if (field_des->is_repeated() ||
+ field_des->cpp_type() != FieldDescriptor::CPPTYPE_BOOL) {
+ printer_->Print("Optional[");
+ }
+ if (field_des->is_map()) {
+ const Descriptor* map_entry = field_des->message_type();
+ printer_->Print("Mapping[$key_type$, $value_type$]", "key_type",
+ GetFieldType(*map_entry->field(0)), "value_type",
+ GetFieldType(*map_entry->field(1)));
+ } else {
+ if (field_des->is_repeated()) {
+ printer_->Print("Iterable[");
+ }
+ if (field_des->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ printer_->Print("Union[$type_name$, Mapping]", "type_name",
+ GetFieldType(*field_des));
+ } else {
+ if (field_des->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
+ printer_->Print("Union[$type_name$, str]", "type_name",
+ ModuleLevelName(*field_des->enum_type()));
+ } else {
+ printer_->Print("$type_name$", "type_name", GetFieldType(*field_des));
+ }
+ }
+ if (field_des->is_repeated()) {
+ printer_->Print("]");
+ }
+ }
+ if (field_des->is_repeated() ||
+ field_des->cpp_type() != FieldDescriptor::CPPTYPE_BOOL) {
+ printer_->Print("]");
+ }
+ printer_->Print(" = ...");
+ }
+ if (has_key_words) {
+ printer_->Print(", **kwargs");
+ }
+ printer_->Print(") -> None: ...\n");
+
+ printer_->Outdent();
+ printer_->Outdent();
+}
+
+void PyiGenerator::PrintMessages() const {
+ // Order the descriptors by name to have same output with proto_to_pyi.py
+ 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);
+ }
+}
+
+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) {
+ printer_->Print("\n");
+ printer_->Print(
+ "class $service_name$(_service.service): ...\n\n"
+ "class $service_name$_Stub($service_name$): ...\n",
+ "service_name", entry->name());
+ }
+}
+
+bool PyiGenerator::Generate(const FileDescriptor* file,
+ const TProtoStringType& parameter,
+ GeneratorContext* context,
+ TProtoStringType* error) const {
+ MutexLock lock(&mutex_);
+ // Calculate file name.
+ file_ = file;
+ // proto_to_pyi.py may set the output file name directly. To replace
+ // proto_to_pyi.py in google3, protoc also accept --pyi_out to set
+ // the output file name.
+ TProtoStringType filename =
+ parameter.empty() ? GetFileName(file, ".pyi") : parameter;
+
+ std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+ GOOGLE_CHECK(output.get());
+ io::Printer printer(output.get(), '$');
+ 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(&item_map);
+ // Adds top level enum values to item_map.
+ for (int i = 0; i < file_->enum_type_count(); ++i) {
+ AddEnumValue(*file_->enum_type(i), &item_map);
+ }
+ // Adds top level extensions to item_map.
+ AddExtensions(*file_, &item_map);
+ // Prints item map
+ PrintItemMap(item_map);
+
+ PrintMessages();
+ PrintTopLevelEnums();
+ if (HasGenericServices(file)) {
+ PrintServices();
+ }
+ return true;
+}
+
+} // namespace python
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/python/python_pyi_generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/python/python_pyi_generator.h
new file mode 100644
index 00000000000..d7f5437e491
--- /dev/null
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/python/python_pyi_generator.h
@@ -0,0 +1,104 @@
+// 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.
+
+// Author: [email protected] (Jie Luo)
+//
+// Generates Python stub (.pyi) for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_PYTHON_PYI_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_PYTHON_PYI_GENERATOR_H__
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/stubs/mutex.h>
+
+// Must be included last.
+#include <google/protobuf/port_def.inc>
+
+namespace google {
+namespace protobuf {
+class Descriptor;
+class EnumDescriptor;
+class FieldDescriptor;
+class MethodDescriptor;
+class ServiceDescriptor;
+
+namespace io {
+class Printer;
+}
+
+namespace compiler {
+namespace python {
+
+class PROTOC_EXPORT PyiGenerator : public google::protobuf::compiler::CodeGenerator {
+ public:
+ PyiGenerator();
+ ~PyiGenerator() override;
+
+ // CodeGenerator methods.
+ bool Generate(const FileDescriptor* file, const TProtoStringType& parameter,
+ GeneratorContext* generator_context,
+ TProtoStringType* error) const override;
+
+ private:
+ void PrintImports(std::map<TProtoStringType, TProtoStringType>* item_map) const;
+ void PrintEnum(const EnumDescriptor& enum_descriptor) const;
+ void AddEnumValue(const EnumDescriptor& enum_descriptor,
+ std::map<TProtoStringType, TProtoStringType>* item_map) const;
+ void PrintTopLevelEnums() const;
+ template <typename DescriptorT>
+ void AddExtensions(const DescriptorT& descriptor,
+ std::map<TProtoStringType, TProtoStringType>* item_map) 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;
+ template <typename DescriptorT>
+ TProtoStringType ModuleLevelName(const DescriptorT& descriptor) const;
+
+ // Very coarse-grained lock to ensure that Generate() is reentrant.
+ // Guards file_ and printer_.
+ mutable 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);
+};
+
+} // namespace python
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#include <google/protobuf/port_undef.inc>
+
+#endif // GOOGLE_PROTOBUF_COMPILER_PYTHON_PYI_GENERATOR_H__