1 | // Protocol Buffers - Google's data interchange format |
2 | // Copyright 2008 Google Inc. All rights reserved. |
3 | // https://developers.google.com/protocol-buffers/ |
4 | // |
5 | // Redistribution and use in source and binary forms, with or without |
6 | // modification, are permitted provided that the following conditions are |
7 | // met: |
8 | // |
9 | // * Redistributions of source code must retain the above copyright |
10 | // notice, this list of conditions and the following disclaimer. |
11 | // * Redistributions in binary form must reproduce the above |
12 | // copyright notice, this list of conditions and the following disclaimer |
13 | // in the documentation and/or other materials provided with the |
14 | // distribution. |
15 | // * Neither the name of Google Inc. nor the names of its |
16 | // contributors may be used to endorse or promote products derived from |
17 | // this software without specific prior written permission. |
18 | // |
19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | |
31 | // Author: robinson@google.com (Will Robinson) |
32 | // |
33 | // This module outputs pure-Python protocol message classes that will |
34 | // largely be constructed at runtime via the metaclass in reflection.py. |
35 | // In other words, our job is basically to output a Python equivalent |
36 | // of the C++ *Descriptor objects, and fix up all circular references |
37 | // within these objects. |
38 | // |
39 | // Note that the runtime performance of protocol message classes created in |
40 | // this way is expected to be lousy. The plan is to create an alternate |
41 | // generator that outputs a Python/C extension module that lets |
42 | // performance-minded Python code leverage the fast C++ implementation |
43 | // directly. |
44 | |
45 | #include <google/protobuf/compiler/python/generator.h> |
46 | |
47 | #include <algorithm> |
48 | #include <limits> |
49 | #include <map> |
50 | #include <memory> |
51 | #include <string> |
52 | #include <utility> |
53 | #include <vector> |
54 | |
55 | #include <google/protobuf/stubs/logging.h> |
56 | #include <google/protobuf/stubs/common.h> |
57 | #include <google/protobuf/stubs/strutil.h> |
58 | #include <google/protobuf/stubs/stringprintf.h> |
59 | #include <google/protobuf/stubs/substitute.h> |
60 | #include <google/protobuf/compiler/python/helpers.h> |
61 | #include <google/protobuf/compiler/python/pyi_generator.h> |
62 | #include <google/protobuf/descriptor.h> |
63 | #include <google/protobuf/descriptor.pb.h> |
64 | #include <google/protobuf/io/printer.h> |
65 | #include <google/protobuf/io/zero_copy_stream.h> |
66 | |
67 | namespace google { |
68 | namespace protobuf { |
69 | namespace compiler { |
70 | namespace python { |
71 | |
72 | namespace { |
73 | // Returns the alias we assign to the module of the given .proto filename |
74 | // when importing. See testPackageInitializationImport in |
75 | // net/proto2/python/internal/reflection_test.py |
76 | // to see why we need the alias. |
77 | std::string ModuleAlias(const std::string& filename) { |
78 | std::string module_name = ModuleName(filename); |
79 | // We can't have dots in the module name, so we replace each with _dot_. |
80 | // But that could lead to a collision between a.b and a_dot_b, so we also |
81 | // duplicate each underscore. |
82 | GlobalReplaceSubstring(substring: "_" , replacement: "__" , s: &module_name); |
83 | GlobalReplaceSubstring(substring: "." , replacement: "_dot_" , s: &module_name); |
84 | return module_name; |
85 | } |
86 | |
87 | // Name of the class attribute where we store the Python |
88 | // descriptor.Descriptor instance for the generated class. |
89 | // Must stay consistent with the _DESCRIPTOR_KEY constant |
90 | // in proto2/public/reflection.py. |
91 | const char kDescriptorKey[] = "DESCRIPTOR" ; |
92 | |
93 | |
94 | // file output by this generator. |
95 | void PrintTopBoilerplate(io::Printer* printer, const FileDescriptor* file, |
96 | bool descriptor_proto) { |
97 | // TODO(robinson): Allow parameterization of Python version? |
98 | printer->Print( |
99 | text: "# -*- coding: utf-8 -*-\n" |
100 | "# Generated by the protocol buffer compiler. DO NOT EDIT!\n" |
101 | "# source: $filename$\n" |
102 | "\"\"\"Generated protocol buffer code.\"\"\"\n" , |
103 | args: "filename" , args: file->name()); |
104 | printer->Print( |
105 | text: "from google.protobuf.internal import builder as _builder\n" |
106 | "from google.protobuf import descriptor as _descriptor\n" |
107 | "from google.protobuf import descriptor_pool as " |
108 | "_descriptor_pool\n" |
109 | "from google.protobuf import symbol_database as " |
110 | "_symbol_database\n" ); |
111 | |
112 | printer->Print(text: "# @@protoc_insertion_point(imports)\n\n" ); |
113 | printer->Print(text: "_sym_db = _symbol_database.Default()\n" ); |
114 | printer->Print(text: "\n\n" ); |
115 | } |
116 | |
117 | // Returns a Python literal giving the default value for a field. |
118 | // If the field specifies no explicit default value, we'll return |
119 | // the default default value for the field type (zero for numbers, |
120 | // empty string for strings, empty list for repeated fields, and |
121 | // None for non-repeated, composite fields). |
122 | // |
123 | // TODO(robinson): Unify with code from |
124 | // //compiler/cpp/internal/primitive_field.cc |
125 | // //compiler/cpp/internal/enum_field.cc |
126 | // //compiler/cpp/internal/string_field.cc |
127 | std::string StringifyDefaultValue(const FieldDescriptor& field) { |
128 | if (field.is_repeated()) { |
129 | return "[]" ; |
130 | } |
131 | |
132 | switch (field.cpp_type()) { |
133 | case FieldDescriptor::CPPTYPE_INT32: |
134 | return StrCat(a: field.default_value_int32()); |
135 | case FieldDescriptor::CPPTYPE_UINT32: |
136 | return StrCat(a: field.default_value_uint32()); |
137 | case FieldDescriptor::CPPTYPE_INT64: |
138 | return StrCat(a: field.default_value_int64()); |
139 | case FieldDescriptor::CPPTYPE_UINT64: |
140 | return StrCat(a: field.default_value_uint64()); |
141 | case FieldDescriptor::CPPTYPE_DOUBLE: { |
142 | double value = field.default_value_double(); |
143 | if (value == std::numeric_limits<double>::infinity()) { |
144 | // Python pre-2.6 on Windows does not parse "inf" correctly. However, |
145 | // a numeric literal that is too big for a double will become infinity. |
146 | return "1e10000" ; |
147 | } else if (value == -std::numeric_limits<double>::infinity()) { |
148 | // See above. |
149 | return "-1e10000" ; |
150 | } else if (value != value) { |
151 | // infinity * 0 = nan |
152 | return "(1e10000 * 0)" ; |
153 | } else { |
154 | return "float(" + SimpleDtoa(value) + ")" ; |
155 | } |
156 | } |
157 | case FieldDescriptor::CPPTYPE_FLOAT: { |
158 | float value = field.default_value_float(); |
159 | if (value == std::numeric_limits<float>::infinity()) { |
160 | // Python pre-2.6 on Windows does not parse "inf" correctly. However, |
161 | // a numeric literal that is too big for a double will become infinity. |
162 | return "1e10000" ; |
163 | } else if (value == -std::numeric_limits<float>::infinity()) { |
164 | // See above. |
165 | return "-1e10000" ; |
166 | } else if (value != value) { |
167 | // infinity - infinity = nan |
168 | return "(1e10000 * 0)" ; |
169 | } else { |
170 | return "float(" + SimpleFtoa(value) + ")" ; |
171 | } |
172 | } |
173 | case FieldDescriptor::CPPTYPE_BOOL: |
174 | return field.default_value_bool() ? "True" : "False" ; |
175 | case FieldDescriptor::CPPTYPE_ENUM: |
176 | return StrCat(a: field.default_value_enum()->number()); |
177 | case FieldDescriptor::CPPTYPE_STRING: |
178 | return "b\"" + CEscape(src: field.default_value_string()) + |
179 | (field.type() != FieldDescriptor::TYPE_STRING |
180 | ? "\"" |
181 | : "\".decode('utf-8')" ); |
182 | case FieldDescriptor::CPPTYPE_MESSAGE: |
183 | return "None" ; |
184 | } |
185 | // (We could add a default case above but then we wouldn't get the nice |
186 | // compiler warning when a new type is added.) |
187 | GOOGLE_LOG(FATAL) << "Not reached." ; |
188 | return "" ; |
189 | } |
190 | |
191 | std::string StringifySyntax(FileDescriptor::Syntax syntax) { |
192 | switch (syntax) { |
193 | case FileDescriptor::SYNTAX_PROTO2: |
194 | return "proto2" ; |
195 | case FileDescriptor::SYNTAX_PROTO3: |
196 | return "proto3" ; |
197 | case FileDescriptor::SYNTAX_UNKNOWN: |
198 | default: |
199 | GOOGLE_LOG(FATAL) << "Unsupported syntax; this generator only supports proto2 " |
200 | "and proto3 syntax." ; |
201 | return "" ; |
202 | } |
203 | } |
204 | |
205 | } // namespace |
206 | |
207 | Generator::Generator() : file_(nullptr) {} |
208 | |
209 | Generator::~Generator() {} |
210 | |
211 | uint64_t Generator::GetSupportedFeatures() const { |
212 | return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL; |
213 | } |
214 | |
215 | bool Generator::Generate(const FileDescriptor* file, |
216 | const std::string& parameter, |
217 | GeneratorContext* context, std::string* error) const { |
218 | // ----------------------------------------------------------------- |
219 | // parse generator options |
220 | bool cpp_generated_lib_linked = false; |
221 | |
222 | std::vector<std::pair<std::string, std::string> > options; |
223 | ParseGeneratorParameter(parameter, &options); |
224 | |
225 | for (int i = 0; i < options.size(); i++) { |
226 | if (options[i].first == "cpp_generated_lib_linked" ) { |
227 | cpp_generated_lib_linked = true; |
228 | } else if (options[i].first == "pyi_out" ) { |
229 | python::PyiGenerator pyi_generator; |
230 | if (!pyi_generator.Generate(file, parameter: "" , generator_context: context, error)) { |
231 | return false; |
232 | } |
233 | } else { |
234 | *error = "Unknown generator option: " + options[i].first; |
235 | return false; |
236 | } |
237 | } |
238 | |
239 | // Completely serialize all Generate() calls on this instance. The |
240 | // thread-safety constraints of the CodeGenerator interface aren't clear so |
241 | // just be as conservative as possible. It's easier to relax this later if |
242 | // we need to, but I doubt it will be an issue. |
243 | // TODO(kenton): The proper thing to do would be to allocate any state on |
244 | // the stack and use that, so that the Generator class itself does not need |
245 | // to have any mutable members. Then it is implicitly thread-safe. |
246 | MutexLock lock(&mutex_); |
247 | file_ = file; |
248 | |
249 | std::string filename = GetFileName(file_des: file, suffix: ".py" ); |
250 | pure_python_workable_ = !cpp_generated_lib_linked; |
251 | if (HasPrefixString(str: file->name(), prefix: "google/protobuf/" )) { |
252 | pure_python_workable_ = true; |
253 | } |
254 | |
255 | FileDescriptorProto fdp; |
256 | file_->CopyTo(proto: &fdp); |
257 | fdp.SerializeToString(output: &file_descriptor_serialized_); |
258 | |
259 | |
260 | std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename)); |
261 | GOOGLE_CHECK(output.get()); |
262 | io::Printer printer(output.get(), '$'); |
263 | printer_ = &printer; |
264 | |
265 | PrintTopBoilerplate(printer: printer_, file: file_, descriptor_proto: GeneratingDescriptorProto()); |
266 | if (pure_python_workable_) { |
267 | PrintImports(); |
268 | } |
269 | PrintFileDescriptor(); |
270 | if (pure_python_workable_) { |
271 | if (GeneratingDescriptorProto()) { |
272 | printer_->Print(text: "if _descriptor._USE_C_DESCRIPTORS == False:\n" ); |
273 | printer_->Indent(); |
274 | // Create enums before message descriptors |
275 | PrintAllNestedEnumsInFile(); |
276 | PrintMessageDescriptors(); |
277 | FixForeignFieldsInDescriptors(); |
278 | printer_->Outdent(); |
279 | printer_->Print(text: "else:\n" ); |
280 | printer_->Indent(); |
281 | } |
282 | // Find the message descriptors first and then use the message |
283 | // descriptor to find enums. |
284 | printer_->Print( |
285 | text: "_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())\n" ); |
286 | if (GeneratingDescriptorProto()) { |
287 | printer_->Outdent(); |
288 | } |
289 | } |
290 | std::string module_name = ModuleName(filename: file->name()); |
291 | printer_->Print( |
292 | text: "_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, '$module_name$', " |
293 | "globals())\n" , |
294 | args: "module_name" , args: module_name); |
295 | if (pure_python_workable_) { |
296 | printer.Print(text: "if _descriptor._USE_C_DESCRIPTORS == False:\n" ); |
297 | printer_->Indent(); |
298 | |
299 | // We have to fix up the extensions after the message classes themselves, |
300 | // since they need to call static RegisterExtension() methods on these |
301 | // classes. |
302 | FixForeignFieldsInExtensions(); |
303 | // Descriptor options may have custom extensions. These custom options |
304 | // can only be successfully parsed after we register corresponding |
305 | // extensions. Therefore we parse all options again here to recognize |
306 | // custom options that may be unknown when we define the descriptors. |
307 | // This does not apply to services because they are not used by extensions. |
308 | FixAllDescriptorOptions(); |
309 | |
310 | // Set serialized_start and serialized_end. |
311 | SetSerializedPbInterval(); |
312 | |
313 | printer_->Outdent(); |
314 | } |
315 | if (HasGenericServices(file)) { |
316 | printer_->Print( |
317 | text: "_builder.BuildServices(DESCRIPTOR, '$module_name$', globals())\n" , |
318 | args: "module_name" , args: module_name); |
319 | } |
320 | |
321 | printer.Print(text: "# @@protoc_insertion_point(module_scope)\n" ); |
322 | |
323 | return !printer.failed(); |
324 | } |
325 | |
326 | // Prints Python imports for all modules imported by |file|. |
327 | void Generator::PrintImports() const { |
328 | for (int i = 0; i < file_->dependency_count(); ++i) { |
329 | const std::string& filename = file_->dependency(index: i)->name(); |
330 | |
331 | std::string module_name = ModuleName(filename); |
332 | std::string module_alias = ModuleAlias(filename); |
333 | if (ContainsPythonKeyword(module_name)) { |
334 | // If the module path contains a Python keyword, we have to quote the |
335 | // module name and import it using importlib. Otherwise the usual kind of |
336 | // import statement would result in a syntax error from the presence of |
337 | // the keyword. |
338 | printer_->Print(text: "import importlib\n" ); |
339 | printer_->Print(text: "$alias$ = importlib.import_module('$name$')\n" , args: "alias" , |
340 | args: module_alias, args: "name" , args: module_name); |
341 | } else { |
342 | int last_dot_pos = module_name.rfind(c: '.'); |
343 | std::string import_statement; |
344 | if (last_dot_pos == std::string::npos) { |
345 | // NOTE(petya): this is not tested as it would require a protocol buffer |
346 | // outside of any package, and I don't think that is easily achievable. |
347 | import_statement = "import " + module_name; |
348 | } else { |
349 | import_statement = "from " + module_name.substr(pos: 0, n: last_dot_pos) + |
350 | " import " + module_name.substr(pos: last_dot_pos + 1); |
351 | } |
352 | printer_->Print(text: "$statement$ as $alias$\n" , args: "statement" , args: import_statement, |
353 | args: "alias" , args: module_alias); |
354 | } |
355 | |
356 | CopyPublicDependenciesAliases(copy_from: module_alias, file: file_->dependency(index: i)); |
357 | } |
358 | printer_->Print(text: "\n" ); |
359 | |
360 | // Print public imports. |
361 | for (int i = 0; i < file_->public_dependency_count(); ++i) { |
362 | std::string module_name = ModuleName(filename: file_->public_dependency(index: i)->name()); |
363 | printer_->Print(text: "from $module$ import *\n" , args: "module" , args: module_name); |
364 | } |
365 | printer_->Print(text: "\n" ); |
366 | } |
367 | |
368 | // Prints the single file descriptor for this file. |
369 | void Generator::PrintFileDescriptor() const { |
370 | std::map<std::string, std::string> m; |
371 | m["descriptor_name" ] = kDescriptorKey; |
372 | m["name" ] = file_->name(); |
373 | m["package" ] = file_->package(); |
374 | m["syntax" ] = StringifySyntax(syntax: file_->syntax()); |
375 | m["options" ] = OptionsValue(serialized_options: file_->options().SerializeAsString()); |
376 | m["serialized_descriptor" ] = strings::CHexEscape(src: file_descriptor_serialized_); |
377 | if (GeneratingDescriptorProto()) { |
378 | printer_->Print(text: "if _descriptor._USE_C_DESCRIPTORS == False:\n" ); |
379 | printer_->Indent(); |
380 | // Pure python's AddSerializedFile() depend on the generated |
381 | // descriptor_pb2.py thus we can not use AddSerializedFile() when |
382 | // generated descriptor.proto for pure python. |
383 | const char file_descriptor_template[] = |
384 | "$descriptor_name$ = _descriptor.FileDescriptor(\n" |
385 | " name='$name$',\n" |
386 | " package='$package$',\n" |
387 | " syntax='$syntax$',\n" |
388 | " serialized_options=$options$,\n" |
389 | " create_key=_descriptor._internal_create_key,\n" ; |
390 | printer_->Print(variables: m, text: file_descriptor_template); |
391 | printer_->Indent(); |
392 | if (pure_python_workable_) { |
393 | printer_->Print(text: "serialized_pb=b'$value$'\n" , args: "value" , |
394 | args: strings::CHexEscape(src: file_descriptor_serialized_)); |
395 | if (file_->dependency_count() != 0) { |
396 | printer_->Print(text: ",\ndependencies=[" ); |
397 | for (int i = 0; i < file_->dependency_count(); ++i) { |
398 | std::string module_alias = ModuleAlias(filename: file_->dependency(index: i)->name()); |
399 | printer_->Print(text: "$module_alias$.DESCRIPTOR," , args: "module_alias" , |
400 | args: module_alias); |
401 | } |
402 | printer_->Print(text: "]" ); |
403 | } |
404 | if (file_->public_dependency_count() > 0) { |
405 | printer_->Print(text: ",\npublic_dependencies=[" ); |
406 | for (int i = 0; i < file_->public_dependency_count(); ++i) { |
407 | std::string module_alias = |
408 | ModuleAlias(filename: file_->public_dependency(index: i)->name()); |
409 | printer_->Print(text: "$module_alias$.DESCRIPTOR," , args: "module_alias" , |
410 | args: module_alias); |
411 | } |
412 | printer_->Print(text: "]" ); |
413 | } |
414 | } else { |
415 | printer_->Print(text: "serialized_pb=''\n" ); |
416 | } |
417 | |
418 | // TODO(falk): Also print options and fix the message_type, enum_type, |
419 | // service and extension later in the generation. |
420 | |
421 | printer_->Outdent(); |
422 | printer_->Print(text: ")\n" ); |
423 | |
424 | printer_->Outdent(); |
425 | printer_->Print(text: "else:\n" ); |
426 | printer_->Indent(); |
427 | } |
428 | printer_->Print(variables: m, |
429 | text: "$descriptor_name$ = " |
430 | "_descriptor_pool.Default().AddSerializedFile(b'$serialized_" |
431 | "descriptor$')\n" ); |
432 | if (GeneratingDescriptorProto()) { |
433 | printer_->Outdent(); |
434 | } |
435 | printer_->Print(text: "\n" ); |
436 | } |
437 | |
438 | // Prints all enums contained in all message types in |file|. |
439 | void Generator::PrintAllNestedEnumsInFile() const { |
440 | for (int i = 0; i < file_->message_type_count(); ++i) { |
441 | PrintNestedEnums(descriptor: *file_->message_type(index: i)); |
442 | } |
443 | } |
444 | |
445 | // Prints a Python statement assigning the appropriate module-level |
446 | // enum name to a Python EnumDescriptor object equivalent to |
447 | // enum_descriptor. |
448 | void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { |
449 | std::map<std::string, std::string> m; |
450 | std::string module_level_descriptor_name = |
451 | ModuleLevelDescriptorName(descriptor: enum_descriptor); |
452 | m["descriptor_name" ] = module_level_descriptor_name; |
453 | m["name" ] = enum_descriptor.name(); |
454 | m["full_name" ] = enum_descriptor.full_name(); |
455 | m["file" ] = kDescriptorKey; |
456 | const char enum_descriptor_template[] = |
457 | "$descriptor_name$ = _descriptor.EnumDescriptor(\n" |
458 | " name='$name$',\n" |
459 | " full_name='$full_name$',\n" |
460 | " filename=None,\n" |
461 | " file=$file$,\n" |
462 | " create_key=_descriptor._internal_create_key,\n" |
463 | " values=[\n" ; |
464 | std::string options_string; |
465 | enum_descriptor.options().SerializeToString(output: &options_string); |
466 | printer_->Print(variables: m, text: enum_descriptor_template); |
467 | printer_->Indent(); |
468 | printer_->Indent(); |
469 | |
470 | if (pure_python_workable_) { |
471 | for (int i = 0; i < enum_descriptor.value_count(); ++i) { |
472 | PrintEnumValueDescriptor(descriptor: *enum_descriptor.value(index: i)); |
473 | printer_->Print(text: ",\n" ); |
474 | } |
475 | } |
476 | |
477 | printer_->Outdent(); |
478 | printer_->Print(text: "],\n" ); |
479 | printer_->Print(text: "containing_type=None,\n" ); |
480 | printer_->Print(text: "serialized_options=$options_value$,\n" , args: "options_value" , |
481 | args: OptionsValue(serialized_options: options_string)); |
482 | EnumDescriptorProto edp; |
483 | printer_->Outdent(); |
484 | printer_->Print(text: ")\n" ); |
485 | if (pure_python_workable_) { |
486 | printer_->Print(text: "_sym_db.RegisterEnumDescriptor($name$)\n" , args: "name" , |
487 | args: module_level_descriptor_name); |
488 | } |
489 | printer_->Print(text: "\n" ); |
490 | } |
491 | |
492 | // Recursively prints enums in nested types within descriptor, then |
493 | // prints enums contained at the top level in descriptor. |
494 | void Generator::PrintNestedEnums(const Descriptor& descriptor) const { |
495 | for (int i = 0; i < descriptor.nested_type_count(); ++i) { |
496 | PrintNestedEnums(descriptor: *descriptor.nested_type(index: i)); |
497 | } |
498 | |
499 | for (int i = 0; i < descriptor.enum_type_count(); ++i) { |
500 | PrintEnum(enum_descriptor: *descriptor.enum_type(index: i)); |
501 | } |
502 | } |
503 | |
504 | // Prints Python equivalents of all Descriptors in |file|. |
505 | void Generator::PrintMessageDescriptors() const { |
506 | for (int i = 0; i < file_->message_type_count(); ++i) { |
507 | PrintDescriptor(message_descriptor: *file_->message_type(index: i)); |
508 | printer_->Print(text: "\n" ); |
509 | } |
510 | } |
511 | |
512 | void Generator::PrintServiceDescriptors() const { |
513 | for (int i = 0; i < file_->service_count(); ++i) { |
514 | PrintServiceDescriptor(descriptor: *file_->service(index: i)); |
515 | } |
516 | } |
517 | |
518 | void Generator::PrintServices() const { |
519 | for (int i = 0; i < file_->service_count(); ++i) { |
520 | PrintServiceClass(descriptor: *file_->service(index: i)); |
521 | PrintServiceStub(descriptor: *file_->service(index: i)); |
522 | printer_->Print(text: "\n" ); |
523 | } |
524 | } |
525 | |
526 | void Generator::PrintServiceDescriptor( |
527 | const ServiceDescriptor& descriptor) const { |
528 | std::map<std::string, std::string> m; |
529 | m["service_name" ] = ModuleLevelServiceDescriptorName(descriptor); |
530 | m["name" ] = descriptor.name(); |
531 | m["file" ] = kDescriptorKey; |
532 | printer_->Print(variables: m, text: "$service_name$ = $file$.services_by_name['$name$']\n" ); |
533 | } |
534 | |
535 | void Generator::PrintDescriptorKeyAndModuleName( |
536 | const ServiceDescriptor& descriptor) const { |
537 | std::string name = ModuleLevelServiceDescriptorName(descriptor); |
538 | if (!pure_python_workable_) { |
539 | name = "_descriptor.ServiceDescriptor(full_name='" + |
540 | descriptor.full_name() + "')" ; |
541 | } |
542 | printer_->Print(text: "$descriptor_key$ = $descriptor_name$,\n" , args: "descriptor_key" , |
543 | args: kDescriptorKey, args: "descriptor_name" , args: name); |
544 | std::string module_name = ModuleName(filename: file_->name()); |
545 | printer_->Print(text: "__module__ = '$module_name$'\n" , args: "module_name" , args: module_name); |
546 | } |
547 | |
548 | void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const { |
549 | // Print the service. |
550 | printer_->Print( |
551 | text: "$class_name$ = service_reflection.GeneratedServiceType(" |
552 | "'$class_name$', (_service.Service,), dict(\n" , |
553 | args: "class_name" , args: descriptor.name()); |
554 | printer_->Indent(); |
555 | Generator::PrintDescriptorKeyAndModuleName(descriptor); |
556 | printer_->Print(text: "))\n\n" ); |
557 | printer_->Outdent(); |
558 | } |
559 | |
560 | void Generator::PrintServiceStub(const ServiceDescriptor& descriptor) const { |
561 | // Print the service stub. |
562 | printer_->Print( |
563 | text: "$class_name$_Stub = " |
564 | "service_reflection.GeneratedServiceStubType(" |
565 | "'$class_name$_Stub', ($class_name$,), dict(\n" , |
566 | args: "class_name" , args: descriptor.name()); |
567 | printer_->Indent(); |
568 | Generator::PrintDescriptorKeyAndModuleName(descriptor); |
569 | printer_->Print(text: "))\n\n" ); |
570 | printer_->Outdent(); |
571 | } |
572 | |
573 | // Prints statement assigning ModuleLevelDescriptorName(message_descriptor) |
574 | // to a Python Descriptor object for message_descriptor. |
575 | // |
576 | // Mutually recursive with PrintNestedDescriptors(). |
577 | void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { |
578 | std::map<std::string, std::string> m; |
579 | m["name" ] = message_descriptor.name(); |
580 | m["full_name" ] = message_descriptor.full_name(); |
581 | m["file" ] = kDescriptorKey; |
582 | |
583 | PrintNestedDescriptors(containing_descriptor: message_descriptor); |
584 | |
585 | printer_->Print(text: "\n" ); |
586 | printer_->Print(text: "$descriptor_name$ = _descriptor.Descriptor(\n" , |
587 | args: "descriptor_name" , |
588 | args: ModuleLevelDescriptorName(descriptor: message_descriptor)); |
589 | printer_->Indent(); |
590 | const char required_function_arguments[] = |
591 | "name='$name$',\n" |
592 | "full_name='$full_name$',\n" |
593 | "filename=None,\n" |
594 | "file=$file$,\n" |
595 | "containing_type=None,\n" |
596 | "create_key=_descriptor._internal_create_key,\n" ; |
597 | printer_->Print(variables: m, text: required_function_arguments); |
598 | PrintFieldsInDescriptor(message_descriptor); |
599 | PrintExtensionsInDescriptor(message_descriptor); |
600 | |
601 | // Nested types |
602 | printer_->Print(text: "nested_types=[" ); |
603 | for (int i = 0; i < message_descriptor.nested_type_count(); ++i) { |
604 | const std::string nested_name = |
605 | ModuleLevelDescriptorName(descriptor: *message_descriptor.nested_type(index: i)); |
606 | printer_->Print(text: "$name$, " , args: "name" , args: nested_name); |
607 | } |
608 | printer_->Print(text: "],\n" ); |
609 | |
610 | // Enum types |
611 | printer_->Print(text: "enum_types=[\n" ); |
612 | printer_->Indent(); |
613 | for (int i = 0; i < message_descriptor.enum_type_count(); ++i) { |
614 | const std::string descriptor_name = |
615 | ModuleLevelDescriptorName(descriptor: *message_descriptor.enum_type(index: i)); |
616 | printer_->Print(text: descriptor_name.c_str()); |
617 | printer_->Print(text: ",\n" ); |
618 | } |
619 | printer_->Outdent(); |
620 | printer_->Print(text: "],\n" ); |
621 | std::string options_string; |
622 | message_descriptor.options().SerializeToString(output: &options_string); |
623 | printer_->Print( |
624 | text: "serialized_options=$options_value$,\n" |
625 | "is_extendable=$extendable$,\n" |
626 | "syntax='$syntax$'" , |
627 | args: "options_value" , args: OptionsValue(serialized_options: options_string), args: "extendable" , |
628 | args: message_descriptor.extension_range_count() > 0 ? "True" : "False" , |
629 | args: "syntax" , args: StringifySyntax(syntax: message_descriptor.file()->syntax())); |
630 | printer_->Print(text: ",\n" ); |
631 | |
632 | // Extension ranges |
633 | printer_->Print(text: "extension_ranges=[" ); |
634 | for (int i = 0; i < message_descriptor.extension_range_count(); ++i) { |
635 | const Descriptor::ExtensionRange* range = |
636 | message_descriptor.extension_range(index: i); |
637 | printer_->Print(text: "($start$, $end$), " , args: "start" , args: StrCat(a: range->start), |
638 | args: "end" , args: StrCat(a: range->end)); |
639 | } |
640 | printer_->Print(text: "],\n" ); |
641 | printer_->Print(text: "oneofs=[\n" ); |
642 | printer_->Indent(); |
643 | for (int i = 0; i < message_descriptor.oneof_decl_count(); ++i) { |
644 | const OneofDescriptor* desc = message_descriptor.oneof_decl(index: i); |
645 | m.clear(); |
646 | m["name" ] = desc->name(); |
647 | m["full_name" ] = desc->full_name(); |
648 | m["index" ] = StrCat(a: desc->index()); |
649 | options_string = OptionsValue(serialized_options: desc->options().SerializeAsString()); |
650 | if (options_string == "None" ) { |
651 | m["serialized_options" ] = "" ; |
652 | } else { |
653 | m["serialized_options" ] = ", serialized_options=" + options_string; |
654 | } |
655 | printer_->Print(variables: m, |
656 | text: "_descriptor.OneofDescriptor(\n" |
657 | " name='$name$', full_name='$full_name$',\n" |
658 | " index=$index$, containing_type=None,\n" |
659 | " create_key=_descriptor._internal_create_key,\n" |
660 | "fields=[]$serialized_options$),\n" ); |
661 | } |
662 | printer_->Outdent(); |
663 | printer_->Print(text: "],\n" ); |
664 | |
665 | printer_->Outdent(); |
666 | printer_->Print(text: ")\n" ); |
667 | } |
668 | |
669 | // Prints Python Descriptor objects for all nested types contained in |
670 | // message_descriptor. |
671 | // |
672 | // Mutually recursive with PrintDescriptor(). |
673 | void Generator::PrintNestedDescriptors( |
674 | const Descriptor& containing_descriptor) const { |
675 | for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) { |
676 | PrintDescriptor(message_descriptor: *containing_descriptor.nested_type(index: i)); |
677 | } |
678 | } |
679 | |
680 | // Prints all messages in |file|. |
681 | void Generator::PrintMessages() const { |
682 | for (int i = 0; i < file_->message_type_count(); ++i) { |
683 | std::vector<std::string> to_register; |
684 | PrintMessage(message_descriptor: *file_->message_type(index: i), prefix: "" , to_register: &to_register, is_nested: false); |
685 | for (int j = 0; j < to_register.size(); ++j) { |
686 | printer_->Print(text: "_sym_db.RegisterMessage($name$)\n" , args: "name" , |
687 | args: ResolveKeyword(name: to_register[j])); |
688 | } |
689 | printer_->Print(text: "\n" ); |
690 | } |
691 | } |
692 | |
693 | // Prints a Python class for the given message descriptor. We defer to the |
694 | // metaclass to do almost all of the work of actually creating a useful class. |
695 | // The purpose of this function and its many helper functions above is merely |
696 | // to output a Python version of the descriptors, which the metaclass in |
697 | // reflection.py will use to construct the meat of the class itself. |
698 | // |
699 | // Mutually recursive with PrintNestedMessages(). |
700 | // Collect nested message names to_register for the symbol_database. |
701 | void Generator::PrintMessage(const Descriptor& message_descriptor, |
702 | const std::string& prefix, |
703 | std::vector<std::string>* to_register, |
704 | bool is_nested) const { |
705 | std::string qualified_name; |
706 | if (is_nested) { |
707 | if (IsPythonKeyword(name: message_descriptor.name())) { |
708 | qualified_name = |
709 | "getattr(" + prefix + ", '" + message_descriptor.name() + "')" ; |
710 | } else { |
711 | qualified_name = prefix + "." + message_descriptor.name(); |
712 | } |
713 | printer_->Print( |
714 | text: "'$name$' : _reflection.GeneratedProtocolMessageType('$name$', " |
715 | "(_message.Message,), {\n" , |
716 | args: "name" , args: message_descriptor.name()); |
717 | } else { |
718 | qualified_name = ResolveKeyword(name: message_descriptor.name()); |
719 | printer_->Print( |
720 | text: "$qualified_name$ = _reflection.GeneratedProtocolMessageType('$name$', " |
721 | "(_message.Message,), {\n" , |
722 | args: "qualified_name" , args: qualified_name, args: "name" , args: message_descriptor.name()); |
723 | } |
724 | printer_->Indent(); |
725 | |
726 | to_register->push_back(x: qualified_name); |
727 | |
728 | PrintNestedMessages(containing_descriptor: message_descriptor, prefix: qualified_name, to_register); |
729 | std::map<std::string, std::string> m; |
730 | m["descriptor_key" ] = kDescriptorKey; |
731 | if (pure_python_workable_) { |
732 | m["descriptor_name" ] = ModuleLevelDescriptorName(descriptor: message_descriptor); |
733 | } else { |
734 | m["descriptor_name" ] = "_descriptor.Descriptor(full_name='" + |
735 | message_descriptor.full_name() + "')" ; |
736 | } |
737 | printer_->Print(variables: m, text: "'$descriptor_key$' : $descriptor_name$,\n" ); |
738 | std::string module_name = ModuleName(filename: file_->name()); |
739 | printer_->Print(text: "'__module__' : '$module_name$'\n" , args: "module_name" , |
740 | args: module_name); |
741 | printer_->Print(text: "# @@protoc_insertion_point(class_scope:$full_name$)\n" , |
742 | args: "full_name" , args: message_descriptor.full_name()); |
743 | printer_->Print(text: "})\n" ); |
744 | printer_->Outdent(); |
745 | } |
746 | |
747 | // Prints all nested messages within |containing_descriptor|. |
748 | // Mutually recursive with PrintMessage(). |
749 | void Generator::PrintNestedMessages( |
750 | const Descriptor& containing_descriptor, const std::string& prefix, |
751 | std::vector<std::string>* to_register) const { |
752 | for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) { |
753 | printer_->Print(text: "\n" ); |
754 | PrintMessage(message_descriptor: *containing_descriptor.nested_type(index: i), prefix, to_register, |
755 | is_nested: true); |
756 | printer_->Print(text: ",\n" ); |
757 | } |
758 | } |
759 | |
760 | // Recursively fixes foreign fields in all nested types in |descriptor|, then |
761 | // sets the message_type and enum_type of all message and enum fields to point |
762 | // to their respective descriptors. |
763 | // Args: |
764 | // descriptor: descriptor to print fields for. |
765 | // containing_descriptor: if descriptor is a nested type, this is its |
766 | // containing type, or NULL if this is a root/top-level type. |
767 | void Generator::FixForeignFieldsInDescriptor( |
768 | const Descriptor& descriptor, |
769 | const Descriptor* containing_descriptor) const { |
770 | for (int i = 0; i < descriptor.nested_type_count(); ++i) { |
771 | FixForeignFieldsInDescriptor(descriptor: *descriptor.nested_type(index: i), containing_descriptor: &descriptor); |
772 | } |
773 | |
774 | for (int i = 0; i < descriptor.field_count(); ++i) { |
775 | const FieldDescriptor& field_descriptor = *descriptor.field(index: i); |
776 | FixForeignFieldsInField(containing_type: &descriptor, field: field_descriptor, python_dict_name: "fields_by_name" ); |
777 | } |
778 | |
779 | FixContainingTypeInDescriptor(descriptor, containing_descriptor); |
780 | for (int i = 0; i < descriptor.enum_type_count(); ++i) { |
781 | const EnumDescriptor& enum_descriptor = *descriptor.enum_type(index: i); |
782 | FixContainingTypeInDescriptor(descriptor: enum_descriptor, containing_descriptor: &descriptor); |
783 | } |
784 | for (int i = 0; i < descriptor.oneof_decl_count(); ++i) { |
785 | std::map<std::string, std::string> m; |
786 | const OneofDescriptor* oneof = descriptor.oneof_decl(index: i); |
787 | m["descriptor_name" ] = ModuleLevelDescriptorName(descriptor); |
788 | m["oneof_name" ] = oneof->name(); |
789 | for (int j = 0; j < oneof->field_count(); ++j) { |
790 | m["field_name" ] = oneof->field(index: j)->name(); |
791 | printer_->Print( |
792 | variables: m, |
793 | text: "$descriptor_name$.oneofs_by_name['$oneof_name$'].fields.append(\n" |
794 | " $descriptor_name$.fields_by_name['$field_name$'])\n" ); |
795 | printer_->Print( |
796 | variables: m, |
797 | text: "$descriptor_name$.fields_by_name['$field_name$'].containing_oneof = " |
798 | "$descriptor_name$.oneofs_by_name['$oneof_name$']\n" ); |
799 | } |
800 | } |
801 | } |
802 | |
803 | void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const { |
804 | std::map<std::string, std::string> m; |
805 | m["descriptor_name" ] = kDescriptorKey; |
806 | m["message_name" ] = descriptor.name(); |
807 | m["message_descriptor_name" ] = ModuleLevelDescriptorName(descriptor); |
808 | const char file_descriptor_template[] = |
809 | "$descriptor_name$.message_types_by_name['$message_name$'] = " |
810 | "$message_descriptor_name$\n" ; |
811 | printer_->Print(variables: m, text: file_descriptor_template); |
812 | } |
813 | |
814 | void Generator::AddServiceToFileDescriptor( |
815 | const ServiceDescriptor& descriptor) const { |
816 | std::map<std::string, std::string> m; |
817 | m["descriptor_name" ] = kDescriptorKey; |
818 | m["service_name" ] = descriptor.name(); |
819 | m["service_descriptor_name" ] = ModuleLevelServiceDescriptorName(descriptor); |
820 | const char file_descriptor_template[] = |
821 | "$descriptor_name$.services_by_name['$service_name$'] = " |
822 | "$service_descriptor_name$\n" ; |
823 | printer_->Print(variables: m, text: file_descriptor_template); |
824 | } |
825 | |
826 | void Generator::AddEnumToFileDescriptor( |
827 | const EnumDescriptor& descriptor) const { |
828 | std::map<std::string, std::string> m; |
829 | m["descriptor_name" ] = kDescriptorKey; |
830 | m["enum_name" ] = descriptor.name(); |
831 | m["enum_descriptor_name" ] = ModuleLevelDescriptorName(descriptor); |
832 | const char file_descriptor_template[] = |
833 | "$descriptor_name$.enum_types_by_name['$enum_name$'] = " |
834 | "$enum_descriptor_name$\n" ; |
835 | printer_->Print(variables: m, text: file_descriptor_template); |
836 | } |
837 | |
838 | void Generator::AddExtensionToFileDescriptor( |
839 | const FieldDescriptor& descriptor) const { |
840 | std::map<std::string, std::string> m; |
841 | m["descriptor_name" ] = kDescriptorKey; |
842 | m["field_name" ] = descriptor.name(); |
843 | m["resolved_name" ] = ResolveKeyword(name: descriptor.name()); |
844 | const char file_descriptor_template[] = |
845 | "$descriptor_name$.extensions_by_name['$field_name$'] = " |
846 | "$resolved_name$\n" ; |
847 | printer_->Print(variables: m, text: file_descriptor_template); |
848 | } |
849 | |
850 | // Sets any necessary message_type and enum_type attributes |
851 | // for the Python version of |field|. |
852 | // |
853 | // containing_type may be NULL, in which case this is a module-level field. |
854 | // |
855 | // python_dict_name is the name of the Python dict where we should |
856 | // look the field up in the containing type. (e.g., fields_by_name |
857 | // or extensions_by_name). We ignore python_dict_name if containing_type |
858 | // is NULL. |
859 | void Generator::FixForeignFieldsInField( |
860 | const Descriptor* containing_type, const FieldDescriptor& field, |
861 | const std::string& python_dict_name) const { |
862 | const std::string field_referencing_expression = |
863 | FieldReferencingExpression(containing_type, field, python_dict_name); |
864 | std::map<std::string, std::string> m; |
865 | m["field_ref" ] = field_referencing_expression; |
866 | const Descriptor* foreign_message_type = field.message_type(); |
867 | if (foreign_message_type) { |
868 | m["foreign_type" ] = ModuleLevelDescriptorName(descriptor: *foreign_message_type); |
869 | printer_->Print(variables: m, text: "$field_ref$.message_type = $foreign_type$\n" ); |
870 | } |
871 | const EnumDescriptor* enum_type = field.enum_type(); |
872 | if (enum_type) { |
873 | m["enum_type" ] = ModuleLevelDescriptorName(descriptor: *enum_type); |
874 | printer_->Print(variables: m, text: "$field_ref$.enum_type = $enum_type$\n" ); |
875 | } |
876 | } |
877 | |
878 | // Returns the module-level expression for the given FieldDescriptor. |
879 | // Only works for fields in the .proto file this Generator is generating for. |
880 | // |
881 | // containing_type may be NULL, in which case this is a module-level field. |
882 | // |
883 | // python_dict_name is the name of the Python dict where we should |
884 | // look the field up in the containing type. (e.g., fields_by_name |
885 | // or extensions_by_name). We ignore python_dict_name if containing_type |
886 | // is NULL. |
887 | std::string Generator::FieldReferencingExpression( |
888 | const Descriptor* containing_type, const FieldDescriptor& field, |
889 | const std::string& python_dict_name) const { |
890 | // We should only ever be looking up fields in the current file. |
891 | // The only things we refer to from other files are message descriptors. |
892 | GOOGLE_CHECK_EQ(field.file(), file_) |
893 | << field.file()->name() << " vs. " << file_->name(); |
894 | if (!containing_type) { |
895 | return ResolveKeyword(name: field.name()); |
896 | } |
897 | return strings::Substitute(format: "$0.$1['$2']" , |
898 | arg0: ModuleLevelDescriptorName(descriptor: *containing_type), |
899 | arg1: python_dict_name, arg2: field.name()); |
900 | } |
901 | |
902 | // Prints containing_type for nested descriptors or enum descriptors. |
903 | template <typename DescriptorT> |
904 | void Generator::FixContainingTypeInDescriptor( |
905 | const DescriptorT& descriptor, |
906 | const Descriptor* containing_descriptor) const { |
907 | if (containing_descriptor != nullptr) { |
908 | const std::string nested_name = ModuleLevelDescriptorName(descriptor); |
909 | const std::string parent_name = |
910 | ModuleLevelDescriptorName(descriptor: *containing_descriptor); |
911 | printer_->Print(text: "$nested_name$.containing_type = $parent_name$\n" , |
912 | args: "nested_name" , args: nested_name, args: "parent_name" , args: parent_name); |
913 | } |
914 | } |
915 | |
916 | // Prints statements setting the message_type and enum_type fields in the |
917 | // Python descriptor objects we've already output in the file. We must |
918 | // do this in a separate step due to circular references (otherwise, we'd |
919 | // just set everything in the initial assignment statements). |
920 | void Generator::FixForeignFieldsInDescriptors() const { |
921 | for (int i = 0; i < file_->message_type_count(); ++i) { |
922 | FixForeignFieldsInDescriptor(descriptor: *file_->message_type(index: i), containing_descriptor: nullptr); |
923 | } |
924 | for (int i = 0; i < file_->message_type_count(); ++i) { |
925 | AddMessageToFileDescriptor(descriptor: *file_->message_type(index: i)); |
926 | } |
927 | for (int i = 0; i < file_->enum_type_count(); ++i) { |
928 | AddEnumToFileDescriptor(descriptor: *file_->enum_type(index: i)); |
929 | } |
930 | for (int i = 0; i < file_->extension_count(); ++i) { |
931 | AddExtensionToFileDescriptor(descriptor: *file_->extension(index: i)); |
932 | } |
933 | |
934 | // TODO(jieluo): Move this register to PrintFileDescriptor() when |
935 | // FieldDescriptor.file is added in generated file. |
936 | printer_->Print(text: "_sym_db.RegisterFileDescriptor($name$)\n" , args: "name" , |
937 | args: kDescriptorKey); |
938 | printer_->Print(text: "\n" ); |
939 | } |
940 | |
941 | // We need to not only set any necessary message_type fields, but |
942 | // also need to call RegisterExtension() on each message we're |
943 | // extending. |
944 | void Generator::FixForeignFieldsInExtensions() const { |
945 | // Top-level extensions. |
946 | for (int i = 0; i < file_->extension_count(); ++i) { |
947 | FixForeignFieldsInExtension(extension_field: *file_->extension(index: i)); |
948 | } |
949 | // Nested extensions. |
950 | for (int i = 0; i < file_->message_type_count(); ++i) { |
951 | FixForeignFieldsInNestedExtensions(descriptor: *file_->message_type(index: i)); |
952 | } |
953 | printer_->Print(text: "\n" ); |
954 | } |
955 | |
956 | void Generator::FixForeignFieldsInExtension( |
957 | const FieldDescriptor& extension_field) const { |
958 | GOOGLE_CHECK(extension_field.is_extension()); |
959 | |
960 | std::map<std::string, std::string> m; |
961 | // Confusingly, for FieldDescriptors that happen to be extensions, |
962 | // containing_type() means "extended type." |
963 | // On the other hand, extension_scope() will give us what we normally |
964 | // mean by containing_type(). |
965 | m["extended_message_class" ] = |
966 | ModuleLevelMessageName(descriptor: *extension_field.containing_type()); |
967 | m["field" ] = FieldReferencingExpression( |
968 | containing_type: extension_field.extension_scope(), field: extension_field, python_dict_name: "extensions_by_name" ); |
969 | printer_->Print(variables: m, text: "$extended_message_class$.RegisterExtension($field$)\n" ); |
970 | } |
971 | |
972 | void Generator::FixForeignFieldsInNestedExtensions( |
973 | const Descriptor& descriptor) const { |
974 | // Recursively fix up extensions in all nested types. |
975 | for (int i = 0; i < descriptor.nested_type_count(); ++i) { |
976 | FixForeignFieldsInNestedExtensions(descriptor: *descriptor.nested_type(index: i)); |
977 | } |
978 | // Fix up extensions directly contained within this type. |
979 | for (int i = 0; i < descriptor.extension_count(); ++i) { |
980 | FixForeignFieldsInExtension(extension_field: *descriptor.extension(index: i)); |
981 | } |
982 | } |
983 | |
984 | // Returns a Python expression that instantiates a Python EnumValueDescriptor |
985 | // object for the given C++ descriptor. |
986 | void Generator::PrintEnumValueDescriptor( |
987 | const EnumValueDescriptor& descriptor) const { |
988 | // TODO(robinson): Fix up EnumValueDescriptor "type" fields. |
989 | // More circular references. ::sigh:: |
990 | std::string options_string; |
991 | descriptor.options().SerializeToString(output: &options_string); |
992 | std::map<std::string, std::string> m; |
993 | m["name" ] = descriptor.name(); |
994 | m["index" ] = StrCat(a: descriptor.index()); |
995 | m["number" ] = StrCat(a: descriptor.number()); |
996 | m["options" ] = OptionsValue(serialized_options: options_string); |
997 | printer_->Print(variables: m, |
998 | text: "_descriptor.EnumValueDescriptor(\n" |
999 | " name='$name$', index=$index$, number=$number$,\n" |
1000 | " serialized_options=$options$,\n" |
1001 | " type=None,\n" |
1002 | " create_key=_descriptor._internal_create_key)" ); |
1003 | } |
1004 | |
1005 | // Returns a CEscaped string of serialized_options. |
1006 | std::string Generator::OptionsValue( |
1007 | const std::string& serialized_options) const { |
1008 | if (serialized_options.length() == 0 || GeneratingDescriptorProto()) { |
1009 | return "None" ; |
1010 | } else { |
1011 | return "b'" + CEscape(src: serialized_options) + "'" ; |
1012 | } |
1013 | } |
1014 | |
1015 | // Prints an expression for a Python FieldDescriptor for |field|. |
1016 | void Generator::PrintFieldDescriptor(const FieldDescriptor& field, |
1017 | bool is_extension) const { |
1018 | std::string options_string; |
1019 | field.options().SerializeToString(output: &options_string); |
1020 | std::map<std::string, std::string> m; |
1021 | m["name" ] = field.name(); |
1022 | m["full_name" ] = field.full_name(); |
1023 | m["index" ] = StrCat(a: field.index()); |
1024 | m["number" ] = StrCat(a: field.number()); |
1025 | m["type" ] = StrCat(a: field.type()); |
1026 | m["cpp_type" ] = StrCat(a: field.cpp_type()); |
1027 | m["label" ] = StrCat(a: field.label()); |
1028 | m["has_default_value" ] = field.has_default_value() ? "True" : "False" ; |
1029 | m["default_value" ] = StringifyDefaultValue(field); |
1030 | m["is_extension" ] = is_extension ? "True" : "False" ; |
1031 | m["serialized_options" ] = OptionsValue(serialized_options: options_string); |
1032 | m["json_name" ] = |
1033 | field.has_json_name() ? ", json_name='" + field.json_name() + "'" : "" ; |
1034 | // We always set message_type and enum_type to None at this point, and then |
1035 | // these fields in correctly after all referenced descriptors have been |
1036 | // defined and/or imported (see FixForeignFieldsInDescriptors()). |
1037 | const char field_descriptor_decl[] = |
1038 | "_descriptor.FieldDescriptor(\n" |
1039 | " name='$name$', full_name='$full_name$', index=$index$,\n" |
1040 | " number=$number$, type=$type$, cpp_type=$cpp_type$, label=$label$,\n" |
1041 | " has_default_value=$has_default_value$, " |
1042 | "default_value=$default_value$,\n" |
1043 | " message_type=None, enum_type=None, containing_type=None,\n" |
1044 | " is_extension=$is_extension$, extension_scope=None,\n" |
1045 | " serialized_options=$serialized_options$$json_name$, file=DESCRIPTOR," |
1046 | " create_key=_descriptor._internal_create_key)" ; |
1047 | printer_->Print(variables: m, text: field_descriptor_decl); |
1048 | } |
1049 | |
1050 | // Helper for Print{Fields,Extensions}InDescriptor(). |
1051 | void Generator::PrintFieldDescriptorsInDescriptor( |
1052 | const Descriptor& message_descriptor, bool is_extension, |
1053 | const std::string& list_variable_name, int (Descriptor::*CountFn)() const, |
1054 | const FieldDescriptor* (Descriptor::*GetterFn)(int)const) const { |
1055 | printer_->Print(text: "$list$=[\n" , args: "list" , args: list_variable_name); |
1056 | printer_->Indent(); |
1057 | for (int i = 0; i < (message_descriptor.*CountFn)(); ++i) { |
1058 | PrintFieldDescriptor(field: *(message_descriptor.*GetterFn)(i), is_extension); |
1059 | printer_->Print(text: ",\n" ); |
1060 | } |
1061 | printer_->Outdent(); |
1062 | printer_->Print(text: "],\n" ); |
1063 | } |
1064 | |
1065 | // Prints a statement assigning "fields" to a list of Python FieldDescriptors, |
1066 | // one for each field present in message_descriptor. |
1067 | void Generator::PrintFieldsInDescriptor( |
1068 | const Descriptor& message_descriptor) const { |
1069 | const bool is_extension = false; |
1070 | PrintFieldDescriptorsInDescriptor(message_descriptor, is_extension, list_variable_name: "fields" , |
1071 | CountFn: &Descriptor::field_count, |
1072 | GetterFn: &Descriptor::field); |
1073 | } |
1074 | |
1075 | // Prints a statement assigning "extensions" to a list of Python |
1076 | // FieldDescriptors, one for each extension present in message_descriptor. |
1077 | void Generator::PrintExtensionsInDescriptor( |
1078 | const Descriptor& message_descriptor) const { |
1079 | const bool is_extension = true; |
1080 | PrintFieldDescriptorsInDescriptor(message_descriptor, is_extension, |
1081 | list_variable_name: "extensions" , CountFn: &Descriptor::extension_count, |
1082 | GetterFn: &Descriptor::extension); |
1083 | } |
1084 | |
1085 | bool Generator::GeneratingDescriptorProto() const { |
1086 | return file_->name() == "net/proto2/proto/descriptor.proto" || |
1087 | file_->name() == "google/protobuf/descriptor.proto" ; |
1088 | } |
1089 | |
1090 | // Returns the unique Python module-level identifier given to a descriptor. |
1091 | // This name is module-qualified iff the given descriptor describes an |
1092 | // entity that doesn't come from the current file. |
1093 | template <typename DescriptorT> |
1094 | std::string Generator::ModuleLevelDescriptorName( |
1095 | const DescriptorT& descriptor) const { |
1096 | // FIXME(robinson): |
1097 | // We currently don't worry about collisions with underscores in the type |
1098 | // names, so these would collide in nasty ways if found in the same file: |
1099 | // OuterProto.ProtoA.ProtoB |
1100 | // OuterProto_ProtoA.ProtoB # Underscore instead of period. |
1101 | // As would these: |
1102 | // OuterProto.ProtoA_.ProtoB |
1103 | // OuterProto.ProtoA._ProtoB # Leading vs. trailing underscore. |
1104 | // (Contrived, but certainly possible). |
1105 | // |
1106 | // The C++ implementation doesn't guard against this either. Leaving |
1107 | // it for now... |
1108 | std::string name = NamePrefixedWithNestedTypes(descriptor, "_" ); |
1109 | ToUpper(s: &name); |
1110 | // Module-private for now. Easy to make public later; almost impossible |
1111 | // to make private later. |
1112 | name = "_" + name; |
1113 | // We now have the name relative to its own module. Also qualify with |
1114 | // the module name iff this descriptor is from a different .proto file. |
1115 | if (descriptor.file() != file_) { |
1116 | name = ModuleAlias(descriptor.file()->name()) + "." + name; |
1117 | } |
1118 | return name; |
1119 | } |
1120 | |
1121 | // Returns the name of the message class itself, not the descriptor. |
1122 | // Like ModuleLevelDescriptorName(), module-qualifies the name iff |
1123 | // the given descriptor describes an entity that doesn't come from |
1124 | // the current file. |
1125 | std::string Generator::ModuleLevelMessageName( |
1126 | const Descriptor& descriptor) const { |
1127 | std::string name = NamePrefixedWithNestedTypes(descriptor, separator: "." ); |
1128 | if (descriptor.file() != file_) { |
1129 | name = ModuleAlias(filename: descriptor.file()->name()) + "." + name; |
1130 | } |
1131 | return name; |
1132 | } |
1133 | |
1134 | // Returns the unique Python module-level identifier given to a service |
1135 | // descriptor. |
1136 | std::string Generator::ModuleLevelServiceDescriptorName( |
1137 | const ServiceDescriptor& descriptor) const { |
1138 | std::string name = descriptor.name(); |
1139 | ToUpper(s: &name); |
1140 | name = "_" + name; |
1141 | if (descriptor.file() != file_) { |
1142 | name = ModuleAlias(filename: descriptor.file()->name()) + "." + name; |
1143 | } |
1144 | return name; |
1145 | } |
1146 | |
1147 | // Prints standard constructor arguments serialized_start and serialized_end. |
1148 | // Args: |
1149 | // descriptor: The cpp descriptor to have a serialized reference. |
1150 | // proto: A proto |
1151 | // Example printer output: |
1152 | // serialized_start=41, |
1153 | // serialized_end=43, |
1154 | // |
1155 | template <typename DescriptorT, typename DescriptorProtoT> |
1156 | void Generator::PrintSerializedPbInterval(const DescriptorT& descriptor, |
1157 | DescriptorProtoT& proto, |
1158 | const std::string& name) const { |
1159 | descriptor.CopyTo(&proto); |
1160 | std::string sp; |
1161 | proto.SerializeToString(&sp); |
1162 | int offset = file_descriptor_serialized_.find(str: sp); |
1163 | GOOGLE_CHECK_GE(offset, 0); |
1164 | |
1165 | printer_->Print( |
1166 | text: "$name$._serialized_start=$serialized_start$\n" |
1167 | "$name$._serialized_end=$serialized_end$\n" , |
1168 | args: "name" , args: name, args: "serialized_start" , args: StrCat(a: offset), args: "serialized_end" , |
1169 | args: StrCat(a: offset + sp.size())); |
1170 | } |
1171 | |
1172 | namespace { |
1173 | void PrintDescriptorOptionsFixingCode(const std::string& descriptor, |
1174 | const std::string& options, |
1175 | io::Printer* printer) { |
1176 | // Reset the _options to None thus DescriptorBase.GetOptions() can |
1177 | // parse _options again after extensions are registered. |
1178 | printer->Print( |
1179 | text: "$descriptor$._options = None\n" |
1180 | "$descriptor$._serialized_options = $serialized_value$\n" , |
1181 | args: "descriptor" , args: descriptor, args: "serialized_value" , args: options); |
1182 | } |
1183 | } // namespace |
1184 | |
1185 | void Generator::SetSerializedPbInterval() const { |
1186 | // Top level enums. |
1187 | for (int i = 0; i < file_->enum_type_count(); ++i) { |
1188 | EnumDescriptorProto proto; |
1189 | const EnumDescriptor& descriptor = *file_->enum_type(index: i); |
1190 | PrintSerializedPbInterval(descriptor, proto, |
1191 | name: ModuleLevelDescriptorName(descriptor)); |
1192 | } |
1193 | |
1194 | // Messages. |
1195 | for (int i = 0; i < file_->message_type_count(); ++i) { |
1196 | SetMessagePbInterval(*file_->message_type(index: i)); |
1197 | } |
1198 | |
1199 | // Services. |
1200 | for (int i = 0; i < file_->service_count(); ++i) { |
1201 | ServiceDescriptorProto proto; |
1202 | const ServiceDescriptor& service = *file_->service(index: i); |
1203 | PrintSerializedPbInterval(descriptor: service, proto, |
1204 | name: ModuleLevelServiceDescriptorName(descriptor: service)); |
1205 | } |
1206 | } |
1207 | |
1208 | void Generator::SetMessagePbInterval(const Descriptor& descriptor) const { |
1209 | DescriptorProto message_proto; |
1210 | PrintSerializedPbInterval(descriptor, proto&: message_proto, |
1211 | name: ModuleLevelDescriptorName(descriptor)); |
1212 | |
1213 | // Nested messages. |
1214 | for (int i = 0; i < descriptor.nested_type_count(); ++i) { |
1215 | SetMessagePbInterval(*descriptor.nested_type(index: i)); |
1216 | } |
1217 | |
1218 | for (int i = 0; i < descriptor.enum_type_count(); ++i) { |
1219 | EnumDescriptorProto proto; |
1220 | const EnumDescriptor& enum_des = *descriptor.enum_type(index: i); |
1221 | PrintSerializedPbInterval(descriptor: enum_des, proto, |
1222 | name: ModuleLevelDescriptorName(descriptor: enum_des)); |
1223 | } |
1224 | } |
1225 | |
1226 | // Prints expressions that set the options field of all descriptors. |
1227 | void Generator::FixAllDescriptorOptions() const { |
1228 | // Prints an expression that sets the file descriptor's options. |
1229 | std::string file_options = OptionsValue(serialized_options: file_->options().SerializeAsString()); |
1230 | if (file_options != "None" ) { |
1231 | PrintDescriptorOptionsFixingCode(descriptor: kDescriptorKey, options: file_options, printer: printer_); |
1232 | } else { |
1233 | printer_->Print(text: "DESCRIPTOR._options = None\n" ); |
1234 | } |
1235 | // Prints expressions that set the options for all top level enums. |
1236 | for (int i = 0; i < file_->enum_type_count(); ++i) { |
1237 | const EnumDescriptor& enum_descriptor = *file_->enum_type(index: i); |
1238 | FixOptionsForEnum(descriptor: enum_descriptor); |
1239 | } |
1240 | // Prints expressions that set the options for all top level extensions. |
1241 | for (int i = 0; i < file_->extension_count(); ++i) { |
1242 | const FieldDescriptor& field = *file_->extension(index: i); |
1243 | FixOptionsForField(field); |
1244 | } |
1245 | // Prints expressions that set the options for all messages, nested enums, |
1246 | // nested extensions and message fields. |
1247 | for (int i = 0; i < file_->message_type_count(); ++i) { |
1248 | FixOptionsForMessage(descriptor: *file_->message_type(index: i)); |
1249 | } |
1250 | |
1251 | for (int i = 0; i < file_->service_count(); ++i) { |
1252 | FixOptionsForService(descriptor: *file_->service(index: i)); |
1253 | } |
1254 | } |
1255 | |
1256 | void Generator::FixOptionsForOneof(const OneofDescriptor& oneof) const { |
1257 | std::string oneof_options = OptionsValue(serialized_options: oneof.options().SerializeAsString()); |
1258 | if (oneof_options != "None" ) { |
1259 | std::string oneof_name = strings::Substitute( |
1260 | format: "$0.$1['$2']" , arg0: ModuleLevelDescriptorName(descriptor: *oneof.containing_type()), |
1261 | arg1: "oneofs_by_name" , arg2: oneof.name()); |
1262 | PrintDescriptorOptionsFixingCode(descriptor: oneof_name, options: oneof_options, printer: printer_); |
1263 | } |
1264 | } |
1265 | |
1266 | // Prints expressions that set the options for an enum descriptor and its |
1267 | // value descriptors. |
1268 | void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const { |
1269 | std::string descriptor_name = ModuleLevelDescriptorName(descriptor: enum_descriptor); |
1270 | std::string enum_options = |
1271 | OptionsValue(serialized_options: enum_descriptor.options().SerializeAsString()); |
1272 | if (enum_options != "None" ) { |
1273 | PrintDescriptorOptionsFixingCode(descriptor: descriptor_name, options: enum_options, printer: printer_); |
1274 | } |
1275 | for (int i = 0; i < enum_descriptor.value_count(); ++i) { |
1276 | const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(index: i); |
1277 | std::string value_options = |
1278 | OptionsValue(serialized_options: value_descriptor.options().SerializeAsString()); |
1279 | if (value_options != "None" ) { |
1280 | PrintDescriptorOptionsFixingCode( |
1281 | descriptor: StringPrintf(format: "%s.values_by_name[\"%s\"]" , descriptor_name.c_str(), |
1282 | value_descriptor.name().c_str()), |
1283 | options: value_options, printer: printer_); |
1284 | } |
1285 | } |
1286 | } |
1287 | |
1288 | // Prints expressions that set the options for an service descriptor and its |
1289 | // value descriptors. |
1290 | void Generator::FixOptionsForService( |
1291 | const ServiceDescriptor& service_descriptor) const { |
1292 | std::string descriptor_name = |
1293 | ModuleLevelServiceDescriptorName(descriptor: service_descriptor); |
1294 | std::string service_options = |
1295 | OptionsValue(serialized_options: service_descriptor.options().SerializeAsString()); |
1296 | if (service_options != "None" ) { |
1297 | PrintDescriptorOptionsFixingCode(descriptor: descriptor_name, options: service_options, |
1298 | printer: printer_); |
1299 | } |
1300 | |
1301 | for (int i = 0; i < service_descriptor.method_count(); ++i) { |
1302 | const MethodDescriptor* method = service_descriptor.method(index: i); |
1303 | std::string method_options = |
1304 | OptionsValue(serialized_options: method->options().SerializeAsString()); |
1305 | if (method_options != "None" ) { |
1306 | std::string method_name = |
1307 | descriptor_name + ".methods_by_name['" + method->name() + "']" ; |
1308 | PrintDescriptorOptionsFixingCode(descriptor: method_name, options: method_options, printer: printer_); |
1309 | } |
1310 | } |
1311 | } |
1312 | |
1313 | // Prints expressions that set the options for field descriptors (including |
1314 | // extensions). |
1315 | void Generator::FixOptionsForField(const FieldDescriptor& field) const { |
1316 | std::string field_options = OptionsValue(serialized_options: field.options().SerializeAsString()); |
1317 | if (field_options != "None" ) { |
1318 | std::string field_name; |
1319 | if (field.is_extension()) { |
1320 | if (field.extension_scope() == nullptr) { |
1321 | // Top level extensions. |
1322 | field_name = field.name(); |
1323 | } else { |
1324 | field_name = FieldReferencingExpression(containing_type: field.extension_scope(), field, |
1325 | python_dict_name: "extensions_by_name" ); |
1326 | } |
1327 | } else { |
1328 | field_name = FieldReferencingExpression(containing_type: field.containing_type(), field, |
1329 | python_dict_name: "fields_by_name" ); |
1330 | } |
1331 | PrintDescriptorOptionsFixingCode(descriptor: field_name, options: field_options, printer: printer_); |
1332 | } |
1333 | } |
1334 | |
1335 | // Prints expressions that set the options for a message and all its inner |
1336 | // types (nested messages, nested enums, extensions, fields). |
1337 | void Generator::FixOptionsForMessage(const Descriptor& descriptor) const { |
1338 | // Nested messages. |
1339 | for (int i = 0; i < descriptor.nested_type_count(); ++i) { |
1340 | FixOptionsForMessage(descriptor: *descriptor.nested_type(index: i)); |
1341 | } |
1342 | // Oneofs. |
1343 | for (int i = 0; i < descriptor.oneof_decl_count(); ++i) { |
1344 | FixOptionsForOneof(oneof: *descriptor.oneof_decl(index: i)); |
1345 | } |
1346 | // Enums. |
1347 | for (int i = 0; i < descriptor.enum_type_count(); ++i) { |
1348 | FixOptionsForEnum(enum_descriptor: *descriptor.enum_type(index: i)); |
1349 | } |
1350 | // Fields. |
1351 | for (int i = 0; i < descriptor.field_count(); ++i) { |
1352 | const FieldDescriptor& field = *descriptor.field(index: i); |
1353 | FixOptionsForField(field); |
1354 | } |
1355 | // Extensions. |
1356 | for (int i = 0; i < descriptor.extension_count(); ++i) { |
1357 | const FieldDescriptor& field = *descriptor.extension(index: i); |
1358 | FixOptionsForField(field); |
1359 | } |
1360 | // Message option for this message. |
1361 | std::string message_options = |
1362 | OptionsValue(serialized_options: descriptor.options().SerializeAsString()); |
1363 | if (message_options != "None" ) { |
1364 | std::string descriptor_name = ModuleLevelDescriptorName(descriptor); |
1365 | PrintDescriptorOptionsFixingCode(descriptor: descriptor_name, options: message_options, |
1366 | printer: printer_); |
1367 | } |
1368 | } |
1369 | |
1370 | // If a dependency forwards other files through public dependencies, let's |
1371 | // copy over the corresponding module aliases. |
1372 | void Generator::CopyPublicDependenciesAliases( |
1373 | const std::string& copy_from, const FileDescriptor* file) const { |
1374 | for (int i = 0; i < file->public_dependency_count(); ++i) { |
1375 | std::string module_name = ModuleName(filename: file->public_dependency(index: i)->name()); |
1376 | std::string module_alias = ModuleAlias(filename: file->public_dependency(index: i)->name()); |
1377 | // There's no module alias in the dependent file if it was generated by |
1378 | // an old protoc (less than 3.0.0-alpha-1). Use module name in this |
1379 | // situation. |
1380 | printer_->Print( |
1381 | text: "try:\n" |
1382 | " $alias$ = $copy_from$.$alias$\n" |
1383 | "except AttributeError:\n" |
1384 | " $alias$ = $copy_from$.$module$\n" , |
1385 | args: "alias" , args: module_alias, args: "module" , args: module_name, args: "copy_from" , args: copy_from); |
1386 | CopyPublicDependenciesAliases(copy_from, file: file->public_dependency(index: i)); |
1387 | } |
1388 | } |
1389 | |
1390 | } // namespace python |
1391 | } // namespace compiler |
1392 | } // namespace protobuf |
1393 | } // namespace google |
1394 | |