1/*
2 * Copyright 2014 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// independent from idl_parser, since this code is not needed for most clients
18
19#include "idl_gen_python.h"
20
21#include <cctype>
22#include <set>
23#include <string>
24#include <unordered_set>
25#include <vector>
26
27#include "flatbuffers/code_generators.h"
28#include "flatbuffers/flatbuffers.h"
29#include "flatbuffers/idl.h"
30#include "flatbuffers/util.h"
31#include "idl_namer.h"
32
33namespace flatbuffers {
34namespace python {
35
36namespace {
37
38typedef std::pair<std::string, std::string> ImportMapEntry;
39typedef std::set<ImportMapEntry> ImportMap;
40
41static std::set<std::string> PythonKeywords() {
42 return { "False", "None", "True", "and", "as", "assert",
43 "break", "class", "continue", "def", "del", "elif",
44 "else", "except", "finally", "for", "from", "global",
45 "if", "import", "in", "is", "lambda", "nonlocal",
46 "not", "or", "pass", "raise", "return", "try",
47 "while", "with", "yield" };
48}
49
50static Namer::Config PythonDefaultConfig() {
51 return { /*types=*/Case::kKeep,
52 /*constants=*/Case::kScreamingSnake,
53 /*methods=*/Case::kUpperCamel,
54 /*functions=*/Case::kUpperCamel,
55 /*fields=*/Case::kLowerCamel,
56 /*variable=*/Case::kLowerCamel,
57 /*variants=*/Case::kKeep,
58 /*enum_variant_seperator=*/".",
59 /*escape_keywords=*/Namer::Config::Escape::BeforeConvertingCase,
60 /*namespaces=*/Case::kKeep, // Packages in python.
61 /*namespace_seperator=*/".",
62 /*object_prefix=*/"",
63 /*object_suffix=*/"T",
64 /*keyword_prefix=*/"",
65 /*keyword_suffix=*/"_",
66 /*filenames=*/Case::kKeep,
67 /*directories=*/Case::kKeep,
68 /*output_path=*/"",
69 /*filename_suffix=*/"",
70 /*filename_extension=*/".py" };
71}
72
73// Hardcode spaces per indentation.
74static const CommentConfig def_comment = { nullptr, "#", nullptr };
75static const std::string Indent = " ";
76
77} // namespace
78
79class PythonGenerator : public BaseGenerator {
80 public:
81 PythonGenerator(const Parser &parser, const std::string &path,
82 const std::string &file_name)
83 : BaseGenerator(parser, path, file_name, "" /* not used */,
84 "" /* not used */, "py"),
85 float_const_gen_("float('nan')", "float('inf')", "float('-inf')"),
86 namer_(WithFlagOptions(PythonDefaultConfig(), parser.opts, path),
87 PythonKeywords()) {}
88
89 // Most field accessors need to retrieve and test the field offset first,
90 // this is the prefix code for that.
91 std::string OffsetPrefix(const FieldDef &field, bool new_line = true) const {
92 return "\n" + Indent + Indent +
93 "o = flatbuffers.number_types.UOffsetTFlags.py_type" +
94 "(self._tab.Offset(" + NumToString(field.value.offset) + "))\n" +
95 Indent + Indent + "if o != 0:" + (new_line ? "\n" : "");
96 }
97
98 // Begin a class declaration.
99 void BeginClass(const StructDef &struct_def, std::string *code_ptr) const {
100 auto &code = *code_ptr;
101 code += "class " + namer_.Type(struct_def) + "(object):\n";
102 code += Indent + "__slots__ = ['_tab']";
103 code += "\n\n";
104 }
105
106 // Begin enum code with a class declaration.
107 void BeginEnum(const EnumDef &enum_def, std::string *code_ptr) const {
108 auto &code = *code_ptr;
109 code += "class " + namer_.Type(enum_def) + "(object):\n";
110 }
111
112 // Starts a new line and then indents.
113 std::string GenIndents(int num) const {
114 return "\n" + std::string(num * Indent.length(), ' ');
115 }
116
117 // A single enum member.
118 void EnumMember(const EnumDef &enum_def, const EnumVal &ev,
119 std::string *code_ptr) const {
120 auto &code = *code_ptr;
121 code += Indent;
122 code += namer_.Variant(ev);
123 code += " = ";
124 code += enum_def.ToString(ev) + "\n";
125 }
126
127 // Initialize a new struct or table from existing data.
128 void NewRootTypeFromBuffer(const StructDef &struct_def,
129 std::string *code_ptr) const {
130 auto &code = *code_ptr;
131 const std::string struct_type = namer_.Type(struct_def);
132
133 code += Indent + "@classmethod\n";
134 code += Indent + "def GetRootAs";
135 if (parser_.opts.python_typing) {
136 code += "(cls, buf, offset: int = 0):";
137 } else {
138 code += "(cls, buf, offset=0):";
139 }
140 code += "\n";
141 code += Indent + Indent;
142 code += "n = flatbuffers.encode.Get";
143 code += "(flatbuffers.packer.uoffset, buf, offset)\n";
144 code += Indent + Indent + "x = " + struct_type + "()\n";
145 code += Indent + Indent + "x.Init(buf, n + offset)\n";
146 code += Indent + Indent + "return x\n";
147 code += "\n";
148
149 if (!parser_.opts.python_no_type_prefix_suffix) {
150 // Add an alias with the old name
151 code += Indent + "@classmethod\n";
152 code +=
153 Indent + "def GetRootAs" + struct_type + "(cls, buf, offset=0):\n";
154 code += Indent + Indent +
155 "\"\"\"This method is deprecated. Please switch to "
156 "GetRootAs.\"\"\"\n";
157 code += Indent + Indent + "return cls.GetRootAs(buf, offset)\n";
158 }
159 }
160
161 // Initialize an existing object with other data, to avoid an allocation.
162 void InitializeExisting(const StructDef &struct_def,
163 std::string *code_ptr) const {
164 auto &code = *code_ptr;
165
166 GenReceiver(struct_def, code_ptr);
167 if (parser_.opts.python_typing) {
168 code += "Init(self, buf: bytes, pos: int):\n";
169 } else {
170 code += "Init(self, buf, pos):\n";
171 }
172 code += Indent + Indent + "self._tab = flatbuffers.table.Table(buf, pos)\n";
173 code += "\n";
174 }
175
176 // Get the length of a vector.
177 void GetVectorLen(const StructDef &struct_def, const FieldDef &field,
178 std::string *code_ptr) const {
179 auto &code = *code_ptr;
180
181 GenReceiver(struct_def, code_ptr);
182 code += namer_.Method(field) + "Length(self)";
183 if (parser_.opts.python_typing) { code += " -> int"; }
184 code += ":";
185 if (!IsArray(field.value.type)) {
186 code += OffsetPrefix(field, false);
187 code += GenIndents(3) + "return self._tab.VectorLen(o)";
188 code += GenIndents(2) + "return 0\n\n";
189 } else {
190 code += GenIndents(2) + "return " +
191 NumToString(field.value.type.fixed_length) + "\n\n";
192 }
193 }
194
195 // Determines whether a vector is none or not.
196 void GetVectorIsNone(const StructDef &struct_def, const FieldDef &field,
197 std::string *code_ptr) const {
198 auto &code = *code_ptr;
199
200 GenReceiver(struct_def, code_ptr);
201 code += namer_.Method(field) + "IsNone(self)";
202 if (parser_.opts.python_typing) { code += " -> bool"; }
203 code += ":";
204 if (!IsArray(field.value.type)) {
205 code += GenIndents(2) +
206 "o = flatbuffers.number_types.UOffsetTFlags.py_type" +
207 "(self._tab.Offset(" + NumToString(field.value.offset) + "))";
208 code += GenIndents(2) + "return o == 0";
209 } else {
210 // assume that we always have an array as memory is preassigned
211 code += GenIndents(2) + "return False";
212 }
213 code += "\n\n";
214 }
215
216 // Get the value of a struct's scalar.
217 void GetScalarFieldOfStruct(const StructDef &struct_def,
218 const FieldDef &field,
219 std::string *code_ptr) const {
220 auto &code = *code_ptr;
221 std::string getter = GenGetter(field.value.type);
222 GenReceiver(struct_def, code_ptr);
223 code += namer_.Method(field);
224 code += "(self): return " + getter;
225 code += "self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(";
226 code += NumToString(field.value.offset) + "))\n";
227 }
228
229 // Get the value of a table's scalar.
230 void GetScalarFieldOfTable(const StructDef &struct_def, const FieldDef &field,
231 std::string *code_ptr) const {
232 auto &code = *code_ptr;
233 std::string getter = GenGetter(field.value.type);
234 GenReceiver(struct_def, code_ptr);
235 code += namer_.Method(field);
236 code += "(self):";
237 code += OffsetPrefix(field);
238 getter += "o + self._tab.Pos)";
239 auto is_bool = IsBool(field.value.type.base_type);
240 if (is_bool) { getter = "bool(" + getter + ")"; }
241 code += Indent + Indent + Indent + "return " + getter + "\n";
242 std::string default_value;
243 if (field.IsScalarOptional()) {
244 default_value = "None";
245 } else if (is_bool) {
246 default_value = field.value.constant == "0" ? "False" : "True";
247 } else {
248 default_value = IsFloat(field.value.type.base_type)
249 ? float_const_gen_.GenFloatConstant(field)
250 : field.value.constant;
251 }
252 code += Indent + Indent + "return " + default_value + "\n\n";
253 }
254
255 // Get a struct by initializing an existing struct.
256 // Specific to Struct.
257 void GetStructFieldOfStruct(const StructDef &struct_def,
258 const FieldDef &field,
259 std::string *code_ptr) const {
260 auto &code = *code_ptr;
261 GenReceiver(struct_def, code_ptr);
262 code += namer_.Method(field);
263 code += "(self, obj):\n";
264 code += Indent + Indent + "obj.Init(self._tab.Bytes, self._tab.Pos + ";
265 code += NumToString(field.value.offset) + ")";
266 code += "\n" + Indent + Indent + "return obj\n\n";
267 }
268
269 // Get the value of a fixed size array.
270 void GetArrayOfStruct(const StructDef &struct_def, const FieldDef &field,
271 std::string *code_ptr, ImportMap &imports) const {
272 auto &code = *code_ptr;
273 const auto vec_type = field.value.type.VectorType();
274 GenReceiver(struct_def, code_ptr);
275 code += namer_.Method(field);
276
277 const ImportMapEntry import_entry = {
278 GenPackageReference(field.value.type), TypeName(field)
279 };
280
281 if (parser_.opts.python_typing) {
282 const std::string return_type = ReturnType(struct_def, field);
283 code += "(self, i: int)";
284 code += " -> " + return_type + ":";
285
286 imports.insert(import_entry);
287 } else {
288 code += "(self, i):";
289 }
290
291 if (parser_.opts.include_dependence_headers &&
292 !parser_.opts.python_typing) {
293 code += GenIndents(2);
294 code += "from " + import_entry.first + " import " + import_entry.second +
295 "\n";
296 }
297
298 code += GenIndents(2) + "obj = " + TypeName(field) + "()";
299 code += GenIndents(2) + "obj.Init(self._tab.Bytes, self._tab.Pos + ";
300 code += NumToString(field.value.offset) + " + i * ";
301 code += NumToString(InlineSize(vec_type));
302 code += ")" + GenIndents(2) + "return obj\n\n";
303 }
304
305 // Get the value of a vector's non-struct member. Uses a named return
306 // argument to conveniently set the zero value for the result.
307 void GetArrayOfNonStruct(const StructDef &struct_def, const FieldDef &field,
308 std::string *code_ptr) const {
309 auto &code = *code_ptr;
310 GenReceiver(struct_def, code_ptr);
311 code += namer_.Method(field);
312 code += "(self, j = None):";
313 code += GenIndents(2) + "if j is None:";
314 code += GenIndents(3) + "return [" + GenGetter(field.value.type);
315 code += "self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(";
316 code += NumToString(field.value.offset) + " + i * ";
317 code += NumToString(InlineSize(field.value.type.VectorType()));
318 code += ")) for i in range(";
319 code += "self." + namer_.Method(field) + "Length()" + ")]";
320 code += GenIndents(2) + "elif j >= 0 and j < self." + namer_.Method(field) +
321 "Length():";
322 code += GenIndents(3) + "return " + GenGetter(field.value.type);
323 code += "self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(";
324 code += NumToString(field.value.offset) + " + j * ";
325 code += NumToString(InlineSize(field.value.type.VectorType()));
326 code += "))";
327 code += GenIndents(2) + "else:";
328 code += GenIndents(3) + "return None\n\n";
329 }
330
331 // Get a struct by initializing an existing struct.
332 // Specific to Table.
333 void GetStructFieldOfTable(const StructDef &struct_def, const FieldDef &field,
334 std::string *code_ptr, ImportMap &imports) const {
335 auto &code = *code_ptr;
336 GenReceiver(struct_def, code_ptr);
337 code += namer_.Method(field) + "(self)";
338
339 const ImportMapEntry import_entry = {
340 GenPackageReference(field.value.type), TypeName(field)
341 };
342
343 if (parser_.opts.python_typing) {
344 const std::string return_type = ReturnType(struct_def, field);
345 code += " -> Optional[" + return_type + "]";
346 imports.insert(ImportMapEntry{ "typing", "Optional" });
347 imports.insert(import_entry);
348 }
349 code += ":";
350 code += OffsetPrefix(field);
351 if (field.value.type.struct_def->fixed) {
352 code += Indent + Indent + Indent + "x = o + self._tab.Pos\n";
353 } else {
354 code += Indent + Indent + Indent;
355 code += "x = self._tab.Indirect(o + self._tab.Pos)\n";
356 }
357
358 if (parser_.opts.include_dependence_headers &&
359 !parser_.opts.python_typing) {
360 code += Indent + Indent + Indent;
361 code += "from " + import_entry.first + " import " + import_entry.second +
362 "\n";
363 }
364 code += Indent + Indent + Indent + "obj = " + TypeName(field) + "()\n";
365 code += Indent + Indent + Indent + "obj.Init(self._tab.Bytes, x)\n";
366 code += Indent + Indent + Indent + "return obj\n";
367 code += Indent + Indent + "return None\n\n";
368 }
369
370 // Get the value of a string.
371 void GetStringField(const StructDef &struct_def, const FieldDef &field,
372 std::string *code_ptr, ImportMap &imports) const {
373 auto &code = *code_ptr;
374 GenReceiver(struct_def, code_ptr);
375 code += namer_.Method(field);
376
377 if (parser_.opts.python_typing) {
378 code += "(self) -> Optional[str]:";
379 imports.insert(ImportMapEntry{ "typing", "Optional" });
380 } else {
381 code += "(self):";
382 }
383
384 code += OffsetPrefix(field);
385 code += Indent + Indent + Indent + "return " + GenGetter(field.value.type);
386 code += "o + self._tab.Pos)\n";
387 code += Indent + Indent + "return None\n\n";
388 }
389
390 // Get the value of a union from an object.
391 void GetUnionField(const StructDef &struct_def, const FieldDef &field,
392 std::string *code_ptr, ImportMap &imports) const {
393 auto &code = *code_ptr;
394 GenReceiver(struct_def, code_ptr);
395 std::string return_ty = "flatbuffers.table.Table";
396
397 bool is_native_table = TypeName(field) == "*flatbuffers.Table";
398 ImportMapEntry import_entry;
399 if (is_native_table) {
400 import_entry = ImportMapEntry{ "flatbuffers.table", "Table" };
401 } else {
402 return_ty = TypeName(field);
403 import_entry = ImportMapEntry{ GenPackageReference(field.value.type),
404 TypeName(field) };
405 }
406
407 code += namer_.Method(field) + "(self)";
408 if (parser_.opts.python_typing) {
409 code += " -> Optional[" + return_ty + "]";
410 imports.insert(ImportMapEntry{ "typing", "Optional" });
411 imports.insert(import_entry);
412 }
413 code += ":";
414 code += OffsetPrefix(field);
415
416 if (!parser_.opts.python_typing) {
417 code += Indent + Indent + Indent;
418 code += "from " + import_entry.first + " import " + import_entry.second +
419 "\n";
420 }
421 code += Indent + Indent + Indent + "obj = Table(bytearray(), 0)\n";
422 code += Indent + Indent + Indent + GenGetter(field.value.type);
423 code += "obj, o)\n" + Indent + Indent + Indent + "return obj\n";
424 code += Indent + Indent + "return None\n\n";
425 }
426
427 // Generate the package reference when importing a struct or enum from its
428 // module.
429 std::string GenPackageReference(const Type &type) const {
430 if (type.struct_def) {
431 return namer_.NamespacedType(*type.struct_def);
432 } else if (type.enum_def) {
433 return namer_.NamespacedType(*type.enum_def);
434 } else {
435 return "." + GenTypeGet(type);
436 }
437 }
438
439 // Get the value of a vector's struct member.
440 void GetMemberOfVectorOfStruct(const StructDef &struct_def,
441 const FieldDef &field, std::string *code_ptr,
442 ImportMap &imports) const {
443 auto &code = *code_ptr;
444 auto vectortype = field.value.type.VectorType();
445
446 GenReceiver(struct_def, code_ptr);
447 code += namer_.Method(field);
448 const ImportMapEntry import_entry = {
449 GenPackageReference(field.value.type), TypeName(field)
450 };
451
452 if (parser_.opts.python_typing) {
453 const std::string return_type = ReturnType(struct_def, field);
454 code += "(self, j: int) -> Optional[" + return_type + "]";
455 imports.insert(ImportMapEntry{ "typing", "Optional" });
456 imports.insert(import_entry);
457 } else {
458 code += "(self, j)";
459 }
460 code += ":" + OffsetPrefix(field);
461 code += Indent + Indent + Indent + "x = self._tab.Vector(o)\n";
462 code += Indent + Indent + Indent;
463 code += "x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * ";
464 code += NumToString(InlineSize(vectortype)) + "\n";
465 if (!(vectortype.struct_def->fixed)) {
466 code += Indent + Indent + Indent + "x = self._tab.Indirect(x)\n";
467 }
468 if (parser_.opts.include_dependence_headers &&
469 !parser_.opts.python_typing) {
470 code += Indent + Indent + Indent;
471 code += "from " + import_entry.first + " import " + import_entry.second +
472 "\n";
473 }
474 code += Indent + Indent + Indent + "obj = " + TypeName(field) + "()\n";
475 code += Indent + Indent + Indent + "obj.Init(self._tab.Bytes, x)\n";
476 code += Indent + Indent + Indent + "return obj\n";
477 code += Indent + Indent + "return None\n\n";
478 }
479
480 // Get the value of a vector's non-struct member. Uses a named return
481 // argument to conveniently set the zero value for the result.
482 void GetMemberOfVectorOfNonStruct(const StructDef &struct_def,
483 const FieldDef &field,
484 std::string *code_ptr) const {
485 auto &code = *code_ptr;
486 auto vectortype = field.value.type.VectorType();
487
488 GenReceiver(struct_def, code_ptr);
489 code += namer_.Method(field);
490 if (parser_.opts.python_typing) {
491 code += "(self, j: int)";
492 } else {
493 code += "(self, j)";
494 }
495 code += ":";
496 code += OffsetPrefix(field);
497 code += Indent + Indent + Indent + "a = self._tab.Vector(o)\n";
498 code += Indent + Indent + Indent;
499 code += "return " + GenGetter(field.value.type);
500 code += "a + flatbuffers.number_types.UOffsetTFlags.py_type(j * ";
501 code += NumToString(InlineSize(vectortype)) + "))\n";
502 if (IsString(vectortype)) {
503 code += Indent + Indent + "return \"\"\n";
504 } else {
505 code += Indent + Indent + "return 0\n";
506 }
507 code += "\n";
508 }
509
510 // Returns a non-struct vector as a numpy array. Much faster
511 // than iterating over the vector element by element.
512 void GetVectorOfNonStructAsNumpy(const StructDef &struct_def,
513 const FieldDef &field,
514 std::string *code_ptr) const {
515 auto &code = *code_ptr;
516 auto vectortype = field.value.type.VectorType();
517
518 // Currently, we only support accessing as numpy array if
519 // the vector type is a scalar.
520 if (!(IsScalar(vectortype.base_type))) { return; }
521
522 GenReceiver(struct_def, code_ptr);
523 code += namer_.Method(field) + "AsNumpy(self):";
524 if (!IsArray(field.value.type)) {
525 code += OffsetPrefix(field, false);
526
527 code += GenIndents(3);
528 code += "return ";
529 code += "self._tab.GetVectorAsNumpy(flatbuffers.number_types.";
530 code += namer_.Method(GenTypeGet(field.value.type));
531 code += "Flags, o)";
532
533 if (IsString(vectortype)) {
534 code += GenIndents(2) + "return \"\"\n";
535 } else {
536 code += GenIndents(2) + "return 0\n";
537 }
538 } else {
539 code += GenIndents(2) + "return ";
540 code += "self._tab.GetArrayAsNumpy(flatbuffers.number_types.";
541 code += namer_.Method(GenTypeGet(field.value.type.VectorType()));
542 code += "Flags, self._tab.Pos + " + NumToString(field.value.offset) +
543 ", " + NumToString("self." + namer_.Method(field) + "Length()") +
544 ")\n";
545 }
546 code += "\n";
547 }
548
549 std::string NestedFlatbufferType(std::string unqualified_name) const {
550 StructDef *nested_root = parser_.LookupStruct(unqualified_name);
551 std::string qualified_name;
552 if (nested_root == nullptr) {
553 qualified_name = namer_.NamespacedType(
554 parser_.current_namespace_->components, unqualified_name);
555 // Double check qualified name just to be sure it exists.
556 nested_root = parser_.LookupStruct(qualified_name);
557 }
558 FLATBUFFERS_ASSERT(nested_root); // Guaranteed to exist by parser.
559 return qualified_name;
560 }
561
562 // Returns a nested flatbuffer as itself.
563 void GetVectorAsNestedFlatbuffer(const StructDef &struct_def,
564 const FieldDef &field, std::string *code_ptr,
565 ImportMap &imports) const {
566 auto nested = field.attributes.Lookup("nested_flatbuffer");
567 if (!nested) { return; } // There is no nested flatbuffer.
568
569 const std::string unqualified_name = nested->constant;
570 std::string qualified_name = NestedFlatbufferType(unqualified_name);
571 if (qualified_name.empty()) { qualified_name = nested->constant; }
572
573 const ImportMapEntry import_entry = { qualified_name,
574 unqualified_name };
575
576 auto &code = *code_ptr;
577 GenReceiver(struct_def, code_ptr);
578 code += namer_.Method(field) + "NestedRoot(self)";
579 if (parser_.opts.python_typing) {
580 code += " -> Union[" + unqualified_name + ", int]";
581 imports.insert(ImportMapEntry{ "typing", "Union" });
582 imports.insert(import_entry);
583 }
584 code += ":";
585
586 code += OffsetPrefix(field);
587
588 if (!parser_.opts.python_typing) {
589 code += Indent + Indent + Indent;
590 code += "from " + import_entry.first + " import " + import_entry.second +
591 "\n";
592 }
593 code += Indent + Indent + Indent + "return " + unqualified_name;
594 code += ".GetRootAs";
595 code += "(self._tab.Bytes, self._tab.Vector(o))\n";
596 code += Indent + Indent + "return 0\n";
597 code += "\n";
598 }
599
600 // Begin the creator function signature.
601 void BeginBuilderArgs(const StructDef &struct_def,
602 std::string *code_ptr) const {
603 auto &code = *code_ptr;
604
605 code += "\n";
606 code += "def Create" + namer_.Type(struct_def);
607 code += "(builder";
608 }
609
610 // Recursively generate arguments for a constructor, to deal with nested
611 // structs.
612 void StructBuilderArgs(const StructDef &struct_def,
613 const std::string nameprefix,
614 const std::string namesuffix, bool has_field_name,
615 const std::string fieldname_suffix,
616 std::string *code_ptr) const {
617 for (auto it = struct_def.fields.vec.begin();
618 it != struct_def.fields.vec.end(); ++it) {
619 auto &field = **it;
620 const auto &field_type = field.value.type;
621 const auto &type =
622 IsArray(field_type) ? field_type.VectorType() : field_type;
623 if (IsStruct(type)) {
624 // Generate arguments for a struct inside a struct. To ensure names
625 // don't clash, and to make it obvious these arguments are constructing
626 // a nested struct, prefix the name with the field name.
627 auto subprefix = nameprefix;
628 if (has_field_name) {
629 subprefix += namer_.Field(field) + fieldname_suffix;
630 }
631 StructBuilderArgs(*field.value.type.struct_def, subprefix, namesuffix,
632 has_field_name, fieldname_suffix, code_ptr);
633 } else {
634 auto &code = *code_ptr;
635 code += std::string(", ") + nameprefix;
636 if (has_field_name) { code += namer_.Field(field); }
637 code += namesuffix;
638 }
639 }
640 }
641
642 // End the creator function signature.
643 void EndBuilderArgs(std::string *code_ptr) const {
644 auto &code = *code_ptr;
645 code += "):\n";
646 }
647
648 // Recursively generate struct construction statements and instert manual
649 // padding.
650 void StructBuilderBody(const StructDef &struct_def, const char *nameprefix,
651 std::string *code_ptr, size_t index = 0,
652 bool in_array = false) const {
653 auto &code = *code_ptr;
654 std::string indent(index * 4, ' ');
655 code +=
656 indent + " builder.Prep(" + NumToString(struct_def.minalign) + ", ";
657 code += NumToString(struct_def.bytesize) + ")\n";
658 for (auto it = struct_def.fields.vec.rbegin();
659 it != struct_def.fields.vec.rend(); ++it) {
660 auto &field = **it;
661 const auto &field_type = field.value.type;
662 const auto &type =
663 IsArray(field_type) ? field_type.VectorType() : field_type;
664 if (field.padding)
665 code +=
666 indent + " builder.Pad(" + NumToString(field.padding) + ")\n";
667 if (IsStruct(field_type)) {
668 StructBuilderBody(*field_type.struct_def,
669 (nameprefix + (namer_.Field(field) + "_")).c_str(),
670 code_ptr, index, in_array);
671 } else {
672 const auto index_var = "_idx" + NumToString(index);
673 if (IsArray(field_type)) {
674 code += indent + " for " + index_var + " in range(";
675 code += NumToString(field_type.fixed_length);
676 code += " , 0, -1):\n";
677 in_array = true;
678 }
679 if (IsStruct(type)) {
680 StructBuilderBody(*field_type.struct_def,
681 (nameprefix + (namer_.Field(field) + "_")).c_str(),
682 code_ptr, index + 1, in_array);
683 } else {
684 code += IsArray(field_type) ? " " : "";
685 code += indent + " builder.Prepend" + GenMethod(field) + "(";
686 code += nameprefix + namer_.Variable(field);
687 size_t array_cnt = index + (IsArray(field_type) ? 1 : 0);
688 for (size_t i = 0; in_array && i < array_cnt; i++) {
689 code += "[_idx" + NumToString(i) + "-1]";
690 }
691 code += ")\n";
692 }
693 }
694 }
695 }
696
697 void EndBuilderBody(std::string *code_ptr) const {
698 auto &code = *code_ptr;
699 code += " return builder.Offset()\n";
700 }
701
702 // Get the value of a table's starting offset.
703 void GetStartOfTable(const StructDef &struct_def,
704 std::string *code_ptr) const {
705 auto &code = *code_ptr;
706 const auto struct_type = namer_.Type(struct_def);
707 // Generate method with struct name.
708
709 const auto name = parser_.opts.python_no_type_prefix_suffix
710 ? "Start"
711 : struct_type + "Start";
712
713 code += "def " + name;
714 if (parser_.opts.python_typing) {
715 code += "(builder: flatbuffers.Builder):\n";
716 } else {
717 code += "(builder):\n";
718 }
719
720 code += Indent + "builder.StartObject(";
721 code += NumToString(struct_def.fields.vec.size());
722 code += ")\n\n";
723
724 if (!parser_.opts.one_file && !parser_.opts.python_no_type_prefix_suffix) {
725 // Generate method without struct name.
726 if (parser_.opts.python_typing) {
727 code += "def Start(builder: flatbuffers.Builder):\n";
728 } else {
729 code += "def Start(builder):\n";
730 }
731 code += Indent + struct_type + "Start(builder)\n\n";
732 }
733 }
734
735 // Set the value of a table's field.
736 void BuildFieldOfTable(const StructDef &struct_def, const FieldDef &field,
737 const size_t offset, std::string *code_ptr) const {
738 auto &code = *code_ptr;
739 const std::string field_var = namer_.Variable(field);
740 const std::string field_method = namer_.Method(field);
741 const std::string field_ty = GenFieldTy(field);
742
743 const auto name = parser_.opts.python_no_type_prefix_suffix
744 ? "Add" + field_method
745 : namer_.Type(struct_def) + "Add" + field_method;
746
747 // Generate method with struct name.
748 code += "def " + name;
749 if (parser_.opts.python_typing) {
750 code += "(builder: flatbuffers.Builder, " + field_var + ": " + field_ty;
751 } else {
752 code += "(builder, " + field_var;
753 }
754 code += "):\n";
755 code += Indent + "builder.Prepend";
756 code += GenMethod(field) + "Slot(";
757 code += NumToString(offset) + ", ";
758 if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
759 code += "flatbuffers.number_types.UOffsetTFlags.py_type";
760 code += "(" + field_var + ")";
761 } else {
762 code += field_var;
763 }
764 code += ", ";
765 if (field.IsScalarOptional()) {
766 code += "None";
767 } else if (IsFloat(field.value.type.base_type)) {
768 code += float_const_gen_.GenFloatConstant(field);
769 } else {
770 code += field.value.constant;
771 }
772 code += ")\n\n";
773
774 if (!parser_.opts.one_file && !parser_.opts.python_no_type_prefix_suffix) {
775 // Generate method without struct name.
776 code += "def Add" + field_method;
777 if (parser_.opts.python_typing) {
778 code += "(builder: flatbuffers.Builder, " + field_var + ": " + field_ty;
779 } else {
780 code += "(builder, " + field_var;
781 }
782 code += "):\n";
783 code += Indent + namer_.Type(struct_def) + "Add" + field_method;
784 code += "(builder, ";
785 code += field_var;
786 code += ")\n\n";
787 }
788 }
789
790 // Set the value of one of the members of a table's vector.
791 void BuildVectorOfTable(const StructDef &struct_def, const FieldDef &field,
792 std::string *code_ptr) const {
793 auto &code = *code_ptr;
794 const std::string struct_type = namer_.Type(struct_def);
795 const std::string field_method = namer_.Method(field);
796
797 // Generate method with struct name.
798 const auto name = parser_.opts.python_no_type_prefix_suffix
799 ? "Start" + field_method
800 : struct_type + "Start" + field_method;
801 code += "def " + name;
802 if (parser_.opts.python_typing) {
803 code += "Vector(builder, numElems: int) -> int:\n";
804 } else {
805 code += "Vector(builder, numElems):\n";
806 }
807
808 code += Indent + "return builder.StartVector(";
809 auto vector_type = field.value.type.VectorType();
810 auto alignment = InlineAlignment(vector_type);
811 auto elem_size = InlineSize(vector_type);
812 code += NumToString(elem_size);
813 code += ", numElems, " + NumToString(alignment);
814 code += ")\n\n";
815
816 if (!parser_.opts.one_file && !parser_.opts.python_no_type_prefix_suffix) {
817 // Generate method without struct name.
818 code += "def Start" + field_method +
819 "Vector(builder, numElems: int) -> int:\n";
820 code += Indent + "return " + struct_type + "Start";
821 code += field_method + "Vector(builder, numElems)\n\n";
822 }
823 }
824
825 // Set the value of one of the members of a table's vector and fills in the
826 // elements from a bytearray. This is for simplifying the use of nested
827 // flatbuffers.
828 void BuildVectorOfTableFromBytes(const StructDef &struct_def,
829 const FieldDef &field,
830 std::string *code_ptr) const {
831 auto nested = field.attributes.Lookup("nested_flatbuffer");
832 if (!nested) { return; } // There is no nested flatbuffer.
833
834 auto &code = *code_ptr;
835 const std::string field_method = namer_.Method(field);
836 const std::string struct_type = namer_.Type(struct_def);
837
838 // Generate method with struct and field name.
839 code += "def " + struct_type + "Make" + field_method;
840 code += "VectorFromBytes(builder, bytes):\n";
841 code += Indent + "builder.StartVector(";
842 auto vector_type = field.value.type.VectorType();
843 auto alignment = InlineAlignment(vector_type);
844 auto elem_size = InlineSize(vector_type);
845 code += NumToString(elem_size);
846 code += ", len(bytes), " + NumToString(alignment);
847 code += ")\n";
848 code += Indent + "builder.head = builder.head - len(bytes)\n";
849 code += Indent + "builder.Bytes[builder.head : builder.head + len(bytes)]";
850 code += " = bytes\n";
851 code += Indent + "return builder.EndVector()\n";
852
853 if (!parser_.opts.one_file) {
854 // Generate method without struct and field name.
855 code += "def Make" + field_method + "VectorFromBytes(builder, bytes):\n";
856 code += Indent + "return " + struct_type + "Make" + field_method +
857 "VectorFromBytes(builder, bytes)\n";
858 }
859 }
860
861 // Get the offset of the end of a table.
862 void GetEndOffsetOnTable(const StructDef &struct_def,
863 std::string *code_ptr) const {
864 auto &code = *code_ptr;
865
866 const auto name = parser_.opts.python_no_type_prefix_suffix
867 ? "End"
868 : namer_.Type(struct_def) + "End";
869 // Generate method with struct name.
870 if (parser_.opts.python_typing) {
871 code += "def " + name + "(builder: flatbuffers.Builder) -> int:\n";
872 } else {
873 code += "def " + name + "(builder):\n";
874 }
875 code += Indent + "return builder.EndObject()\n\n";
876
877 if (!parser_.opts.one_file && !parser_.opts.python_no_type_prefix_suffix) {
878 // Generate method without struct name.
879 if (parser_.opts.python_typing) {
880 code += "def End(builder: flatbuffers.Builder) -> int:\n";
881 } else {
882 code += "def End(builder):\n";
883 }
884 code += Indent + "return " + namer_.Type(struct_def) + "End(builder)";
885 code += "\n";
886 }
887 }
888
889 // Generate the receiver for function signatures.
890 void GenReceiver(const StructDef &struct_def, std::string *code_ptr) const {
891 auto &code = *code_ptr;
892 code += Indent + "# " + namer_.Type(struct_def) + "\n";
893 code += Indent + "def ";
894 }
895
896 // Generate a struct field, conditioned on its child type(s).
897 void GenStructAccessor(const StructDef &struct_def, const FieldDef &field,
898 std::string *code_ptr, ImportMap &imports) const {
899 GenComment(field.doc_comment, code_ptr, &def_comment, Indent.c_str());
900 if (IsScalar(field.value.type.base_type)) {
901 if (struct_def.fixed) {
902 GetScalarFieldOfStruct(struct_def, field, code_ptr);
903 } else {
904 GetScalarFieldOfTable(struct_def, field, code_ptr);
905 }
906 } else {
907 switch (field.value.type.base_type) {
908 case BASE_TYPE_STRUCT:
909 if (struct_def.fixed) {
910 GetStructFieldOfStruct(struct_def, field, code_ptr);
911 } else {
912 GetStructFieldOfTable(struct_def, field, code_ptr, imports);
913 }
914 break;
915 case BASE_TYPE_STRING:
916 GetStringField(struct_def, field, code_ptr, imports);
917 break;
918 case BASE_TYPE_VECTOR: {
919 auto vectortype = field.value.type.VectorType();
920 if (vectortype.base_type == BASE_TYPE_STRUCT) {
921 GetMemberOfVectorOfStruct(struct_def, field, code_ptr, imports);
922 } else {
923 GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr);
924 GetVectorOfNonStructAsNumpy(struct_def, field, code_ptr);
925 GetVectorAsNestedFlatbuffer(struct_def, field, code_ptr, imports);
926 }
927 break;
928 }
929 case BASE_TYPE_ARRAY: {
930 auto vectortype = field.value.type.VectorType();
931 if (vectortype.base_type == BASE_TYPE_STRUCT) {
932 GetArrayOfStruct(struct_def, field, code_ptr, imports);
933 } else {
934 GetArrayOfNonStruct(struct_def, field, code_ptr);
935 GetVectorOfNonStructAsNumpy(struct_def, field, code_ptr);
936 GetVectorAsNestedFlatbuffer(struct_def, field, code_ptr, imports);
937 }
938 break;
939 }
940 case BASE_TYPE_UNION:
941 GetUnionField(struct_def, field, code_ptr, imports);
942 break;
943 default: FLATBUFFERS_ASSERT(0);
944 }
945 }
946 if (IsVector(field.value.type) || IsArray(field.value.type)) {
947 GetVectorLen(struct_def, field, code_ptr);
948 GetVectorIsNone(struct_def, field, code_ptr);
949 }
950 }
951
952 // Generate struct sizeof.
953 void GenStructSizeOf(const StructDef &struct_def,
954 std::string *code_ptr) const {
955 auto &code = *code_ptr;
956 code += Indent + "@classmethod\n";
957 if (parser_.opts.python_typing) {
958 code += Indent + "def SizeOf(cls) -> int:\n";
959 } else {
960 code += Indent + "def SizeOf(cls):\n";
961 }
962 code +=
963 Indent + Indent + "return " + NumToString(struct_def.bytesize) + "\n";
964 code += "\n";
965 }
966
967 // Generate table constructors, conditioned on its members' types.
968 void GenTableBuilders(const StructDef &struct_def,
969 std::string *code_ptr) const {
970 GetStartOfTable(struct_def, code_ptr);
971
972 for (auto it = struct_def.fields.vec.begin();
973 it != struct_def.fields.vec.end(); ++it) {
974 auto &field = **it;
975 if (field.deprecated) continue;
976
977 auto offset = it - struct_def.fields.vec.begin();
978 BuildFieldOfTable(struct_def, field, offset, code_ptr);
979 if (IsVector(field.value.type)) {
980 BuildVectorOfTable(struct_def, field, code_ptr);
981 BuildVectorOfTableFromBytes(struct_def, field, code_ptr);
982 }
983 }
984
985 GetEndOffsetOnTable(struct_def, code_ptr);
986 }
987
988 // Generate function to check for proper file identifier
989 void GenHasFileIdentifier(const StructDef &struct_def,
990 std::string *code_ptr) const {
991 auto &code = *code_ptr;
992 std::string escapedID;
993 // In the event any of file_identifier characters are special(NULL, \, etc),
994 // problems occur. To prevent this, convert all chars to their hex-escaped
995 // equivalent.
996 for (auto it = parser_.file_identifier_.begin();
997 it != parser_.file_identifier_.end(); ++it) {
998 escapedID += "\\x" + IntToStringHex(*it, 2);
999 }
1000
1001 code += Indent + "@classmethod\n";
1002 code += Indent + "def " + namer_.Type(struct_def);
1003 code += "BufferHasIdentifier(cls, buf, offset, size_prefixed=False):";
1004 code += "\n";
1005 code += Indent + Indent;
1006 code += "return flatbuffers.util.BufferHasIdentifier(buf, offset, b\"";
1007 code += escapedID;
1008 code += "\", size_prefixed=size_prefixed)\n";
1009 code += "\n";
1010 }
1011
1012 // Generates struct or table methods.
1013 void GenStruct(const StructDef &struct_def, std::string *code_ptr,
1014 ImportMap &imports) const {
1015 if (struct_def.generated) return;
1016
1017 GenComment(struct_def.doc_comment, code_ptr, &def_comment);
1018 BeginClass(struct_def, code_ptr);
1019 if (!struct_def.fixed) {
1020 // Generate a special accessor for the table that has been declared as
1021 // the root type.
1022 NewRootTypeFromBuffer(struct_def, code_ptr);
1023 if (parser_.file_identifier_.length()) {
1024 // Generate a special function to test file_identifier
1025 GenHasFileIdentifier(struct_def, code_ptr);
1026 }
1027 } else {
1028 // Generates the SizeOf method for all structs.
1029 GenStructSizeOf(struct_def, code_ptr);
1030 }
1031 // Generates the Init method that sets the field in a pre-existing
1032 // accessor object. This is to allow object reuse.
1033 InitializeExisting(struct_def, code_ptr);
1034 for (auto it = struct_def.fields.vec.begin();
1035 it != struct_def.fields.vec.end(); ++it) {
1036 auto &field = **it;
1037 if (field.deprecated) continue;
1038
1039 GenStructAccessor(struct_def, field, code_ptr, imports);
1040 }
1041
1042 if (struct_def.fixed) {
1043 // creates a struct constructor function
1044 GenStructBuilder(struct_def, code_ptr);
1045 } else {
1046 // Creates a set of functions that allow table construction.
1047 GenTableBuilders(struct_def, code_ptr);
1048 }
1049 }
1050
1051 void GenReceiverForObjectAPI(const StructDef &struct_def,
1052 std::string *code_ptr) const {
1053 auto &code = *code_ptr;
1054 code += GenIndents(1) + "# " + namer_.ObjectType(struct_def);
1055 code += GenIndents(1) + "def ";
1056 }
1057
1058 void BeginClassForObjectAPI(const StructDef &struct_def,
1059 std::string *code_ptr) const {
1060 auto &code = *code_ptr;
1061 code += "\n";
1062 code += "class " + namer_.ObjectType(struct_def) + "(object):";
1063 code += "\n";
1064 }
1065
1066 // Gets the accoresponding python builtin type of a BaseType for scalars and
1067 // string.
1068 std::string GetBasePythonTypeForScalarAndString(
1069 const BaseType &base_type) const {
1070 if (IsBool(base_type)) {
1071 return "bool";
1072 } else if (IsFloat(base_type)) {
1073 return "float";
1074 } else if (IsInteger(base_type)) {
1075 return "int";
1076 } else if (base_type == BASE_TYPE_STRING) {
1077 return "str";
1078 } else {
1079 FLATBUFFERS_ASSERT(false && "base_type is not a scalar or string type.");
1080 return "";
1081 }
1082 }
1083
1084 std::string GetDefaultValue(const FieldDef &field) const {
1085 BaseType base_type = field.value.type.base_type;
1086 if (field.IsScalarOptional()) {
1087 return "None";
1088 } else if (IsBool(base_type)) {
1089 return field.value.constant == "0" ? "False" : "True";
1090 } else if (IsFloat(base_type)) {
1091 return float_const_gen_.GenFloatConstant(field);
1092 } else if (IsInteger(base_type)) {
1093 return field.value.constant;
1094 } else {
1095 // For string, struct, and table.
1096 return "None";
1097 }
1098 }
1099
1100 void GenUnionInit(const FieldDef &field, std::string *field_types_ptr,
1101 std::set<std::string> *import_list,
1102 std::set<std::string> *import_typing_list) const {
1103 // Gets all possible types in the union.
1104 import_typing_list->insert("Union");
1105 auto &field_types = *field_types_ptr;
1106 field_types = "Union[";
1107
1108 std::string separator_string = ", ";
1109 auto enum_def = field.value.type.enum_def;
1110 for (auto it = enum_def->Vals().begin(); it != enum_def->Vals().end();
1111 ++it) {
1112 auto &ev = **it;
1113 // Union only supports string and table.
1114 std::string field_type;
1115 switch (ev.union_type.base_type) {
1116 case BASE_TYPE_STRUCT:
1117 field_type = namer_.ObjectType(*ev.union_type.struct_def);
1118 if (parser_.opts.include_dependence_headers) {
1119 auto package_reference = GenPackageReference(ev.union_type);
1120 field_type = package_reference + "." + field_type;
1121 import_list->insert("import " + package_reference);
1122 }
1123 break;
1124 case BASE_TYPE_STRING: field_type += "str"; break;
1125 case BASE_TYPE_NONE: field_type += "None"; break;
1126 default: break;
1127 }
1128 field_types += field_type + separator_string;
1129 }
1130
1131 // Removes the last separator_string.
1132 field_types.erase(field_types.length() - separator_string.size());
1133 field_types += "]";
1134
1135 // Gets the import lists for the union.
1136 if (parser_.opts.include_dependence_headers) {
1137 const auto package_reference = GenPackageReference(field.value.type);
1138 import_list->insert("import " + package_reference);
1139 }
1140 }
1141
1142 void GenStructInit(const FieldDef &field, std::string *out_ptr,
1143 std::set<std::string> *import_list,
1144 std::set<std::string> *import_typing_list) const {
1145 import_typing_list->insert("Optional");
1146 auto &output = *out_ptr;
1147 const Type &type = field.value.type;
1148 const std::string object_type = namer_.ObjectType(*type.struct_def);
1149 if (parser_.opts.include_dependence_headers) {
1150 auto package_reference = GenPackageReference(type);
1151 output = package_reference + "." + object_type + "]";
1152 import_list->insert("import " + package_reference);
1153 } else {
1154 output = object_type + "]";
1155 }
1156 output = "Optional[" + output;
1157 }
1158
1159 void GenVectorInit(const FieldDef &field, std::string *field_type_ptr,
1160 std::set<std::string> *import_list,
1161 std::set<std::string> *import_typing_list) const {
1162 import_typing_list->insert("List");
1163 auto &field_type = *field_type_ptr;
1164 const Type &vector_type = field.value.type.VectorType();
1165 const BaseType base_type = vector_type.base_type;
1166 if (base_type == BASE_TYPE_STRUCT) {
1167 const std::string object_type =
1168 namer_.ObjectType(*vector_type.struct_def);
1169 field_type = object_type + "]";
1170 if (parser_.opts.include_dependence_headers) {
1171 auto package_reference = GenPackageReference(vector_type);
1172 field_type = package_reference + "." + object_type + "]";
1173 import_list->insert("import " + package_reference);
1174 }
1175 field_type = "List[" + field_type;
1176 } else {
1177 field_type =
1178 "List[" + GetBasePythonTypeForScalarAndString(base_type) + "]";
1179 }
1180 }
1181
1182 void GenInitialize(const StructDef &struct_def, std::string *code_ptr,
1183 std::set<std::string> *import_list) const {
1184 std::string code;
1185 std::set<std::string> import_typing_list;
1186 for (auto it = struct_def.fields.vec.begin();
1187 it != struct_def.fields.vec.end(); ++it) {
1188 auto &field = **it;
1189 if (field.deprecated) continue;
1190
1191 // Determines field type, default value, and typing imports.
1192 auto base_type = field.value.type.base_type;
1193 std::string field_type;
1194 switch (base_type) {
1195 case BASE_TYPE_UNION: {
1196 GenUnionInit(field, &field_type, import_list, &import_typing_list);
1197 break;
1198 }
1199 case BASE_TYPE_STRUCT: {
1200 GenStructInit(field, &field_type, import_list, &import_typing_list);
1201 break;
1202 }
1203 case BASE_TYPE_VECTOR:
1204 case BASE_TYPE_ARRAY: {
1205 GenVectorInit(field, &field_type, import_list, &import_typing_list);
1206 break;
1207 }
1208 default:
1209 // Scalar or sting fields.
1210 field_type = GetBasePythonTypeForScalarAndString(base_type);
1211 if (field.IsScalarOptional()) {
1212 field_type = "Optional[" + field_type + "]";
1213 }
1214 break;
1215 }
1216
1217 const auto default_value = GetDefaultValue(field);
1218 // Wrties the init statement.
1219 const auto field_field = namer_.Field(field);
1220 code += GenIndents(2) + "self." + field_field + " = " + default_value +
1221 " # type: " + field_type;
1222 }
1223
1224 // Writes __init__ method.
1225 auto &code_base = *code_ptr;
1226 GenReceiverForObjectAPI(struct_def, code_ptr);
1227 code_base += "__init__(self):";
1228 if (code.empty()) {
1229 code_base += GenIndents(2) + "pass";
1230 } else {
1231 code_base += code;
1232 }
1233 code_base += "\n";
1234
1235 // Merges the typing imports into import_list.
1236 if (!import_typing_list.empty()) {
1237 // Adds the try statement.
1238 std::string typing_imports = "try:";
1239 typing_imports += GenIndents(1) + "from typing import ";
1240 std::string separator_string = ", ";
1241 for (auto it = import_typing_list.begin(); it != import_typing_list.end();
1242 ++it) {
1243 const std::string &im = *it;
1244 typing_imports += im + separator_string;
1245 }
1246 // Removes the last separator_string.
1247 typing_imports.erase(typing_imports.length() - separator_string.size());
1248
1249 // Adds the except statement.
1250 typing_imports += "\n";
1251 typing_imports += "except:";
1252 typing_imports += GenIndents(1) + "pass";
1253 import_list->insert(typing_imports);
1254 }
1255
1256 // Removes the import of the struct itself, if applied.
1257 auto struct_import = "import " + namer_.NamespacedType(struct_def);
1258 import_list->erase(struct_import);
1259 }
1260
1261 void InitializeFromBuf(const StructDef &struct_def,
1262 std::string *code_ptr) const {
1263 auto &code = *code_ptr;
1264 const auto struct_var = namer_.Variable(struct_def);
1265 const auto struct_type = namer_.Type(struct_def);
1266
1267 code += GenIndents(1) + "@classmethod";
1268 code += GenIndents(1) + "def InitFromBuf(cls, buf, pos):";
1269 code += GenIndents(2) + struct_var + " = " + struct_type + "()";
1270 code += GenIndents(2) + struct_var + ".Init(buf, pos)";
1271 code += GenIndents(2) + "return cls.InitFromObj(" + struct_var + ")";
1272 code += "\n";
1273 }
1274
1275 void InitializeFromPackedBuf(const StructDef &struct_def,
1276 std::string *code_ptr) const {
1277 auto &code = *code_ptr;
1278 const auto struct_var = namer_.Variable(struct_def);
1279 const auto struct_type = namer_.Type(struct_def);
1280
1281 code += GenIndents(1) + "@classmethod";
1282 code += GenIndents(1) + "def InitFromPackedBuf(cls, buf, pos=0):";
1283 code += GenIndents(2) +
1284 "n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, pos)";
1285 code += GenIndents(2) + "return cls.InitFromBuf(buf, pos+n)";
1286 code += "\n";
1287 }
1288
1289 void InitializeFromObjForObject(const StructDef &struct_def,
1290 std::string *code_ptr) const {
1291 auto &code = *code_ptr;
1292 const auto struct_var = namer_.Variable(struct_def);
1293 const auto struct_object = namer_.ObjectType(struct_def);
1294
1295 code += GenIndents(1) + "@classmethod";
1296 code += GenIndents(1) + "def InitFromObj(cls, " + struct_var + "):";
1297 code += GenIndents(2) + "x = " + struct_object + "()";
1298 code += GenIndents(2) + "x._UnPack(" + struct_var + ")";
1299 code += GenIndents(2) + "return x";
1300 code += "\n";
1301 }
1302
1303 void GenCompareOperator(const StructDef &struct_def,
1304 std::string *code_ptr) const {
1305 auto &code = *code_ptr;
1306 code += GenIndents(1) + "def __eq__(self, other):";
1307 code += GenIndents(2) + "return type(self) == type(other)";
1308 for (auto it = struct_def.fields.vec.begin();
1309 it != struct_def.fields.vec.end(); ++it) {
1310 auto &field = **it;
1311 if (field.deprecated) continue;
1312
1313 // Wrties the comparison statement for this field.
1314 const auto field_field = namer_.Field(field);
1315 code += " and \\" + GenIndents(3) + "self." + field_field +
1316 " == " + "other." + field_field;
1317 }
1318 code += "\n";
1319 }
1320
1321 void GenUnPackForStruct(const StructDef &struct_def, const FieldDef &field,
1322 std::string *code_ptr) const {
1323 auto &code = *code_ptr;
1324 const auto struct_var = namer_.Variable(struct_def);
1325 const auto field_field = namer_.Field(field);
1326 const auto field_method = namer_.Method(field);
1327 auto field_type = TypeName(field);
1328
1329 if (parser_.opts.include_dependence_headers) {
1330 auto package_reference = GenPackageReference(field.value.type);
1331 field_type = package_reference + "." + TypeName(field);
1332 }
1333
1334 code += GenIndents(2) + "if " + struct_var + "." + field_method + "(";
1335 // if field is a struct, we need to create an instance for it first.
1336 if (struct_def.fixed && field.value.type.base_type == BASE_TYPE_STRUCT) {
1337 code += field_type + "()";
1338 }
1339 code += ") is not None:";
1340 code += GenIndents(3) + "self." + field_field + " = " +
1341 namer_.ObjectType(field_type) + +".InitFromObj(" + struct_var +
1342 "." + field_method + "(";
1343 // A struct's accessor requires a struct buf instance.
1344 if (struct_def.fixed && field.value.type.base_type == BASE_TYPE_STRUCT) {
1345 code += field_type + "()";
1346 }
1347 code += "))";
1348 }
1349
1350 void GenUnPackForUnion(const StructDef &struct_def, const FieldDef &field,
1351 std::string *code_ptr) const {
1352 auto &code = *code_ptr;
1353 const auto field_field = namer_.Field(field);
1354 const auto field_method = namer_.Method(field);
1355 const auto struct_var = namer_.Variable(struct_def);
1356 const EnumDef &enum_def = *field.value.type.enum_def;
1357 auto union_type = namer_.Type(enum_def);
1358
1359 if (parser_.opts.include_dependence_headers) {
1360 union_type = namer_.NamespacedType(enum_def) + "." + union_type;
1361 }
1362 code += GenIndents(2) + "self." + field_field + " = " + union_type +
1363 "Creator(" + "self." + field_field + "Type, " + struct_var + "." +
1364 field_method + "())";
1365 }
1366
1367 void GenUnPackForStructVector(const StructDef &struct_def,
1368 const FieldDef &field,
1369 std::string *code_ptr) const {
1370 auto &code = *code_ptr;
1371 const auto field_field = namer_.Field(field);
1372 const auto field_method = namer_.Method(field);
1373 const auto struct_var = namer_.Variable(struct_def);
1374
1375 code += GenIndents(2) + "if not " + struct_var + "." + field_method +
1376 "IsNone():";
1377 code += GenIndents(3) + "self." + field_field + " = []";
1378 code += GenIndents(3) + "for i in range(" + struct_var + "." +
1379 field_method + "Length()):";
1380
1381 auto field_type = TypeName(field);
1382 auto one_instance = field_type + "_";
1383 one_instance[0] = CharToLower(one_instance[0]);
1384 if (parser_.opts.include_dependence_headers) {
1385 auto package_reference = GenPackageReference(field.value.type);
1386 field_type = package_reference + "." + TypeName(field);
1387 }
1388 code += GenIndents(4) + "if " + struct_var + "." + field_method +
1389 "(i) is None:";
1390 code += GenIndents(5) + "self." + field_field + ".append(None)";
1391 code += GenIndents(4) + "else:";
1392 code += GenIndents(5) + one_instance + " = " +
1393 namer_.ObjectType(field_type) + ".InitFromObj(" + struct_var + "." +
1394 field_method + "(i))";
1395 code +=
1396 GenIndents(5) + "self." + field_field + ".append(" + one_instance + ")";
1397 }
1398
1399 void GenUnpackForTableVector(const StructDef &struct_def,
1400 const FieldDef &field,
1401 std::string *code_ptr) const {
1402 auto &code = *code_ptr;
1403 const auto field_field = namer_.Field(field);
1404 const auto field_method = namer_.Method(field);
1405 const auto struct_var = namer_.Variable(struct_def);
1406
1407 code += GenIndents(2) + "if not " + struct_var + "." + field_method +
1408 "IsNone():";
1409 code += GenIndents(3) + "self." + field_field + " = []";
1410 code += GenIndents(3) + "for i in range(" + struct_var + "." +
1411 field_method + "Length()):";
1412
1413 auto field_type = TypeName(field);
1414 auto one_instance = field_type + "_";
1415 one_instance[0] = CharToLower(one_instance[0]);
1416 if (parser_.opts.include_dependence_headers) {
1417 auto package_reference = GenPackageReference(field.value.type);
1418 field_type = package_reference + "." + TypeName(field);
1419 }
1420 code += GenIndents(4) + "if " + struct_var + "." + field_method +
1421 "(i) is None:";
1422 code += GenIndents(5) + "self." + field_field + ".append(None)";
1423 code += GenIndents(4) + "else:";
1424 code += GenIndents(5) + one_instance + " = " +
1425 namer_.ObjectType(field_type) + ".InitFromObj(" + struct_var + "." +
1426 field_method + "(i))";
1427 code +=
1428 GenIndents(5) + "self." + field_field + ".append(" + one_instance + ")";
1429 }
1430
1431 void GenUnpackforScalarVectorHelper(const StructDef &struct_def,
1432 const FieldDef &field,
1433 std::string *code_ptr,
1434 int indents) const {
1435 auto &code = *code_ptr;
1436 const auto field_field = namer_.Field(field);
1437 const auto field_method = namer_.Method(field);
1438 const auto struct_var = namer_.Variable(struct_def);
1439
1440 code += GenIndents(indents) + "self." + field_field + " = []";
1441 code += GenIndents(indents) + "for i in range(" + struct_var + "." +
1442 field_method + "Length()):";
1443 code += GenIndents(indents + 1) + "self." + field_field + ".append(" +
1444 struct_var + "." + field_method + "(i))";
1445 }
1446
1447 void GenUnPackForScalarVector(const StructDef &struct_def,
1448 const FieldDef &field,
1449 std::string *code_ptr) const {
1450 auto &code = *code_ptr;
1451 const auto field_field = namer_.Field(field);
1452 const auto field_method = namer_.Method(field);
1453 const auto struct_var = namer_.Variable(struct_def);
1454
1455 code += GenIndents(2) + "if not " + struct_var + "." + field_method +
1456 "IsNone():";
1457
1458 // String does not have the AsNumpy method.
1459 if (!(IsScalar(field.value.type.VectorType().base_type))) {
1460 GenUnpackforScalarVectorHelper(struct_def, field, code_ptr, 3);
1461 return;
1462 }
1463
1464 code += GenIndents(3) + "if np is None:";
1465 GenUnpackforScalarVectorHelper(struct_def, field, code_ptr, 4);
1466
1467 // If numpy exists, use the AsNumpy method to optimize the unpack speed.
1468 code += GenIndents(3) + "else:";
1469 code += GenIndents(4) + "self." + field_field + " = " + struct_var + "." +
1470 field_method + "AsNumpy()";
1471 }
1472
1473 void GenUnPackForScalar(const StructDef &struct_def, const FieldDef &field,
1474 std::string *code_ptr) const {
1475 auto &code = *code_ptr;
1476 const auto field_field = namer_.Field(field);
1477 const auto field_method = namer_.Method(field);
1478 const auto struct_var = namer_.Variable(struct_def);
1479
1480 code += GenIndents(2) + "self." + field_field + " = " + struct_var + "." +
1481 field_method + "()";
1482 }
1483
1484 // Generates the UnPack method for the object class.
1485 void GenUnPack(const StructDef &struct_def, std::string *code_ptr) const {
1486 std::string code;
1487 // Items that needs to be imported. No duplicate modules will be imported.
1488 std::set<std::string> import_list;
1489
1490 for (auto it = struct_def.fields.vec.begin();
1491 it != struct_def.fields.vec.end(); ++it) {
1492 auto &field = **it;
1493 if (field.deprecated) continue;
1494
1495 auto field_type = TypeName(field);
1496 switch (field.value.type.base_type) {
1497 case BASE_TYPE_STRUCT: {
1498 GenUnPackForStruct(struct_def, field, &code);
1499 break;
1500 }
1501 case BASE_TYPE_UNION: {
1502 GenUnPackForUnion(struct_def, field, &code);
1503 break;
1504 }
1505 case BASE_TYPE_ARRAY:
1506 case BASE_TYPE_VECTOR: {
1507 auto vectortype = field.value.type.VectorType();
1508 if (vectortype.base_type == BASE_TYPE_STRUCT) {
1509 GenUnPackForStructVector(struct_def, field, &code);
1510 } else {
1511 GenUnPackForScalarVector(struct_def, field, &code);
1512 }
1513 break;
1514 }
1515 default: GenUnPackForScalar(struct_def, field, &code);
1516 }
1517 }
1518
1519 // Writes import statements and code into the generated file.
1520 auto &code_base = *code_ptr;
1521 const auto struct_var = namer_.Variable(struct_def);
1522
1523 GenReceiverForObjectAPI(struct_def, code_ptr);
1524 code_base += "_UnPack(self, " + struct_var + "):";
1525 code_base += GenIndents(2) + "if " + struct_var + " is None:";
1526 code_base += GenIndents(3) + "return";
1527
1528 // Write the import statements.
1529 for (std::set<std::string>::iterator it = import_list.begin();
1530 it != import_list.end(); ++it) {
1531 code_base += GenIndents(2) + *it;
1532 }
1533
1534 // Write the code.
1535 code_base += code;
1536 code_base += "\n";
1537 }
1538
1539 void GenPackForStruct(const StructDef &struct_def,
1540 std::string *code_ptr) const {
1541 auto &code = *code_ptr;
1542 const auto struct_fn = namer_.Function(struct_def);
1543
1544 GenReceiverForObjectAPI(struct_def, code_ptr);
1545 code += "Pack(self, builder):";
1546 code += GenIndents(2) + "return Create" + struct_fn + "(builder";
1547
1548 StructBuilderArgs(struct_def,
1549 /* nameprefix = */ "self.",
1550 /* namesuffix = */ "",
1551 /* has_field_name = */ true,
1552 /* fieldname_suffix = */ ".", code_ptr);
1553 code += ")\n";
1554 }
1555
1556 void GenPackForStructVectorField(const StructDef &struct_def,
1557 const FieldDef &field,
1558 std::string *code_prefix_ptr,
1559 std::string *code_ptr) const {
1560 auto &code_prefix = *code_prefix_ptr;
1561 auto &code = *code_ptr;
1562 const auto field_field = namer_.Field(field);
1563 const auto struct_type = namer_.Type(struct_def);
1564 const auto field_method = namer_.Method(field);
1565
1566 // Creates the field.
1567 code_prefix += GenIndents(2) + "if self." + field_field + " is not None:";
1568 if (field.value.type.struct_def->fixed) {
1569 code_prefix += GenIndents(3) + struct_type + "Start" + field_method +
1570 "Vector(builder, len(self." + field_field + "))";
1571 code_prefix += GenIndents(3) + "for i in reversed(range(len(self." +
1572 field_field + "))):";
1573 code_prefix +=
1574 GenIndents(4) + "self." + field_field + "[i].Pack(builder)";
1575 code_prefix += GenIndents(3) + field_field + " = builder.EndVector()";
1576 } else {
1577 // If the vector is a struct vector, we need to first build accessor for
1578 // each struct element.
1579 code_prefix += GenIndents(3) + field_field + "list = []";
1580 code_prefix += GenIndents(3);
1581 code_prefix += "for i in range(len(self." + field_field + ")):";
1582 code_prefix += GenIndents(4) + field_field + "list.append(self." +
1583 field_field + "[i].Pack(builder))";
1584
1585 code_prefix += GenIndents(3) + struct_type + "Start" + field_method +
1586 "Vector(builder, len(self." + field_field + "))";
1587 code_prefix += GenIndents(3) + "for i in reversed(range(len(self." +
1588 field_field + "))):";
1589 code_prefix += GenIndents(4) + "builder.PrependUOffsetTRelative" + "(" +
1590 field_field + "list[i])";
1591 code_prefix += GenIndents(3) + field_field + " = builder.EndVector()";
1592 }
1593
1594 // Adds the field into the struct.
1595 code += GenIndents(2) + "if self." + field_field + " is not None:";
1596 code += GenIndents(3) + struct_type + "Add" + field_method + "(builder, " +
1597 field_field + ")";
1598 }
1599
1600 void GenPackForScalarVectorFieldHelper(const StructDef &struct_def,
1601 const FieldDef &field,
1602 std::string *code_ptr,
1603 int indents) const {
1604 auto &code = *code_ptr;
1605 const auto field_field = namer_.Field(field);
1606 const auto field_method = namer_.Method(field);
1607 const auto struct_type = namer_.Type(struct_def);
1608 const auto vectortype = field.value.type.VectorType();
1609
1610 code += GenIndents(indents) + struct_type + "Start" + field_method +
1611 "Vector(builder, len(self." + field_field + "))";
1612 code += GenIndents(indents) + "for i in reversed(range(len(self." +
1613 field_field + "))):";
1614 code += GenIndents(indents + 1) + "builder.Prepend";
1615
1616 std::string type_name;
1617 switch (vectortype.base_type) {
1618 case BASE_TYPE_BOOL: type_name = "Bool"; break;
1619 case BASE_TYPE_CHAR: type_name = "Byte"; break;
1620 case BASE_TYPE_UCHAR: type_name = "Uint8"; break;
1621 case BASE_TYPE_SHORT: type_name = "Int16"; break;
1622 case BASE_TYPE_USHORT: type_name = "Uint16"; break;
1623 case BASE_TYPE_INT: type_name = "Int32"; break;
1624 case BASE_TYPE_UINT: type_name = "Uint32"; break;
1625 case BASE_TYPE_LONG: type_name = "Int64"; break;
1626 case BASE_TYPE_ULONG: type_name = "Uint64"; break;
1627 case BASE_TYPE_FLOAT: type_name = "Float32"; break;
1628 case BASE_TYPE_DOUBLE: type_name = "Float64"; break;
1629 case BASE_TYPE_STRING: type_name = "UOffsetTRelative"; break;
1630 default: type_name = "VOffsetT"; break;
1631 }
1632 code += type_name;
1633 }
1634
1635 void GenPackForScalarVectorField(const StructDef &struct_def,
1636 const FieldDef &field,
1637 std::string *code_prefix_ptr,
1638 std::string *code_ptr) const {
1639 auto &code = *code_ptr;
1640 auto &code_prefix = *code_prefix_ptr;
1641 const auto field_field = namer_.Field(field);
1642 const auto field_method = namer_.Method(field);
1643 const auto struct_type = namer_.Type(struct_def);
1644
1645 // Adds the field into the struct.
1646 code += GenIndents(2) + "if self." + field_field + " is not None:";
1647 code += GenIndents(3) + struct_type + "Add" + field_method + "(builder, " +
1648 field_field + ")";
1649
1650 // Creates the field.
1651 code_prefix += GenIndents(2) + "if self." + field_field + " is not None:";
1652 // If the vector is a string vector, we need to first build accessor for
1653 // each string element. And this generated code, needs to be
1654 // placed ahead of code_prefix.
1655 auto vectortype = field.value.type.VectorType();
1656 if (IsString(vectortype)) {
1657 code_prefix += GenIndents(3) + field_field + "list = []";
1658 code_prefix +=
1659 GenIndents(3) + "for i in range(len(self." + field_field + ")):";
1660 code_prefix += GenIndents(4) + field_field +
1661 "list.append(builder.CreateString(self." + field_field +
1662 "[i]))";
1663 GenPackForScalarVectorFieldHelper(struct_def, field, code_prefix_ptr, 3);
1664 code_prefix += "(" + field_field + "list[i])";
1665 code_prefix += GenIndents(3) + field_field + " = builder.EndVector()";
1666 return;
1667 }
1668
1669 code_prefix += GenIndents(3) + "if np is not None and type(self." +
1670 field_field + ") is np.ndarray:";
1671 code_prefix += GenIndents(4) + field_field +
1672 " = builder.CreateNumpyVector(self." + field_field + ")";
1673 code_prefix += GenIndents(3) + "else:";
1674 GenPackForScalarVectorFieldHelper(struct_def, field, code_prefix_ptr, 4);
1675 code_prefix += "(self." + field_field + "[i])";
1676 code_prefix += GenIndents(4) + field_field + " = builder.EndVector()";
1677 }
1678
1679 void GenPackForStructField(const StructDef &struct_def, const FieldDef &field,
1680 std::string *code_prefix_ptr,
1681 std::string *code_ptr) const {
1682 auto &code_prefix = *code_prefix_ptr;
1683 auto &code = *code_ptr;
1684 const auto field_field = namer_.Field(field);
1685 const auto field_method = namer_.Method(field);
1686 const auto struct_type = namer_.Type(struct_def);
1687
1688 if (field.value.type.struct_def->fixed) {
1689 // Pure struct fields need to be created along with their parent
1690 // structs.
1691 code += GenIndents(2) + "if self." + field_field + " is not None:";
1692 code += GenIndents(3) + field_field + " = self." + field_field +
1693 ".Pack(builder)";
1694 } else {
1695 // Tables need to be created before their parent structs are created.
1696 code_prefix += GenIndents(2) + "if self." + field_field + " is not None:";
1697 code_prefix += GenIndents(3) + field_field + " = self." + field_field +
1698 ".Pack(builder)";
1699 code += GenIndents(2) + "if self." + field_field + " is not None:";
1700 }
1701
1702 code += GenIndents(3) + struct_type + "Add" + field_method + "(builder, " +
1703 field_field + ")";
1704 }
1705
1706 void GenPackForUnionField(const StructDef &struct_def, const FieldDef &field,
1707 std::string *code_prefix_ptr,
1708 std::string *code_ptr) const {
1709 auto &code_prefix = *code_prefix_ptr;
1710 auto &code = *code_ptr;
1711 const auto field_field = namer_.Field(field);
1712 const auto field_method = namer_.Method(field);
1713 const auto struct_type = namer_.Type(struct_def);
1714
1715 // TODO(luwa): TypeT should be moved under the None check as well.
1716 code_prefix += GenIndents(2) + "if self." + field_field + " is not None:";
1717 code_prefix += GenIndents(3) + field_field + " = self." + field_field +
1718 ".Pack(builder)";
1719 code += GenIndents(2) + "if self." + field_field + " is not None:";
1720 code += GenIndents(3) + struct_type + "Add" + field_method + "(builder, " +
1721 field_field + ")";
1722 }
1723
1724 void GenPackForTable(const StructDef &struct_def,
1725 std::string *code_ptr) const {
1726 auto &code_base = *code_ptr;
1727 std::string code, code_prefix;
1728 const auto struct_var = namer_.Variable(struct_def);
1729 const auto struct_type = namer_.Type(struct_def);
1730
1731 GenReceiverForObjectAPI(struct_def, code_ptr);
1732 code_base += "Pack(self, builder):";
1733 code += GenIndents(2) + struct_type + "Start(builder)";
1734 for (auto it = struct_def.fields.vec.begin();
1735 it != struct_def.fields.vec.end(); ++it) {
1736 auto &field = **it;
1737 if (field.deprecated) continue;
1738
1739 const auto field_method = namer_.Method(field);
1740 const auto field_field = namer_.Field(field);
1741
1742 switch (field.value.type.base_type) {
1743 case BASE_TYPE_STRUCT: {
1744 GenPackForStructField(struct_def, field, &code_prefix, &code);
1745 break;
1746 }
1747 case BASE_TYPE_UNION: {
1748 GenPackForUnionField(struct_def, field, &code_prefix, &code);
1749 break;
1750 }
1751 case BASE_TYPE_ARRAY:
1752 case BASE_TYPE_VECTOR: {
1753 auto vectortype = field.value.type.VectorType();
1754 if (vectortype.base_type == BASE_TYPE_STRUCT) {
1755 GenPackForStructVectorField(struct_def, field, &code_prefix, &code);
1756 } else {
1757 GenPackForScalarVectorField(struct_def, field, &code_prefix, &code);
1758 }
1759 break;
1760 }
1761 case BASE_TYPE_STRING: {
1762 code_prefix +=
1763 GenIndents(2) + "if self." + field_field + " is not None:";
1764 code_prefix += GenIndents(3) + field_field +
1765 " = builder.CreateString(self." + field_field + ")";
1766 code += GenIndents(2) + "if self." + field_field + " is not None:";
1767 code += GenIndents(3) + struct_type + "Add" + field_method +
1768 "(builder, " + field_field + ")";
1769 break;
1770 }
1771 default:
1772 // Generates code for scalar values. If the value equals to the
1773 // default value, builder will automatically ignore it. So we don't
1774 // need to check the value ahead.
1775 code += GenIndents(2) + struct_type + "Add" + field_method +
1776 "(builder, self." + field_field + ")";
1777 break;
1778 }
1779 }
1780
1781 code += GenIndents(2) + struct_var + " = " + struct_type + "End(builder)";
1782 code += GenIndents(2) + "return " + struct_var;
1783
1784 code_base += code_prefix + code;
1785 code_base += "\n";
1786 }
1787
1788 void GenStructForObjectAPI(const StructDef &struct_def,
1789 std::string *code_ptr) const {
1790 if (struct_def.generated) return;
1791
1792 std::set<std::string> import_list;
1793 std::string code;
1794
1795 // Creates an object class for a struct or a table
1796 BeginClassForObjectAPI(struct_def, &code);
1797
1798 GenInitialize(struct_def, &code, &import_list);
1799
1800 InitializeFromBuf(struct_def, &code);
1801
1802 InitializeFromPackedBuf(struct_def, &code);
1803
1804 InitializeFromObjForObject(struct_def, &code);
1805
1806 if (parser_.opts.gen_compare) { GenCompareOperator(struct_def, &code); }
1807
1808 GenUnPack(struct_def, &code);
1809
1810 if (struct_def.fixed) {
1811 GenPackForStruct(struct_def, &code);
1812 } else {
1813 GenPackForTable(struct_def, &code);
1814 }
1815
1816 // Adds the imports at top.
1817 auto &code_base = *code_ptr;
1818 code_base += "\n";
1819 for (auto it = import_list.begin(); it != import_list.end(); it++) {
1820 auto im = *it;
1821 code_base += im + "\n";
1822 }
1823 code_base += code;
1824 }
1825
1826 void GenUnionCreatorForStruct(const EnumDef &enum_def, const EnumVal &ev,
1827 std::string *code_ptr) const {
1828 auto &code = *code_ptr;
1829 const auto union_type = namer_.Type(enum_def);
1830 const auto variant = namer_.Variant(ev);
1831 auto field_type = namer_.ObjectType(*ev.union_type.struct_def);
1832
1833 code +=
1834 GenIndents(1) + "if unionType == " + union_type + "()." + variant + ":";
1835 if (parser_.opts.include_dependence_headers) {
1836 auto package_reference = GenPackageReference(ev.union_type);
1837 code += GenIndents(2) + "import " + package_reference;
1838 field_type = package_reference + "." + field_type;
1839 }
1840 code += GenIndents(2) + "return " + field_type +
1841 ".InitFromBuf(table.Bytes, table.Pos)";
1842 }
1843
1844 void GenUnionCreatorForString(const EnumDef &enum_def, const EnumVal &ev,
1845 std::string *code_ptr) const {
1846 auto &code = *code_ptr;
1847 const auto union_type = namer_.Type(enum_def);
1848 const auto variant = namer_.Variant(ev);
1849
1850 code +=
1851 GenIndents(1) + "if unionType == " + union_type + "()." + variant + ":";
1852 code += GenIndents(2) + "tab = Table(table.Bytes, table.Pos)";
1853 code += GenIndents(2) + "union = tab.String(table.Pos)";
1854 code += GenIndents(2) + "return union";
1855 }
1856
1857 // Creates an union object based on union type.
1858 void GenUnionCreator(const EnumDef &enum_def, std::string *code_ptr) const {
1859 if (enum_def.generated) return;
1860
1861 auto &code = *code_ptr;
1862 const auto enum_fn = namer_.Function(enum_def);
1863
1864 code += "\n";
1865 code += "def " + enum_fn + "Creator(unionType, table):";
1866 code += GenIndents(1) + "from flatbuffers.table import Table";
1867 code += GenIndents(1) + "if not isinstance(table, Table):";
1868 code += GenIndents(2) + "return None";
1869
1870 for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
1871 auto &ev = **it;
1872 // Union only supports string and table.
1873 switch (ev.union_type.base_type) {
1874 case BASE_TYPE_STRUCT:
1875 GenUnionCreatorForStruct(enum_def, ev, &code);
1876 break;
1877 case BASE_TYPE_STRING:
1878 GenUnionCreatorForString(enum_def, ev, &code);
1879 break;
1880 default: break;
1881 }
1882 }
1883 code += GenIndents(1) + "return None";
1884 code += "\n";
1885 }
1886
1887 // Generate enum declarations.
1888 void GenEnum(const EnumDef &enum_def, std::string *code_ptr) const {
1889 if (enum_def.generated) return;
1890
1891 GenComment(enum_def.doc_comment, code_ptr, &def_comment);
1892 BeginEnum(enum_def, code_ptr);
1893 for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
1894 auto &ev = **it;
1895 GenComment(ev.doc_comment, code_ptr, &def_comment, Indent.c_str());
1896 EnumMember(enum_def, ev, code_ptr);
1897 }
1898 }
1899
1900 // Returns the function name that is able to read a value of the given type.
1901 std::string GenGetter(const Type &type) const {
1902 switch (type.base_type) {
1903 case BASE_TYPE_STRING: return "self._tab.String(";
1904 case BASE_TYPE_UNION: return "self._tab.Union(";
1905 case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
1906 default:
1907 return "self._tab.Get(flatbuffers.number_types." +
1908 namer_.Method(GenTypeGet(type)) + "Flags, ";
1909 }
1910 }
1911
1912 std::string GenFieldTy(const FieldDef &field) const {
1913 if (IsScalar(field.value.type.base_type) || IsArray(field.value.type)) {
1914 const std::string ty = GenTypeBasic(field.value.type);
1915 if (ty.find("int") != std::string::npos) { return "int"; }
1916
1917 if (ty.find("float") != std::string::npos) { return "float"; }
1918
1919 if (ty == "bool") { return "bool"; }
1920
1921 return "Any";
1922 } else {
1923 if (IsStruct(field.value.type)) {
1924 return "Any";
1925 } else {
1926 return "int";
1927 }
1928 }
1929 }
1930
1931 // Returns the method name for use with add/put calls.
1932 std::string GenMethod(const FieldDef &field) const {
1933 return (IsScalar(field.value.type.base_type) || IsArray(field.value.type))
1934 ? namer_.Method(GenTypeBasic(field.value.type))
1935 : (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative");
1936 }
1937
1938 std::string GenTypeBasic(const Type &type) const {
1939 // clang-format off
1940 static const char *ctypename[] = {
1941 #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
1942 CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, ...) \
1943 #PTYPE,
1944 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
1945 #undef FLATBUFFERS_TD
1946 };
1947 // clang-format on
1948 return ctypename[IsArray(type) ? type.VectorType().base_type
1949 : type.base_type];
1950 }
1951
1952 std::string GenTypePointer(const Type &type) const {
1953 switch (type.base_type) {
1954 case BASE_TYPE_STRING: return "string";
1955 case BASE_TYPE_VECTOR:
1956 // fall through
1957 case BASE_TYPE_ARRAY: return GenTypeGet(type.VectorType());
1958 case BASE_TYPE_STRUCT: return type.struct_def->name;
1959 case BASE_TYPE_UNION:
1960 // fall through
1961 default: return "*flatbuffers.Table";
1962 }
1963 }
1964
1965 std::string GenTypeGet(const Type &type) const {
1966 return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
1967 }
1968
1969 std::string TypeName(const FieldDef &field) const {
1970 return GenTypeGet(field.value.type);
1971 }
1972
1973 std::string ReturnType(const StructDef &struct_def,
1974 const FieldDef &field) const {
1975 // If we have a class member that returns an instance of the same class,
1976 // for example:
1977 // class Field(object):
1978 // def Children(self, j: int) -> Optional[Field]:
1979 // pass
1980 //
1981 // we need to quote the return type:
1982 // class Field(object):
1983 // def Children(self, j: int) -> Optional['Field']:
1984 // pass
1985 //
1986 // because Python is unable to resolve the name during parse and will return
1987 // an error.
1988 // (see PEP 484 under forward references:
1989 // https://peps.python.org/pep-0484/#forward-references)
1990 const std::string self_type = struct_def.name;
1991 std::string field_type = TypeName(field);
1992
1993 if (self_type == field_type) { field_type = "'" + field_type + "'"; }
1994
1995 return field_type;
1996 }
1997
1998 // Create a struct with a builder and the struct's arguments.
1999 void GenStructBuilder(const StructDef &struct_def,
2000 std::string *code_ptr) const {
2001 BeginBuilderArgs(struct_def, code_ptr);
2002 StructBuilderArgs(struct_def,
2003 /* nameprefix = */ "",
2004 /* namesuffix = */ "",
2005 /* has_field_name = */ true,
2006 /* fieldname_suffix = */ "_", code_ptr);
2007 EndBuilderArgs(code_ptr);
2008
2009 StructBuilderBody(struct_def, "", code_ptr);
2010 EndBuilderBody(code_ptr);
2011 }
2012
2013 bool generate() {
2014 std::string one_file_code;
2015 ImportMap one_file_imports;
2016 if (!generateEnums(&one_file_code)) return false;
2017 if (!generateStructs(&one_file_code, one_file_imports)) return false;
2018
2019 if (parser_.opts.one_file) {
2020 const std::string mod = file_name_ + "_generated";
2021
2022 // Legacy file format uses keep casing.
2023 return SaveType(mod + ".py", *parser_.current_namespace_, one_file_code,
2024 one_file_imports, mod, true);
2025 }
2026
2027 return true;
2028 }
2029
2030 private:
2031 bool generateEnums(std::string *one_file_code) const {
2032 for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
2033 ++it) {
2034 auto &enum_def = **it;
2035 std::string enumcode;
2036 GenEnum(enum_def, &enumcode);
2037 if (parser_.opts.generate_object_based_api & enum_def.is_union) {
2038 GenUnionCreator(enum_def, &enumcode);
2039 }
2040
2041 if (parser_.opts.one_file && !enumcode.empty()) {
2042 *one_file_code += enumcode + "\n\n";
2043 } else {
2044 ImportMap imports;
2045 const std::string mod =
2046 namer_.File(enum_def, SkipFile::SuffixAndExtension);
2047
2048 if (!SaveType(namer_.File(enum_def, SkipFile::Suffix),
2049 *enum_def.defined_namespace, enumcode, imports, mod,
2050 false))
2051 return false;
2052 }
2053 }
2054 return true;
2055 }
2056
2057 bool generateStructs(std::string *one_file_code,
2058 ImportMap &one_file_imports) const {
2059 for (auto it = parser_.structs_.vec.begin();
2060 it != parser_.structs_.vec.end(); ++it) {
2061 auto &struct_def = **it;
2062 std::string declcode;
2063 ImportMap imports;
2064 GenStruct(struct_def, &declcode, imports);
2065 if (parser_.opts.generate_object_based_api) {
2066 GenStructForObjectAPI(struct_def, &declcode);
2067 }
2068
2069 if (parser_.opts.one_file) {
2070 if (!declcode.empty()) { *one_file_code += declcode + "\n\n"; }
2071
2072 for (auto import_str : imports) { one_file_imports.insert(import_str); }
2073 } else {
2074 const std::string mod =
2075 namer_.File(struct_def, SkipFile::SuffixAndExtension);
2076 if (!SaveType(namer_.File(struct_def, SkipFile::Suffix),
2077 *struct_def.defined_namespace, declcode, imports, mod,
2078 true))
2079 return false;
2080 }
2081 }
2082 return true;
2083 }
2084
2085 // Begin by declaring namespace and imports.
2086 void BeginFile(const std::string &name_space_name, const bool needs_imports,
2087 std::string *code_ptr, const std::string &mod,
2088 const ImportMap &imports) const {
2089 auto &code = *code_ptr;
2090 code = code + "# " + FlatBuffersGeneratedWarning() + "\n\n";
2091 code += "# namespace: " + name_space_name + "\n\n";
2092
2093 if (needs_imports) {
2094 const std::string local_import = "." + mod;
2095
2096 code += "import flatbuffers\n";
2097 code += "from flatbuffers.compat import import_numpy\n";
2098 if (parser_.opts.python_typing) {
2099 code += "from typing import Any\n";
2100
2101 for (auto import_entry : imports) {
2102 // If we have a file called, say, "MyType.py" and in it we have a
2103 // class "MyType", we can generate imports -- usually when we
2104 // have a type that contains arrays of itself -- of the type
2105 // "from .MyType import MyType", which Python can't resolve. So
2106 // if we are trying to import ourself, we skip.
2107 if (import_entry.first != local_import) {
2108 code += "from " + import_entry.first + " import " +
2109 import_entry.second + "\n";
2110 }
2111 }
2112 }
2113 code += "np = import_numpy()\n\n";
2114 }
2115 }
2116
2117 // Save out the generated code for a Python Table type.
2118 bool SaveType(const std::string &defname, const Namespace &ns,
2119 const std::string &classcode, const ImportMap &imports,
2120 const std::string &mod, bool needs_imports) const {
2121 if (!classcode.length()) return true;
2122
2123 std::string code = "";
2124 BeginFile(LastNamespacePart(ns), needs_imports, &code, mod, imports);
2125 code += classcode;
2126
2127 const std::string directories =
2128 parser_.opts.one_file ? path_ : namer_.Directories(ns.components);
2129 EnsureDirExists(directories);
2130
2131 for (size_t i = path_.size() + 1; i != std::string::npos;
2132 i = directories.find(kPathSeparator, i + 1)) {
2133 const std::string init_py =
2134 directories.substr(0, i) + kPathSeparator + "__init__.py";
2135 SaveFile(init_py.c_str(), "", false);
2136 }
2137
2138 const std::string filename = directories + defname;
2139 return SaveFile(filename.c_str(), code, false);
2140 }
2141
2142 private:
2143 const SimpleFloatConstantGenerator float_const_gen_;
2144 const IdlNamer namer_;
2145};
2146
2147} // namespace python
2148
2149static bool GeneratePython(const Parser &parser, const std::string &path,
2150 const std::string &file_name) {
2151 python::PythonGenerator generator(parser, path, file_name);
2152 return generator.generate();
2153}
2154
2155namespace {
2156
2157class PythonCodeGenerator : public CodeGenerator {
2158 public:
2159 Status GenerateCode(const Parser &parser, const std::string &path,
2160 const std::string &filename) override {
2161 if (!GeneratePython(parser, path, filename)) { return Status::ERROR; }
2162 return Status::OK;
2163 }
2164
2165 Status GenerateCode(const uint8_t *, int64_t,
2166 const CodeGenOptions &) override {
2167 return Status::NOT_IMPLEMENTED;
2168 }
2169
2170 Status GenerateMakeRule(const Parser &parser, const std::string &path,
2171 const std::string &filename,
2172 std::string &output) override {
2173 (void)parser;
2174 (void)path;
2175 (void)filename;
2176 (void)output;
2177 return Status::NOT_IMPLEMENTED;
2178 }
2179
2180 Status GenerateGrpcCode(const Parser &parser, const std::string &path,
2181 const std::string &filename) override {
2182 if (!GeneratePythonGRPC(parser, path, filename)) { return Status::ERROR; }
2183 return Status::OK;
2184 }
2185
2186 Status GenerateRootFile(const Parser &parser,
2187 const std::string &path) override {
2188 (void)parser;
2189 (void)path;
2190 return Status::NOT_IMPLEMENTED;
2191 }
2192
2193 bool IsSchemaOnly() const override { return true; }
2194
2195 bool SupportsBfbsGeneration() const override { return false; }
2196 bool SupportsRootFileGeneration() const override { return false; }
2197
2198 IDLOptions::Language Language() const override { return IDLOptions::kPython; }
2199
2200 std::string LanguageName() const override { return "Python"; }
2201};
2202} // namespace
2203
2204std::unique_ptr<CodeGenerator> NewPythonCodeGenerator() {
2205 return std::unique_ptr<PythonCodeGenerator>(new PythonCodeGenerator());
2206}
2207
2208} // namespace flatbuffers
View as plain text