xref: /aosp_15_r20/external/flatbuffers/src/idl_gen_python.cpp (revision 890232f25432b36107d06881e0a25aaa6b473652)
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 <cctype>
20 #include <set>
21 #include <string>
22 #include <unordered_set>
23 #include <vector>
24 
25 #include "flatbuffers/code_generators.h"
26 #include "flatbuffers/flatbuffers.h"
27 #include "flatbuffers/idl.h"
28 #include "flatbuffers/util.h"
29 #include "idl_namer.h"
30 
31 namespace flatbuffers {
32 namespace python {
33 
34 namespace {
35 
PythonKeywords()36 static std::set<std::string> PythonKeywords() {
37   return { "False", "None",   "True",     "and",   "as",     "assert",
38            "break", "class",  "continue", "def",   "del",    "elif",
39            "else",  "except", "finally",  "for",   "from",   "global",
40            "if",    "import", "in",       "is",    "lambda", "nonlocal",
41            "not",   "or",     "pass",     "raise", "return", "try",
42            "while", "with",   "yield" };
43 }
44 
PythonDefaultConfig()45 static Namer::Config PythonDefaultConfig() {
46   return { /*types=*/Case::kKeep,
47            /*constants=*/Case::kScreamingSnake,
48            /*methods=*/Case::kUpperCamel,
49            /*functions=*/Case::kUpperCamel,
50            /*fields=*/Case::kLowerCamel,
51            /*variable=*/Case::kLowerCamel,
52            /*variants=*/Case::kKeep,
53            /*enum_variant_seperator=*/".",
54            /*escape_keywords=*/Namer::Config::Escape::BeforeConvertingCase,
55            /*namespaces=*/Case::kKeep,  // Packages in python.
56            /*namespace_seperator=*/".",
57            /*object_prefix=*/"",
58            /*object_suffix=*/"T",
59            /*keyword_prefix=*/"",
60            /*keyword_suffix=*/"_",
61            /*filenames=*/Case::kKeep,
62            /*directories=*/Case::kKeep,
63            /*output_path=*/"",
64            /*filename_suffix=*/"",
65            /*filename_extension=*/".py" };
66 }
67 
68 // Hardcode spaces per indentation.
69 static const CommentConfig def_comment = { nullptr, "#", nullptr };
70 static const std::string Indent = "    ";
71 
72 } // namespace
73 
74 class PythonGenerator : public BaseGenerator {
75  public:
PythonGenerator(const Parser & parser,const std::string & path,const std::string & file_name)76   PythonGenerator(const Parser &parser, const std::string &path,
77                   const std::string &file_name)
78       : BaseGenerator(parser, path, file_name, "" /* not used */,
79                       "" /* not used */, "py"),
80         float_const_gen_("float('nan')", "float('inf')", "float('-inf')"),
81         namer_(WithFlagOptions(PythonDefaultConfig(), parser.opts, path),
82                PythonKeywords()) {}
83 
84   // Most field accessors need to retrieve and test the field offset first,
85   // this is the prefix code for that.
OffsetPrefix(const FieldDef & field) const86   std::string OffsetPrefix(const FieldDef &field) const {
87     return "\n" + Indent + Indent +
88            "o = flatbuffers.number_types.UOffsetTFlags.py_type" +
89            "(self._tab.Offset(" + NumToString(field.value.offset) + "))\n" +
90            Indent + Indent + "if o != 0:\n";
91   }
92 
93   // Begin a class declaration.
BeginClass(const StructDef & struct_def,std::string * code_ptr) const94   void BeginClass(const StructDef &struct_def, std::string *code_ptr) const {
95     auto &code = *code_ptr;
96     code += "class " + namer_.Type(struct_def) + "(object):\n";
97     code += Indent + "__slots__ = ['_tab']";
98     code += "\n\n";
99   }
100 
101   // Begin enum code with a class declaration.
BeginEnum(const EnumDef & enum_def,std::string * code_ptr) const102   void BeginEnum(const EnumDef &enum_def, std::string *code_ptr) const {
103     auto &code = *code_ptr;
104     code += "class " + namer_.Type(enum_def) + "(object):\n";
105   }
106 
107   // Starts a new line and then indents.
GenIndents(int num) const108   std::string GenIndents(int num) const {
109     return "\n" + std::string(num * Indent.length(), ' ');
110   }
111 
112   // A single enum member.
EnumMember(const EnumDef & enum_def,const EnumVal & ev,std::string * code_ptr) const113   void EnumMember(const EnumDef &enum_def, const EnumVal &ev,
114                   std::string *code_ptr) const {
115     auto &code = *code_ptr;
116     code += Indent;
117     code += namer_.Variant(ev);
118     code += " = ";
119     code += enum_def.ToString(ev) + "\n";
120   }
121 
122   // Initialize a new struct or table from existing data.
NewRootTypeFromBuffer(const StructDef & struct_def,std::string * code_ptr) const123   void NewRootTypeFromBuffer(const StructDef &struct_def,
124                              std::string *code_ptr) const {
125     auto &code = *code_ptr;
126     const std::string struct_type = namer_.Type(struct_def);
127 
128     code += Indent + "@classmethod\n";
129     code += Indent + "def GetRootAs";
130     code += "(cls, buf, offset=0):";
131     code += "\n";
132     code += Indent + Indent;
133     code += "n = flatbuffers.encode.Get";
134     code += "(flatbuffers.packer.uoffset, buf, offset)\n";
135     code += Indent + Indent + "x = " + struct_type + "()\n";
136     code += Indent + Indent + "x.Init(buf, n + offset)\n";
137     code += Indent + Indent + "return x\n";
138     code += "\n";
139 
140     // Add an alias with the old name
141     code += Indent + "@classmethod\n";
142     code += Indent + "def GetRootAs" + struct_type + "(cls, buf, offset=0):\n";
143     code +=
144         Indent + Indent +
145         "\"\"\"This method is deprecated. Please switch to GetRootAs.\"\"\"\n";
146     code += Indent + Indent + "return cls.GetRootAs(buf, offset)\n";
147   }
148 
149   // Initialize an existing object with other data, to avoid an allocation.
InitializeExisting(const StructDef & struct_def,std::string * code_ptr) const150   void InitializeExisting(const StructDef &struct_def,
151                           std::string *code_ptr) const {
152     auto &code = *code_ptr;
153 
154     GenReceiver(struct_def, code_ptr);
155     code += "Init(self, buf, pos):\n";
156     code += Indent + Indent + "self._tab = flatbuffers.table.Table(buf, pos)\n";
157     code += "\n";
158   }
159 
160   // Get the length of a vector.
GetVectorLen(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const161   void GetVectorLen(const StructDef &struct_def, const FieldDef &field,
162                     std::string *code_ptr) const {
163     auto &code = *code_ptr;
164 
165     GenReceiver(struct_def, code_ptr);
166     code += namer_.Method(field) + "Length(self";
167     code += "):" + OffsetPrefix(field);
168     code += Indent + Indent + Indent + "return self._tab.VectorLen(o)\n";
169     code += Indent + Indent + "return 0\n\n";
170   }
171 
172   // Determines whether a vector is none or not.
GetVectorIsNone(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const173   void GetVectorIsNone(const StructDef &struct_def, const FieldDef &field,
174                        std::string *code_ptr) const {
175     auto &code = *code_ptr;
176 
177     GenReceiver(struct_def, code_ptr);
178     code += namer_.Method(field) + "IsNone(self";
179     code += "):";
180     code += GenIndents(2) +
181             "o = flatbuffers.number_types.UOffsetTFlags.py_type" +
182             "(self._tab.Offset(" + NumToString(field.value.offset) + "))";
183     code += GenIndents(2) + "return o == 0";
184     code += "\n\n";
185   }
186 
187   // Get the value of a struct's scalar.
GetScalarFieldOfStruct(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const188   void GetScalarFieldOfStruct(const StructDef &struct_def,
189                               const FieldDef &field,
190                               std::string *code_ptr) const {
191     auto &code = *code_ptr;
192     std::string getter = GenGetter(field.value.type);
193     GenReceiver(struct_def, code_ptr);
194     code += namer_.Method(field);
195     code += "(self): return " + getter;
196     code += "self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(";
197     code += NumToString(field.value.offset) + "))\n";
198   }
199 
200   // Get the value of a table's scalar.
GetScalarFieldOfTable(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const201   void GetScalarFieldOfTable(const StructDef &struct_def, const FieldDef &field,
202                              std::string *code_ptr) const {
203     auto &code = *code_ptr;
204     std::string getter = GenGetter(field.value.type);
205     GenReceiver(struct_def, code_ptr);
206     code += namer_.Method(field);
207     code += "(self):";
208     code += OffsetPrefix(field);
209     getter += "o + self._tab.Pos)";
210     auto is_bool = IsBool(field.value.type.base_type);
211     if (is_bool) { getter = "bool(" + getter + ")"; }
212     code += Indent + Indent + Indent + "return " + getter + "\n";
213     std::string default_value;
214     if (field.IsScalarOptional()) {
215       default_value = "None";
216     } else if (is_bool) {
217       default_value = field.value.constant == "0" ? "False" : "True";
218     } else {
219       default_value = IsFloat(field.value.type.base_type)
220                           ? float_const_gen_.GenFloatConstant(field)
221                           : field.value.constant;
222     }
223     code += Indent + Indent + "return " + default_value + "\n\n";
224   }
225 
226   // Get a struct by initializing an existing struct.
227   // Specific to Struct.
GetStructFieldOfStruct(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const228   void GetStructFieldOfStruct(const StructDef &struct_def,
229                               const FieldDef &field,
230                               std::string *code_ptr) const {
231     auto &code = *code_ptr;
232     GenReceiver(struct_def, code_ptr);
233     code += namer_.Method(field);
234     code += "(self, obj):\n";
235     code += Indent + Indent + "obj.Init(self._tab.Bytes, self._tab.Pos + ";
236     code += NumToString(field.value.offset) + ")";
237     code += "\n" + Indent + Indent + "return obj\n\n";
238   }
239 
240   // Get the value of a fixed size array.
GetArrayOfStruct(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const241   void GetArrayOfStruct(const StructDef &struct_def, const FieldDef &field,
242                         std::string *code_ptr) const {
243     auto &code = *code_ptr;
244     const auto vec_type = field.value.type.VectorType();
245     GenReceiver(struct_def, code_ptr);
246     code += namer_.Method(field);
247     if (IsStruct(vec_type)) {
248       code += "(self, obj, i):\n";
249       code += Indent + Indent + "obj.Init(self._tab.Bytes, self._tab.Pos + ";
250       code += NumToString(field.value.offset) + " + i * ";
251       code += NumToString(InlineSize(vec_type));
252       code += ")\n" + Indent + Indent + "return obj\n\n";
253     } else {
254       auto getter = GenGetter(vec_type);
255       code += "(self): return [" + getter;
256       code += "self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(";
257       code += NumToString(field.value.offset) + " + i * ";
258       code += NumToString(InlineSize(vec_type));
259       code += ")) for i in range(";
260       code += NumToString(field.value.type.fixed_length) + ")]\n";
261     }
262   }
263 
264   // Get a struct by initializing an existing struct.
265   // Specific to Table.
GetStructFieldOfTable(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const266   void GetStructFieldOfTable(const StructDef &struct_def, const FieldDef &field,
267                              std::string *code_ptr) const {
268     auto &code = *code_ptr;
269     GenReceiver(struct_def, code_ptr);
270     code += namer_.Method(field);
271     code += "(self):";
272     code += OffsetPrefix(field);
273     if (field.value.type.struct_def->fixed) {
274       code += Indent + Indent + Indent + "x = o + self._tab.Pos\n";
275     } else {
276       code += Indent + Indent + Indent;
277       code += "x = self._tab.Indirect(o + self._tab.Pos)\n";
278     }
279     if (parser_.opts.include_dependence_headers) {
280       code += Indent + Indent + Indent;
281       code += "from " + GenPackageReference(field.value.type) + " import " +
282               TypeName(field) + "\n";
283     }
284     code += Indent + Indent + Indent + "obj = " + TypeName(field) + "()\n";
285     code += Indent + Indent + Indent + "obj.Init(self._tab.Bytes, x)\n";
286     code += Indent + Indent + Indent + "return obj\n";
287     code += Indent + Indent + "return None\n\n";
288   }
289 
290   // Get the value of a string.
GetStringField(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const291   void GetStringField(const StructDef &struct_def, const FieldDef &field,
292                       std::string *code_ptr) const {
293     auto &code = *code_ptr;
294     GenReceiver(struct_def, code_ptr);
295     code += namer_.Method(field);
296     code += "(self):";
297     code += OffsetPrefix(field);
298     code += Indent + Indent + Indent + "return " + GenGetter(field.value.type);
299     code += "o + self._tab.Pos)\n";
300     code += Indent + Indent + "return None\n\n";
301   }
302 
303   // Get the value of a union from an object.
GetUnionField(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const304   void GetUnionField(const StructDef &struct_def, const FieldDef &field,
305                      std::string *code_ptr) const {
306     auto &code = *code_ptr;
307     GenReceiver(struct_def, code_ptr);
308     code += namer_.Method(field) + "(self):";
309     code += OffsetPrefix(field);
310 
311     // TODO(rw): this works and is not the good way to it:
312     bool is_native_table = TypeName(field) == "*flatbuffers.Table";
313     if (is_native_table) {
314       code +=
315           Indent + Indent + Indent + "from flatbuffers.table import Table\n";
316     } else if (parser_.opts.include_dependence_headers) {
317       code += Indent + Indent + Indent;
318       code += "from " + GenPackageReference(field.value.type) + " import " +
319               TypeName(field) + "\n";
320     }
321     code += Indent + Indent + Indent + "obj = Table(bytearray(), 0)\n";
322     code += Indent + Indent + Indent + GenGetter(field.value.type);
323     code += "obj, o)\n" + Indent + Indent + Indent + "return obj\n";
324     code += Indent + Indent + "return None\n\n";
325   }
326 
327   // Generate the package reference when importing a struct or enum from its
328   // module.
GenPackageReference(const Type & type) const329   std::string GenPackageReference(const Type &type) const {
330     if (type.struct_def) {
331       return namer_.NamespacedType(*type.struct_def);
332     } else if (type.enum_def) {
333       return namer_.NamespacedType(*type.enum_def);
334     } else {
335       return "." + GenTypeGet(type);
336     }
337   }
338 
339   // Get the value of a vector's struct member.
GetMemberOfVectorOfStruct(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const340   void GetMemberOfVectorOfStruct(const StructDef &struct_def,
341                                  const FieldDef &field,
342                                  std::string *code_ptr) const {
343     auto &code = *code_ptr;
344     auto vectortype = field.value.type.VectorType();
345 
346     GenReceiver(struct_def, code_ptr);
347     code += namer_.Method(field);
348     code += "(self, j):" + OffsetPrefix(field);
349     code += Indent + Indent + Indent + "x = self._tab.Vector(o)\n";
350     code += Indent + Indent + Indent;
351     code += "x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * ";
352     code += NumToString(InlineSize(vectortype)) + "\n";
353     if (!(vectortype.struct_def->fixed)) {
354       code += Indent + Indent + Indent + "x = self._tab.Indirect(x)\n";
355     }
356     if (parser_.opts.include_dependence_headers) {
357       code += Indent + Indent + Indent;
358       code += "from " + GenPackageReference(field.value.type) + " import " +
359               TypeName(field) + "\n";
360     }
361     code += Indent + Indent + Indent + "obj = " + TypeName(field) + "()\n";
362     code += Indent + Indent + Indent + "obj.Init(self._tab.Bytes, x)\n";
363     code += Indent + Indent + Indent + "return obj\n";
364     code += Indent + Indent + "return None\n\n";
365   }
366 
367   // Get the value of a vector's non-struct member. Uses a named return
368   // argument to conveniently set the zero value for the result.
GetMemberOfVectorOfNonStruct(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const369   void GetMemberOfVectorOfNonStruct(const StructDef &struct_def,
370                                     const FieldDef &field,
371                                     std::string *code_ptr) const {
372     auto &code = *code_ptr;
373     auto vectortype = field.value.type.VectorType();
374 
375     GenReceiver(struct_def, code_ptr);
376     code += namer_.Method(field);
377     code += "(self, j):";
378     code += OffsetPrefix(field);
379     code += Indent + Indent + Indent + "a = self._tab.Vector(o)\n";
380     code += Indent + Indent + Indent;
381     code += "return " + GenGetter(field.value.type);
382     code += "a + flatbuffers.number_types.UOffsetTFlags.py_type(j * ";
383     code += NumToString(InlineSize(vectortype)) + "))\n";
384     if (IsString(vectortype)) {
385       code += Indent + Indent + "return \"\"\n";
386     } else {
387       code += Indent + Indent + "return 0\n";
388     }
389     code += "\n";
390   }
391 
392   // Returns a non-struct vector as a numpy array. Much faster
393   // than iterating over the vector element by element.
GetVectorOfNonStructAsNumpy(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const394   void GetVectorOfNonStructAsNumpy(const StructDef &struct_def,
395                                    const FieldDef &field,
396                                    std::string *code_ptr) const {
397     auto &code = *code_ptr;
398     auto vectortype = field.value.type.VectorType();
399 
400     // Currently, we only support accessing as numpy array if
401     // the vector type is a scalar.
402     if (!(IsScalar(vectortype.base_type))) { return; }
403 
404     GenReceiver(struct_def, code_ptr);
405     code += namer_.Method(field) + "AsNumpy(self):";
406     code += OffsetPrefix(field);
407 
408     code += Indent + Indent + Indent;
409     code += "return ";
410     code += "self._tab.GetVectorAsNumpy(flatbuffers.number_types.";
411     code += namer_.Method(GenTypeGet(field.value.type));
412     code += "Flags, o)\n";
413 
414     if (IsString(vectortype)) {
415       code += Indent + Indent + "return \"\"\n";
416     } else {
417       code += Indent + Indent + "return 0\n";
418     }
419     code += "\n";
420   }
421 
NestedFlatbufferType(std::string unqualified_name) const422   std::string NestedFlatbufferType(std::string unqualified_name) const {
423     StructDef *nested_root = parser_.LookupStruct(unqualified_name);
424     std::string qualified_name;
425     if (nested_root == nullptr) {
426       qualified_name = namer_.NamespacedType(
427           parser_.current_namespace_->components, unqualified_name);
428       // Double check qualified name just to be sure it exists.
429       nested_root = parser_.LookupStruct(qualified_name);
430     }
431     FLATBUFFERS_ASSERT(nested_root);  // Guaranteed to exist by parser.
432     return qualified_name;
433   }
434 
435   // Returns a nested flatbuffer as itself.
GetVectorAsNestedFlatbuffer(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const436   void GetVectorAsNestedFlatbuffer(const StructDef &struct_def,
437                                    const FieldDef &field,
438                                    std::string *code_ptr) const {
439     auto nested = field.attributes.Lookup("nested_flatbuffer");
440     if (!nested) { return; }  // There is no nested flatbuffer.
441 
442     const std::string unqualified_name = nested->constant;
443     const std::string qualified_name = NestedFlatbufferType(unqualified_name);
444 
445     auto &code = *code_ptr;
446     GenReceiver(struct_def, code_ptr);
447     code += namer_.Method(field) + "NestedRoot(self):";
448 
449     code += OffsetPrefix(field);
450 
451     code += Indent + Indent + Indent;
452     code += "from " + qualified_name + " import " + unqualified_name + "\n";
453     code += Indent + Indent + Indent + "return " + unqualified_name;
454     code += ".GetRootAs" + unqualified_name;
455     code += "(self._tab.Bytes, self._tab.Vector(o))\n";
456     code += Indent + Indent + "return 0\n";
457     code += "\n";
458   }
459 
460   // Begin the creator function signature.
BeginBuilderArgs(const StructDef & struct_def,std::string * code_ptr) const461   void BeginBuilderArgs(const StructDef &struct_def,
462                         std::string *code_ptr) const {
463     auto &code = *code_ptr;
464 
465     code += "\n";
466     code += "def Create" + namer_.Type(struct_def);
467     code += "(builder";
468   }
469 
470   // Recursively generate arguments for a constructor, to deal with nested
471   // structs.
StructBuilderArgs(const StructDef & struct_def,const std::string nameprefix,const std::string namesuffix,bool has_field_name,const std::string fieldname_suffix,std::string * code_ptr) const472   void StructBuilderArgs(const StructDef &struct_def,
473                          const std::string nameprefix,
474                          const std::string namesuffix, bool has_field_name,
475                          const std::string fieldname_suffix,
476                          std::string *code_ptr) const {
477     for (auto it = struct_def.fields.vec.begin();
478          it != struct_def.fields.vec.end(); ++it) {
479       auto &field = **it;
480       const auto &field_type = field.value.type;
481       const auto &type =
482           IsArray(field_type) ? field_type.VectorType() : field_type;
483       if (IsStruct(type)) {
484         // Generate arguments for a struct inside a struct. To ensure names
485         // don't clash, and to make it obvious these arguments are constructing
486         // a nested struct, prefix the name with the field name.
487         auto subprefix = nameprefix;
488         if (has_field_name) {
489           subprefix += namer_.Field(field) + fieldname_suffix;
490         }
491         StructBuilderArgs(*field.value.type.struct_def, subprefix, namesuffix,
492                           has_field_name, fieldname_suffix, code_ptr);
493       } else {
494         auto &code = *code_ptr;
495         code += std::string(", ") + nameprefix;
496         if (has_field_name) { code += namer_.Field(field); }
497         code += namesuffix;
498       }
499     }
500   }
501 
502   // End the creator function signature.
EndBuilderArgs(std::string * code_ptr) const503   void EndBuilderArgs(std::string *code_ptr) const {
504     auto &code = *code_ptr;
505     code += "):\n";
506   }
507 
508   // Recursively generate struct construction statements and instert manual
509   // padding.
StructBuilderBody(const StructDef & struct_def,const char * nameprefix,std::string * code_ptr,size_t index=0,bool in_array=false) const510   void StructBuilderBody(const StructDef &struct_def, const char *nameprefix,
511                          std::string *code_ptr, size_t index = 0,
512                          bool in_array = false) const {
513     auto &code = *code_ptr;
514     std::string indent(index * 4, ' ');
515     code +=
516         indent + "    builder.Prep(" + NumToString(struct_def.minalign) + ", ";
517     code += NumToString(struct_def.bytesize) + ")\n";
518     for (auto it = struct_def.fields.vec.rbegin();
519          it != struct_def.fields.vec.rend(); ++it) {
520       auto &field = **it;
521       const auto &field_type = field.value.type;
522       const auto &type =
523           IsArray(field_type) ? field_type.VectorType() : field_type;
524       if (field.padding)
525         code +=
526             indent + "    builder.Pad(" + NumToString(field.padding) + ")\n";
527       if (IsStruct(field_type)) {
528         StructBuilderBody(*field_type.struct_def,
529                           (nameprefix + (namer_.Field(field) + "_")).c_str(),
530                           code_ptr, index, in_array);
531       } else {
532         const auto index_var = "_idx" + NumToString(index);
533         if (IsArray(field_type)) {
534           code += indent + "    for " + index_var + " in range(";
535           code += NumToString(field_type.fixed_length);
536           code += " , 0, -1):\n";
537           in_array = true;
538         }
539         if (IsStruct(type)) {
540           StructBuilderBody(*field_type.struct_def,
541                             (nameprefix + (namer_.Field(field) + "_")).c_str(),
542                             code_ptr, index + 1, in_array);
543         } else {
544           code += IsArray(field_type) ? "    " : "";
545           code += indent + "    builder.Prepend" + GenMethod(field) + "(";
546           code += nameprefix + namer_.Variable(field);
547           size_t array_cnt = index + (IsArray(field_type) ? 1 : 0);
548           for (size_t i = 0; in_array && i < array_cnt; i++) {
549             code += "[_idx" + NumToString(i) + "-1]";
550           }
551           code += ")\n";
552         }
553       }
554     }
555   }
556 
EndBuilderBody(std::string * code_ptr) const557   void EndBuilderBody(std::string *code_ptr) const {
558     auto &code = *code_ptr;
559     code += "    return builder.Offset()\n";
560   }
561 
562   // Get the value of a table's starting offset.
GetStartOfTable(const StructDef & struct_def,std::string * code_ptr) const563   void GetStartOfTable(const StructDef &struct_def,
564                        std::string *code_ptr) const {
565     auto &code = *code_ptr;
566     const auto struct_type = namer_.Type(struct_def);
567     // Generate method with struct name.
568     code += "def " + struct_type + "Start(builder): ";
569     code += "builder.StartObject(";
570     code += NumToString(struct_def.fields.vec.size());
571     code += ")\n";
572 
573     if (!parser_.opts.one_file) {
574       // Generate method without struct name.
575       code += "def Start(builder):\n";
576       code += Indent + "return " + struct_type + "Start(builder)\n";
577     }
578   }
579 
580   // Set the value of a table's field.
BuildFieldOfTable(const StructDef & struct_def,const FieldDef & field,const size_t offset,std::string * code_ptr) const581   void BuildFieldOfTable(const StructDef &struct_def, const FieldDef &field,
582                          const size_t offset, std::string *code_ptr) const {
583     auto &code = *code_ptr;
584     const std::string field_var = namer_.Variable(field);
585     const std::string field_method = namer_.Method(field);
586 
587     // Generate method with struct name.
588     code += "def " + namer_.Type(struct_def) + "Add" + field_method;
589     code += "(builder, ";
590     code += field_var;
591     code += "): ";
592     code += "builder.Prepend";
593     code += GenMethod(field) + "Slot(";
594     code += NumToString(offset) + ", ";
595     if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
596       code += "flatbuffers.number_types.UOffsetTFlags.py_type";
597       code += "(" + field_var + ")";
598     } else {
599       code += field_var;
600     }
601     code += ", ";
602     if (field.IsScalarOptional()) {
603       code += "None";
604     } else if (IsFloat(field.value.type.base_type)) {
605       code += float_const_gen_.GenFloatConstant(field);
606     } else {
607       code += field.value.constant;
608     }
609     code += ")\n";
610 
611     if (!parser_.opts.one_file) {
612       // Generate method without struct name.
613       code += "def Add" + field_method + "(builder, " + field_var + "):\n";
614       code +=
615           Indent + "return " + namer_.Type(struct_def) + "Add" + field_method;
616       code += "(builder, ";
617       code += field_var;
618       code += ")\n";
619     }
620   }
621 
622   // Set the value of one of the members of a table's vector.
BuildVectorOfTable(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const623   void BuildVectorOfTable(const StructDef &struct_def, const FieldDef &field,
624                           std::string *code_ptr) const {
625     auto &code = *code_ptr;
626     const std::string struct_type = namer_.Type(struct_def);
627     const std::string field_method = namer_.Method(field);
628 
629     // Generate method with struct name.
630     code += "def " + struct_type + "Start" + field_method;
631     code += "Vector(builder, numElems): return builder.StartVector(";
632     auto vector_type = field.value.type.VectorType();
633     auto alignment = InlineAlignment(vector_type);
634     auto elem_size = InlineSize(vector_type);
635     code += NumToString(elem_size);
636     code += ", numElems, " + NumToString(alignment);
637     code += ")\n";
638 
639     if (!parser_.opts.one_file) {
640       // Generate method without struct name.
641       code += "def Start" + field_method + "Vector(builder, numElems):\n";
642       code += Indent + "return " + struct_type + "Start";
643       code += field_method + "Vector(builder, numElems)\n";
644     }
645   }
646 
647   // Set the value of one of the members of a table's vector and fills in the
648   // elements from a bytearray. This is for simplifying the use of nested
649   // flatbuffers.
BuildVectorOfTableFromBytes(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const650   void BuildVectorOfTableFromBytes(const StructDef &struct_def,
651                                    const FieldDef &field,
652                                    std::string *code_ptr) const {
653     auto nested = field.attributes.Lookup("nested_flatbuffer");
654     if (!nested) { return; }  // There is no nested flatbuffer.
655 
656     auto &code = *code_ptr;
657     const std::string field_method = namer_.Method(field);
658     const std::string struct_type = namer_.Type(struct_def);
659 
660     // Generate method with struct and field name.
661     code += "def " + struct_type + "Make" + field_method;
662     code += "VectorFromBytes(builder, bytes):\n";
663     code += Indent + "builder.StartVector(";
664     auto vector_type = field.value.type.VectorType();
665     auto alignment = InlineAlignment(vector_type);
666     auto elem_size = InlineSize(vector_type);
667     code += NumToString(elem_size);
668     code += ", len(bytes), " + NumToString(alignment);
669     code += ")\n";
670     code += Indent + "builder.head = builder.head - len(bytes)\n";
671     code += Indent + "builder.Bytes[builder.head : builder.head + len(bytes)]";
672     code += " = bytes\n";
673     code += Indent + "return builder.EndVector()\n";
674 
675     if (!parser_.opts.one_file) {
676       // Generate method without struct and field name.
677       code += "def Make" + field_method + "VectorFromBytes(builder, bytes):\n";
678       code += Indent + "return " + struct_type + "Make" + field_method +
679               "VectorFromBytes(builder, bytes)\n";
680     }
681   }
682 
683   // Get the offset of the end of a table.
GetEndOffsetOnTable(const StructDef & struct_def,std::string * code_ptr) const684   void GetEndOffsetOnTable(const StructDef &struct_def,
685                            std::string *code_ptr) const {
686     auto &code = *code_ptr;
687 
688     // Generate method with struct name.
689     code += "def " + namer_.Type(struct_def) + "End";
690     code += "(builder): ";
691     code += "return builder.EndObject()\n";
692 
693     if (!parser_.opts.one_file) {
694       // Generate method without struct name.
695       code += "def End(builder):\n";
696       code += Indent + "return " + namer_.Type(struct_def) + "End(builder)";
697     }
698   }
699 
700   // Generate the receiver for function signatures.
GenReceiver(const StructDef & struct_def,std::string * code_ptr) const701   void GenReceiver(const StructDef &struct_def, std::string *code_ptr) const {
702     auto &code = *code_ptr;
703     code += Indent + "# " + namer_.Type(struct_def) + "\n";
704     code += Indent + "def ";
705   }
706 
707   // Generate a struct field, conditioned on its child type(s).
GenStructAccessor(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const708   void GenStructAccessor(const StructDef &struct_def, const FieldDef &field,
709                          std::string *code_ptr) const {
710     GenComment(field.doc_comment, code_ptr, &def_comment, Indent.c_str());
711     if (IsScalar(field.value.type.base_type)) {
712       if (struct_def.fixed) {
713         GetScalarFieldOfStruct(struct_def, field, code_ptr);
714       } else {
715         GetScalarFieldOfTable(struct_def, field, code_ptr);
716       }
717     } else if (IsArray(field.value.type)) {
718       GetArrayOfStruct(struct_def, field, code_ptr);
719     } else {
720       switch (field.value.type.base_type) {
721         case BASE_TYPE_STRUCT:
722           if (struct_def.fixed) {
723             GetStructFieldOfStruct(struct_def, field, code_ptr);
724           } else {
725             GetStructFieldOfTable(struct_def, field, code_ptr);
726           }
727           break;
728         case BASE_TYPE_STRING:
729           GetStringField(struct_def, field, code_ptr);
730           break;
731         case BASE_TYPE_VECTOR: {
732           auto vectortype = field.value.type.VectorType();
733           if (vectortype.base_type == BASE_TYPE_STRUCT) {
734             GetMemberOfVectorOfStruct(struct_def, field, code_ptr);
735           } else {
736             GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr);
737             GetVectorOfNonStructAsNumpy(struct_def, field, code_ptr);
738             GetVectorAsNestedFlatbuffer(struct_def, field, code_ptr);
739           }
740           break;
741         }
742         case BASE_TYPE_UNION: GetUnionField(struct_def, field, code_ptr); break;
743         default: FLATBUFFERS_ASSERT(0);
744       }
745     }
746     if (IsVector(field.value.type) || IsArray(field.value.type)) {
747       GetVectorLen(struct_def, field, code_ptr);
748       GetVectorIsNone(struct_def, field, code_ptr);
749     }
750   }
751 
752   // Generate struct sizeof.
GenStructSizeOf(const StructDef & struct_def,std::string * code_ptr) const753   void GenStructSizeOf(const StructDef &struct_def,
754                        std::string *code_ptr) const {
755     auto &code = *code_ptr;
756     code += Indent + "@classmethod\n";
757     code += Indent + "def SizeOf(cls):\n";
758     code +=
759         Indent + Indent + "return " + NumToString(struct_def.bytesize) + "\n";
760     code += "\n";
761   }
762 
763   // Generate table constructors, conditioned on its members' types.
GenTableBuilders(const StructDef & struct_def,std::string * code_ptr) const764   void GenTableBuilders(const StructDef &struct_def,
765                         std::string *code_ptr) const {
766     GetStartOfTable(struct_def, code_ptr);
767 
768     for (auto it = struct_def.fields.vec.begin();
769          it != struct_def.fields.vec.end(); ++it) {
770       auto &field = **it;
771       if (field.deprecated) continue;
772 
773       auto offset = it - struct_def.fields.vec.begin();
774       BuildFieldOfTable(struct_def, field, offset, code_ptr);
775       if (IsVector(field.value.type)) {
776         BuildVectorOfTable(struct_def, field, code_ptr);
777         BuildVectorOfTableFromBytes(struct_def, field, code_ptr);
778       }
779     }
780 
781     GetEndOffsetOnTable(struct_def, code_ptr);
782   }
783 
784   // Generate function to check for proper file identifier
GenHasFileIdentifier(const StructDef & struct_def,std::string * code_ptr) const785   void GenHasFileIdentifier(const StructDef &struct_def,
786                             std::string *code_ptr) const {
787     auto &code = *code_ptr;
788     std::string escapedID;
789     // In the event any of file_identifier characters are special(NULL, \, etc),
790     // problems occur. To prevent this, convert all chars to their hex-escaped
791     // equivalent.
792     for (auto it = parser_.file_identifier_.begin();
793          it != parser_.file_identifier_.end(); ++it) {
794       escapedID += "\\x" + IntToStringHex(*it, 2);
795     }
796 
797     code += Indent + "@classmethod\n";
798     code += Indent + "def " + namer_.Type(struct_def);
799     code += "BufferHasIdentifier(cls, buf, offset, size_prefixed=False):";
800     code += "\n";
801     code += Indent + Indent;
802     code += "return flatbuffers.util.BufferHasIdentifier(buf, offset, b\"";
803     code += escapedID;
804     code += "\", size_prefixed=size_prefixed)\n";
805     code += "\n";
806   }
807 
808   // Generates struct or table methods.
GenStruct(const StructDef & struct_def,std::string * code_ptr) const809   void GenStruct(const StructDef &struct_def, std::string *code_ptr) const {
810     if (struct_def.generated) return;
811 
812     GenComment(struct_def.doc_comment, code_ptr, &def_comment);
813     BeginClass(struct_def, code_ptr);
814     if (!struct_def.fixed) {
815       // Generate a special accessor for the table that has been declared as
816       // the root type.
817       NewRootTypeFromBuffer(struct_def, code_ptr);
818       if (parser_.file_identifier_.length()) {
819         // Generate a special function to test file_identifier
820         GenHasFileIdentifier(struct_def, code_ptr);
821       }
822     } else {
823       // Generates the SizeOf method for all structs.
824       GenStructSizeOf(struct_def, code_ptr);
825     }
826     // Generates the Init method that sets the field in a pre-existing
827     // accessor object. This is to allow object reuse.
828     InitializeExisting(struct_def, code_ptr);
829     for (auto it = struct_def.fields.vec.begin();
830          it != struct_def.fields.vec.end(); ++it) {
831       auto &field = **it;
832       if (field.deprecated) continue;
833 
834       GenStructAccessor(struct_def, field, code_ptr);
835     }
836 
837     if (struct_def.fixed) {
838       // creates a struct constructor function
839       GenStructBuilder(struct_def, code_ptr);
840     } else {
841       // Creates a set of functions that allow table construction.
842       GenTableBuilders(struct_def, code_ptr);
843     }
844   }
845 
GenReceiverForObjectAPI(const StructDef & struct_def,std::string * code_ptr) const846   void GenReceiverForObjectAPI(const StructDef &struct_def,
847                                std::string *code_ptr) const {
848     auto &code = *code_ptr;
849     code += GenIndents(1) + "# " + namer_.ObjectType(struct_def);
850     code += GenIndents(1) + "def ";
851   }
852 
BeginClassForObjectAPI(const StructDef & struct_def,std::string * code_ptr) const853   void BeginClassForObjectAPI(const StructDef &struct_def,
854                               std::string *code_ptr) const {
855     auto &code = *code_ptr;
856     code += "\n";
857     code += "class " + namer_.ObjectType(struct_def) + "(object):";
858     code += "\n";
859   }
860 
861   // Gets the accoresponding python builtin type of a BaseType for scalars and
862   // string.
GetBasePythonTypeForScalarAndString(const BaseType & base_type) const863   std::string GetBasePythonTypeForScalarAndString(
864       const BaseType &base_type) const {
865     if (IsBool(base_type)) {
866       return "bool";
867     } else if (IsFloat(base_type)) {
868       return "float";
869     } else if (IsInteger(base_type)) {
870       return "int";
871     } else if (base_type == BASE_TYPE_STRING) {
872       return "str";
873     } else {
874       FLATBUFFERS_ASSERT(false && "base_type is not a scalar or string type.");
875       return "";
876     }
877   }
878 
GetDefaultValue(const FieldDef & field) const879   std::string GetDefaultValue(const FieldDef &field) const {
880     BaseType base_type = field.value.type.base_type;
881     if (field.IsScalarOptional()) {
882       return "None";
883     } else if (IsBool(base_type)) {
884       return field.value.constant == "0" ? "False" : "True";
885     } else if (IsFloat(base_type)) {
886       return float_const_gen_.GenFloatConstant(field);
887     } else if (IsInteger(base_type)) {
888       return field.value.constant;
889     } else {
890       // For string, struct, and table.
891       return "None";
892     }
893   }
894 
GenUnionInit(const FieldDef & field,std::string * field_types_ptr,std::set<std::string> * import_list,std::set<std::string> * import_typing_list) const895   void GenUnionInit(const FieldDef &field, std::string *field_types_ptr,
896                     std::set<std::string> *import_list,
897                     std::set<std::string> *import_typing_list) const {
898     // Gets all possible types in the union.
899     import_typing_list->insert("Union");
900     auto &field_types = *field_types_ptr;
901     field_types = "Union[";
902 
903     std::string separator_string = ", ";
904     auto enum_def = field.value.type.enum_def;
905     for (auto it = enum_def->Vals().begin(); it != enum_def->Vals().end();
906          ++it) {
907       auto &ev = **it;
908       // Union only supports string and table.
909       std::string field_type;
910       switch (ev.union_type.base_type) {
911         case BASE_TYPE_STRUCT:
912           field_type = namer_.ObjectType(*ev.union_type.struct_def);
913           if (parser_.opts.include_dependence_headers) {
914             auto package_reference = GenPackageReference(ev.union_type);
915             field_type = package_reference + "." + field_type;
916             import_list->insert("import " + package_reference);
917           }
918           break;
919         case BASE_TYPE_STRING: field_type += "str"; break;
920         case BASE_TYPE_NONE: field_type += "None"; break;
921         default: break;
922       }
923       field_types += field_type + separator_string;
924     }
925 
926     // Removes the last separator_string.
927     field_types.erase(field_types.length() - separator_string.size());
928     field_types += "]";
929 
930     // Gets the import lists for the union.
931     if (parser_.opts.include_dependence_headers) {
932       const auto package_reference = GenPackageReference(field.value.type);
933       import_list->insert("import " + package_reference);
934     }
935   }
936 
GenStructInit(const FieldDef & field,std::string * out_ptr,std::set<std::string> * import_list,std::set<std::string> * import_typing_list) const937   void GenStructInit(const FieldDef &field, std::string *out_ptr,
938                      std::set<std::string> *import_list,
939                      std::set<std::string> *import_typing_list) const {
940     import_typing_list->insert("Optional");
941     auto &output = *out_ptr;
942     const Type &type = field.value.type;
943     const std::string object_type = namer_.ObjectType(*type.struct_def);
944     if (parser_.opts.include_dependence_headers) {
945       auto package_reference = GenPackageReference(type);
946       output = package_reference + "." + object_type + "]";
947       import_list->insert("import " + package_reference);
948     } else {
949       output = object_type + "]";
950     }
951     output = "Optional[" + output;
952   }
953 
GenVectorInit(const FieldDef & field,std::string * field_type_ptr,std::set<std::string> * import_list,std::set<std::string> * import_typing_list) const954   void GenVectorInit(const FieldDef &field, std::string *field_type_ptr,
955                      std::set<std::string> *import_list,
956                      std::set<std::string> *import_typing_list) const {
957     import_typing_list->insert("List");
958     auto &field_type = *field_type_ptr;
959     const Type &vector_type = field.value.type.VectorType();
960     const BaseType base_type = vector_type.base_type;
961     if (base_type == BASE_TYPE_STRUCT) {
962       const std::string object_type =
963           namer_.ObjectType(*vector_type.struct_def);
964       field_type = object_type + "]";
965       if (parser_.opts.include_dependence_headers) {
966         auto package_reference = GenPackageReference(vector_type);
967         field_type = package_reference + "." + object_type + "]";
968         import_list->insert("import " + package_reference);
969       }
970       field_type = "List[" + field_type;
971     } else {
972       field_type =
973           "List[" + GetBasePythonTypeForScalarAndString(base_type) + "]";
974     }
975   }
976 
GenInitialize(const StructDef & struct_def,std::string * code_ptr,std::set<std::string> * import_list) const977   void GenInitialize(const StructDef &struct_def, std::string *code_ptr,
978                      std::set<std::string> *import_list) const {
979     std::string code;
980     std::set<std::string> import_typing_list;
981     for (auto it = struct_def.fields.vec.begin();
982          it != struct_def.fields.vec.end(); ++it) {
983       auto &field = **it;
984       if (field.deprecated) continue;
985 
986       // Determines field type, default value, and typing imports.
987       auto base_type = field.value.type.base_type;
988       std::string field_type;
989       switch (base_type) {
990         case BASE_TYPE_UNION: {
991           GenUnionInit(field, &field_type, import_list, &import_typing_list);
992           break;
993         }
994         case BASE_TYPE_STRUCT: {
995           GenStructInit(field, &field_type, import_list, &import_typing_list);
996           break;
997         }
998         case BASE_TYPE_VECTOR:
999         case BASE_TYPE_ARRAY: {
1000           GenVectorInit(field, &field_type, import_list, &import_typing_list);
1001           break;
1002         }
1003         default:
1004           // Scalar or sting fields.
1005           field_type = GetBasePythonTypeForScalarAndString(base_type);
1006           if (field.IsScalarOptional()) {
1007             field_type = "Optional[" + field_type + "]";
1008           }
1009           break;
1010       }
1011 
1012       const auto default_value = GetDefaultValue(field);
1013       // Wrties the init statement.
1014       const auto field_field = namer_.Field(field);
1015       code += GenIndents(2) + "self." + field_field + " = " + default_value +
1016               "  # type: " + field_type;
1017     }
1018 
1019     // Writes __init__ method.
1020     auto &code_base = *code_ptr;
1021     GenReceiverForObjectAPI(struct_def, code_ptr);
1022     code_base += "__init__(self):";
1023     if (code.empty()) {
1024       code_base += GenIndents(2) + "pass";
1025     } else {
1026       code_base += code;
1027     }
1028     code_base += "\n";
1029 
1030     // Merges the typing imports into import_list.
1031     if (!import_typing_list.empty()) {
1032       // Adds the try statement.
1033       std::string typing_imports = "try:";
1034       typing_imports += GenIndents(1) + "from typing import ";
1035       std::string separator_string = ", ";
1036       for (auto it = import_typing_list.begin(); it != import_typing_list.end();
1037            ++it) {
1038         const std::string &im = *it;
1039         typing_imports += im + separator_string;
1040       }
1041       // Removes the last separator_string.
1042       typing_imports.erase(typing_imports.length() - separator_string.size());
1043 
1044       // Adds the except statement.
1045       typing_imports += "\n";
1046       typing_imports += "except:";
1047       typing_imports += GenIndents(1) + "pass";
1048       import_list->insert(typing_imports);
1049     }
1050 
1051     // Removes the import of the struct itself, if applied.
1052     auto struct_import = "import " + namer_.NamespacedType(struct_def);
1053     import_list->erase(struct_import);
1054   }
1055 
InitializeFromBuf(const StructDef & struct_def,std::string * code_ptr) const1056   void InitializeFromBuf(const StructDef &struct_def,
1057                          std::string *code_ptr) const {
1058     auto &code = *code_ptr;
1059     const auto struct_var = namer_.Variable(struct_def);
1060     const auto struct_type = namer_.Type(struct_def);
1061 
1062     code += GenIndents(1) + "@classmethod";
1063     code += GenIndents(1) + "def InitFromBuf(cls, buf, pos):";
1064     code += GenIndents(2) + struct_var + " = " + struct_type + "()";
1065     code += GenIndents(2) + struct_var + ".Init(buf, pos)";
1066     code += GenIndents(2) + "return cls.InitFromObj(" + struct_var + ")";
1067     code += "\n";
1068   }
1069 
InitializeFromObjForObject(const StructDef & struct_def,std::string * code_ptr) const1070   void InitializeFromObjForObject(const StructDef &struct_def,
1071                                   std::string *code_ptr) const {
1072     auto &code = *code_ptr;
1073     const auto struct_var = namer_.Variable(struct_def);
1074     const auto struct_object = namer_.ObjectType(struct_def);
1075 
1076     code += GenIndents(1) + "@classmethod";
1077     code += GenIndents(1) + "def InitFromObj(cls, " + struct_var + "):";
1078     code += GenIndents(2) + "x = " + struct_object + "()";
1079     code += GenIndents(2) + "x._UnPack(" + struct_var + ")";
1080     code += GenIndents(2) + "return x";
1081     code += "\n";
1082   }
1083 
GenUnPackForStruct(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const1084   void GenUnPackForStruct(const StructDef &struct_def, const FieldDef &field,
1085                           std::string *code_ptr) const {
1086     auto &code = *code_ptr;
1087     const auto struct_var = namer_.Variable(struct_def);
1088     const auto field_field = namer_.Field(field);
1089     const auto field_method = namer_.Method(field);
1090     auto field_type = TypeName(field);
1091 
1092     if (parser_.opts.include_dependence_headers) {
1093       auto package_reference = GenPackageReference(field.value.type);
1094       field_type = package_reference + "." + TypeName(field);
1095     }
1096 
1097     code += GenIndents(2) + "if " + struct_var + "." + field_method + "(";
1098     // if field is a struct, we need to create an instance for it first.
1099     if (struct_def.fixed && field.value.type.base_type == BASE_TYPE_STRUCT) {
1100       code += field_type + "()";
1101     }
1102     code += ") is not None:";
1103     code += GenIndents(3) + "self." + field_field + " = " + field_type +
1104             "T.InitFromObj(" + struct_var + "." + field_method + "(";
1105     // A struct's accessor requires a struct buf instance.
1106     if (struct_def.fixed && field.value.type.base_type == BASE_TYPE_STRUCT) {
1107       code += field_type + "()";
1108     }
1109     code += "))";
1110   }
1111 
GenUnPackForUnion(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const1112   void GenUnPackForUnion(const StructDef &struct_def, const FieldDef &field,
1113                          std::string *code_ptr) const {
1114     auto &code = *code_ptr;
1115     const auto field_field = namer_.Field(field);
1116     const auto field_method = namer_.Method(field);
1117     const auto struct_var = namer_.Variable(struct_def);
1118     const EnumDef &enum_def = *field.value.type.enum_def;
1119     auto union_type = namer_.Type(enum_def);
1120 
1121     if (parser_.opts.include_dependence_headers) {
1122       union_type = namer_.NamespacedType(enum_def) + "." + union_type;
1123     }
1124     code += GenIndents(2) + "self." + field_field + " = " + union_type +
1125             "Creator(" + "self." + field_field + "Type, " + struct_var + "." +
1126             field_method + "())";
1127   }
1128 
GenUnPackForStructVector(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const1129   void GenUnPackForStructVector(const StructDef &struct_def,
1130                                 const FieldDef &field,
1131                                 std::string *code_ptr) const {
1132     auto &code = *code_ptr;
1133     const auto field_field = namer_.Field(field);
1134     const auto field_method = namer_.Method(field);
1135     const auto struct_var = namer_.Variable(struct_def);
1136 
1137     code += GenIndents(2) + "if not " + struct_var + "." + field_method +
1138             "IsNone():";
1139     code += GenIndents(3) + "self." + field_field + " = []";
1140     code += GenIndents(3) + "for i in range(" + struct_var + "." +
1141             field_method + "Length()):";
1142 
1143     auto field_type = TypeName(field);
1144     auto one_instance = field_type + "_";
1145     one_instance[0] = CharToLower(one_instance[0]);
1146 
1147     if (parser_.opts.include_dependence_headers) {
1148       auto package_reference = GenPackageReference(field.value.type);
1149       field_type = package_reference + "." + TypeName(field);
1150     }
1151 
1152     code += GenIndents(4) + "if " + struct_var + "." + field_method +
1153             "(i) is None:";
1154     code += GenIndents(5) + "self." + field_field + ".append(None)";
1155     code += GenIndents(4) + "else:";
1156     code += GenIndents(5) + one_instance + " = " + field_type +
1157             "T.InitFromObj(" + struct_var + "." + field_method + "(i))";
1158     code +=
1159         GenIndents(5) + "self." + field_field + ".append(" + one_instance + ")";
1160   }
1161 
GenUnpackforScalarVectorHelper(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr,int indents) const1162   void GenUnpackforScalarVectorHelper(const StructDef &struct_def,
1163                                       const FieldDef &field,
1164                                       std::string *code_ptr,
1165                                       int indents) const {
1166     auto &code = *code_ptr;
1167     const auto field_field = namer_.Field(field);
1168     const auto field_method = namer_.Method(field);
1169     const auto struct_var = namer_.Variable(struct_def);
1170 
1171     code += GenIndents(indents) + "self." + field_field + " = []";
1172     code += GenIndents(indents) + "for i in range(" + struct_var + "." +
1173             field_method + "Length()):";
1174     code += GenIndents(indents + 1) + "self." + field_field + ".append(" +
1175             struct_var + "." + field_method + "(i))";
1176   }
1177 
GenUnPackForScalarVector(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const1178   void GenUnPackForScalarVector(const StructDef &struct_def,
1179                                 const FieldDef &field,
1180                                 std::string *code_ptr) const {
1181     auto &code = *code_ptr;
1182     const auto field_field = namer_.Field(field);
1183     const auto field_method = namer_.Method(field);
1184     const auto struct_var = namer_.Variable(struct_def);
1185 
1186     code += GenIndents(2) + "if not " + struct_var + "." + field_method +
1187             "IsNone():";
1188 
1189     // String does not have the AsNumpy method.
1190     if (!(IsScalar(field.value.type.VectorType().base_type))) {
1191       GenUnpackforScalarVectorHelper(struct_def, field, code_ptr, 3);
1192       return;
1193     }
1194 
1195     code += GenIndents(3) + "if np is None:";
1196     GenUnpackforScalarVectorHelper(struct_def, field, code_ptr, 4);
1197 
1198     // If numpy exists, use the AsNumpy method to optimize the unpack speed.
1199     code += GenIndents(3) + "else:";
1200     code += GenIndents(4) + "self." + field_field + " = " + struct_var + "." +
1201             field_method + "AsNumpy()";
1202   }
1203 
GenUnPackForScalar(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr) const1204   void GenUnPackForScalar(const StructDef &struct_def, const FieldDef &field,
1205                           std::string *code_ptr) const {
1206     auto &code = *code_ptr;
1207     const auto field_field = namer_.Field(field);
1208     const auto field_method = namer_.Method(field);
1209     const auto struct_var = namer_.Variable(struct_def);
1210 
1211     code += GenIndents(2) + "self." + field_field + " = " + struct_var + "." +
1212             field_method + "()";
1213   }
1214 
1215   // Generates the UnPack method for the object class.
GenUnPack(const StructDef & struct_def,std::string * code_ptr) const1216   void GenUnPack(const StructDef &struct_def, std::string *code_ptr) const {
1217     std::string code;
1218     // Items that needs to be imported. No duplicate modules will be imported.
1219     std::set<std::string> import_list;
1220 
1221     for (auto it = struct_def.fields.vec.begin();
1222          it != struct_def.fields.vec.end(); ++it) {
1223       auto &field = **it;
1224       if (field.deprecated) continue;
1225 
1226       auto field_type = TypeName(field);
1227       switch (field.value.type.base_type) {
1228         case BASE_TYPE_STRUCT: {
1229           GenUnPackForStruct(struct_def, field, &code);
1230           break;
1231         }
1232         case BASE_TYPE_UNION: {
1233           GenUnPackForUnion(struct_def, field, &code);
1234           break;
1235         }
1236         case BASE_TYPE_VECTOR: {
1237           auto vectortype = field.value.type.VectorType();
1238           if (vectortype.base_type == BASE_TYPE_STRUCT) {
1239             GenUnPackForStructVector(struct_def, field, &code);
1240           } else {
1241             GenUnPackForScalarVector(struct_def, field, &code);
1242           }
1243           break;
1244         }
1245         case BASE_TYPE_ARRAY: {
1246           GenUnPackForScalarVector(struct_def, field, &code);
1247           break;
1248         }
1249         default: GenUnPackForScalar(struct_def, field, &code);
1250       }
1251     }
1252 
1253     // Writes import statements and code into the generated file.
1254     auto &code_base = *code_ptr;
1255     const auto struct_var = namer_.Variable(struct_def);
1256 
1257     GenReceiverForObjectAPI(struct_def, code_ptr);
1258     code_base += "_UnPack(self, " + struct_var + "):";
1259     code_base += GenIndents(2) + "if " + struct_var + " is None:";
1260     code_base += GenIndents(3) + "return";
1261 
1262     // Write the import statements.
1263     for (std::set<std::string>::iterator it = import_list.begin();
1264          it != import_list.end(); ++it) {
1265       code_base += GenIndents(2) + *it;
1266     }
1267 
1268     // Write the code.
1269     code_base += code;
1270     code_base += "\n";
1271   }
1272 
GenPackForStruct(const StructDef & struct_def,std::string * code_ptr) const1273   void GenPackForStruct(const StructDef &struct_def,
1274                         std::string *code_ptr) const {
1275     auto &code = *code_ptr;
1276     const auto struct_fn = namer_.Function(struct_def);
1277 
1278     GenReceiverForObjectAPI(struct_def, code_ptr);
1279     code += "Pack(self, builder):";
1280     code += GenIndents(2) + "return Create" + struct_fn + "(builder";
1281 
1282     StructBuilderArgs(struct_def,
1283                       /* nameprefix = */ "self.",
1284                       /* namesuffix = */ "",
1285                       /* has_field_name = */ true,
1286                       /* fieldname_suffix = */ ".", code_ptr);
1287     code += ")\n";
1288   }
1289 
GenPackForStructVectorField(const StructDef & struct_def,const FieldDef & field,std::string * code_prefix_ptr,std::string * code_ptr) const1290   void GenPackForStructVectorField(const StructDef &struct_def,
1291                                    const FieldDef &field,
1292                                    std::string *code_prefix_ptr,
1293                                    std::string *code_ptr) const {
1294     auto &code_prefix = *code_prefix_ptr;
1295     auto &code = *code_ptr;
1296     const auto field_field = namer_.Field(field);
1297     const auto struct_type = namer_.Type(struct_def);
1298     const auto field_method = namer_.Method(field);
1299 
1300     // Creates the field.
1301     code_prefix += GenIndents(2) + "if self." + field_field + " is not None:";
1302     if (field.value.type.struct_def->fixed) {
1303       code_prefix += GenIndents(3) + struct_type + "Start" + field_method +
1304                      "Vector(builder, len(self." + field_field + "))";
1305       code_prefix += GenIndents(3) + "for i in reversed(range(len(self." +
1306                      field_field + "))):";
1307       code_prefix +=
1308           GenIndents(4) + "self." + field_field + "[i].Pack(builder)";
1309       code_prefix += GenIndents(3) + field_field + " = builder.EndVector()";
1310     } else {
1311       // If the vector is a struct vector, we need to first build accessor for
1312       // each struct element.
1313       code_prefix += GenIndents(3) + field_field + "list = []";
1314       code_prefix += GenIndents(3);
1315       code_prefix += "for i in range(len(self." + field_field + ")):";
1316       code_prefix += GenIndents(4) + field_field + "list.append(self." +
1317                      field_field + "[i].Pack(builder))";
1318 
1319       code_prefix += GenIndents(3) + struct_type + "Start" + field_method +
1320                      "Vector(builder, len(self." + field_field + "))";
1321       code_prefix += GenIndents(3) + "for i in reversed(range(len(self." +
1322                      field_field + "))):";
1323       code_prefix += GenIndents(4) + "builder.PrependUOffsetTRelative" + "(" +
1324                      field_field + "list[i])";
1325       code_prefix += GenIndents(3) + field_field + " = builder.EndVector()";
1326     }
1327 
1328     // Adds the field into the struct.
1329     code += GenIndents(2) + "if self." + field_field + " is not None:";
1330     code += GenIndents(3) + struct_type + "Add" + field_method + "(builder, " +
1331             field_field + ")";
1332   }
1333 
GenPackForScalarVectorFieldHelper(const StructDef & struct_def,const FieldDef & field,std::string * code_ptr,int indents) const1334   void GenPackForScalarVectorFieldHelper(const StructDef &struct_def,
1335                                          const FieldDef &field,
1336                                          std::string *code_ptr,
1337                                          int indents) const {
1338     auto &code = *code_ptr;
1339     const auto field_field = namer_.Field(field);
1340     const auto field_method = namer_.Method(field);
1341     const auto struct_type = namer_.Type(struct_def);
1342     const auto vectortype = field.value.type.VectorType();
1343 
1344     code += GenIndents(indents) + struct_type + "Start" + field_method +
1345             "Vector(builder, len(self." + field_field + "))";
1346     code += GenIndents(indents) + "for i in reversed(range(len(self." +
1347             field_field + "))):";
1348     code += GenIndents(indents + 1) + "builder.Prepend";
1349 
1350     std::string type_name;
1351     switch (vectortype.base_type) {
1352       case BASE_TYPE_BOOL: type_name = "Bool"; break;
1353       case BASE_TYPE_CHAR: type_name = "Byte"; break;
1354       case BASE_TYPE_UCHAR: type_name = "Uint8"; break;
1355       case BASE_TYPE_SHORT: type_name = "Int16"; break;
1356       case BASE_TYPE_USHORT: type_name = "Uint16"; break;
1357       case BASE_TYPE_INT: type_name = "Int32"; break;
1358       case BASE_TYPE_UINT: type_name = "Uint32"; break;
1359       case BASE_TYPE_LONG: type_name = "Int64"; break;
1360       case BASE_TYPE_ULONG: type_name = "Uint64"; break;
1361       case BASE_TYPE_FLOAT: type_name = "Float32"; break;
1362       case BASE_TYPE_DOUBLE: type_name = "Float64"; break;
1363       case BASE_TYPE_STRING: type_name = "UOffsetTRelative"; break;
1364       default: type_name = "VOffsetT"; break;
1365     }
1366     code += type_name;
1367   }
1368 
GenPackForScalarVectorField(const StructDef & struct_def,const FieldDef & field,std::string * code_prefix_ptr,std::string * code_ptr) const1369   void GenPackForScalarVectorField(const StructDef &struct_def,
1370                                    const FieldDef &field,
1371                                    std::string *code_prefix_ptr,
1372                                    std::string *code_ptr) const {
1373     auto &code = *code_ptr;
1374     auto &code_prefix = *code_prefix_ptr;
1375     const auto field_field = namer_.Field(field);
1376     const auto field_method = namer_.Method(field);
1377     const auto struct_type = namer_.Type(struct_def);
1378 
1379     // Adds the field into the struct.
1380     code += GenIndents(2) + "if self." + field_field + " is not None:";
1381     code += GenIndents(3) + struct_type + "Add" + field_method + "(builder, " +
1382             field_field + ")";
1383 
1384     // Creates the field.
1385     code_prefix += GenIndents(2) + "if self." + field_field + " is not None:";
1386     // If the vector is a string vector, we need to first build accessor for
1387     // each string element. And this generated code, needs to be
1388     // placed ahead of code_prefix.
1389     auto vectortype = field.value.type.VectorType();
1390     if (IsString(vectortype)) {
1391       code_prefix += GenIndents(3) + field_field + "list = []";
1392       code_prefix +=
1393           GenIndents(3) + "for i in range(len(self." + field_field + ")):";
1394       code_prefix += GenIndents(4) + field_field +
1395                      "list.append(builder.CreateString(self." + field_field +
1396                      "[i]))";
1397       GenPackForScalarVectorFieldHelper(struct_def, field, code_prefix_ptr, 3);
1398       code_prefix += "(" + field_field + "list[i])";
1399       code_prefix += GenIndents(3) + field_field + " = builder.EndVector()";
1400       return;
1401     }
1402 
1403     code_prefix += GenIndents(3) + "if np is not None and type(self." +
1404                    field_field + ") is np.ndarray:";
1405     code_prefix += GenIndents(4) + field_field +
1406                    " = builder.CreateNumpyVector(self." + field_field + ")";
1407     code_prefix += GenIndents(3) + "else:";
1408     GenPackForScalarVectorFieldHelper(struct_def, field, code_prefix_ptr, 4);
1409     code_prefix += "(self." + field_field + "[i])";
1410     code_prefix += GenIndents(4) + field_field + " = builder.EndVector()";
1411   }
1412 
GenPackForStructField(const StructDef & struct_def,const FieldDef & field,std::string * code_prefix_ptr,std::string * code_ptr) const1413   void GenPackForStructField(const StructDef &struct_def, const FieldDef &field,
1414                              std::string *code_prefix_ptr,
1415                              std::string *code_ptr) const {
1416     auto &code_prefix = *code_prefix_ptr;
1417     auto &code = *code_ptr;
1418     const auto field_field = namer_.Field(field);
1419     const auto field_method = namer_.Method(field);
1420     const auto struct_type = namer_.Type(struct_def);
1421 
1422     if (field.value.type.struct_def->fixed) {
1423       // Pure struct fields need to be created along with their parent
1424       // structs.
1425       code += GenIndents(2) + "if self." + field_field + " is not None:";
1426       code += GenIndents(3) + field_field + " = self." + field_field +
1427               ".Pack(builder)";
1428     } else {
1429       // Tables need to be created before their parent structs are created.
1430       code_prefix += GenIndents(2) + "if self." + field_field + " is not None:";
1431       code_prefix += GenIndents(3) + field_field + " = self." + field_field +
1432                      ".Pack(builder)";
1433       code += GenIndents(2) + "if self." + field_field + " is not None:";
1434     }
1435 
1436     code += GenIndents(3) + struct_type + "Add" + field_method + "(builder, " +
1437             field_field + ")";
1438   }
1439 
GenPackForUnionField(const StructDef & struct_def,const FieldDef & field,std::string * code_prefix_ptr,std::string * code_ptr) const1440   void GenPackForUnionField(const StructDef &struct_def, const FieldDef &field,
1441                             std::string *code_prefix_ptr,
1442                             std::string *code_ptr) const {
1443     auto &code_prefix = *code_prefix_ptr;
1444     auto &code = *code_ptr;
1445     const auto field_field = namer_.Field(field);
1446     const auto field_method = namer_.Method(field);
1447     const auto struct_type = namer_.Type(struct_def);
1448 
1449     // TODO(luwa): TypeT should be moved under the None check as well.
1450     code_prefix += GenIndents(2) + "if self." + field_field + " is not None:";
1451     code_prefix += GenIndents(3) + field_field + " = self." + field_field +
1452                    ".Pack(builder)";
1453     code += GenIndents(2) + "if self." + field_field + " is not None:";
1454     code += GenIndents(3) + struct_type + "Add" + field_method + "(builder, " +
1455             field_field + ")";
1456   }
1457 
GenPackForTable(const StructDef & struct_def,std::string * code_ptr) const1458   void GenPackForTable(const StructDef &struct_def,
1459                        std::string *code_ptr) const {
1460     auto &code_base = *code_ptr;
1461     std::string code, code_prefix;
1462     const auto struct_var = namer_.Variable(struct_def);
1463     const auto struct_type = namer_.Type(struct_def);
1464 
1465     GenReceiverForObjectAPI(struct_def, code_ptr);
1466     code_base += "Pack(self, builder):";
1467     code += GenIndents(2) + struct_type + "Start(builder)";
1468     for (auto it = struct_def.fields.vec.begin();
1469          it != struct_def.fields.vec.end(); ++it) {
1470       auto &field = **it;
1471       if (field.deprecated) continue;
1472 
1473       const auto field_method = namer_.Method(field);
1474       const auto field_field = namer_.Field(field);
1475 
1476       switch (field.value.type.base_type) {
1477         case BASE_TYPE_STRUCT: {
1478           GenPackForStructField(struct_def, field, &code_prefix, &code);
1479           break;
1480         }
1481         case BASE_TYPE_UNION: {
1482           GenPackForUnionField(struct_def, field, &code_prefix, &code);
1483           break;
1484         }
1485         case BASE_TYPE_VECTOR: {
1486           auto vectortype = field.value.type.VectorType();
1487           if (vectortype.base_type == BASE_TYPE_STRUCT) {
1488             GenPackForStructVectorField(struct_def, field, &code_prefix, &code);
1489           } else {
1490             GenPackForScalarVectorField(struct_def, field, &code_prefix, &code);
1491           }
1492           break;
1493         }
1494         case BASE_TYPE_ARRAY: {
1495           GenPackForScalarVectorField(struct_def, field, &code_prefix, &code);
1496           break;
1497         }
1498         case BASE_TYPE_STRING: {
1499           code_prefix +=
1500               GenIndents(2) + "if self." + field_field + " is not None:";
1501           code_prefix += GenIndents(3) + field_field +
1502                          " = builder.CreateString(self." + field_field + ")";
1503           code += GenIndents(2) + "if self." + field_field + " is not None:";
1504           code += GenIndents(3) + struct_type + "Add" + field_method +
1505                   "(builder, " + field_field + ")";
1506           break;
1507         }
1508         default:
1509           // Generates code for scalar values. If the value equals to the
1510           // default value, builder will automatically ignore it. So we don't
1511           // need to check the value ahead.
1512           code += GenIndents(2) + struct_type + "Add" + field_method +
1513                   "(builder, self." + field_field + ")";
1514           break;
1515       }
1516     }
1517 
1518     code += GenIndents(2) + struct_var + " = " + struct_type + "End(builder)";
1519     code += GenIndents(2) + "return " + struct_var;
1520 
1521     code_base += code_prefix + code;
1522     code_base += "\n";
1523   }
1524 
GenStructForObjectAPI(const StructDef & struct_def,std::string * code_ptr) const1525   void GenStructForObjectAPI(const StructDef &struct_def,
1526                              std::string *code_ptr) const {
1527     if (struct_def.generated) return;
1528 
1529     std::set<std::string> import_list;
1530     std::string code;
1531 
1532     // Creates an object class for a struct or a table
1533     BeginClassForObjectAPI(struct_def, &code);
1534 
1535     GenInitialize(struct_def, &code, &import_list);
1536 
1537     InitializeFromBuf(struct_def, &code);
1538 
1539     InitializeFromObjForObject(struct_def, &code);
1540 
1541     GenUnPack(struct_def, &code);
1542 
1543     if (struct_def.fixed) {
1544       GenPackForStruct(struct_def, &code);
1545     } else {
1546       GenPackForTable(struct_def, &code);
1547     }
1548 
1549     // Adds the imports at top.
1550     auto &code_base = *code_ptr;
1551     code_base += "\n";
1552     for (auto it = import_list.begin(); it != import_list.end(); it++) {
1553       auto im = *it;
1554       code_base += im + "\n";
1555     }
1556     code_base += code;
1557   }
1558 
GenUnionCreatorForStruct(const EnumDef & enum_def,const EnumVal & ev,std::string * code_ptr) const1559   void GenUnionCreatorForStruct(const EnumDef &enum_def, const EnumVal &ev,
1560                                 std::string *code_ptr) const {
1561     auto &code = *code_ptr;
1562     const auto union_type = namer_.Type(enum_def);
1563     const auto variant = namer_.Variant(ev);
1564     auto field_type = namer_.ObjectType(*ev.union_type.struct_def);
1565 
1566     code +=
1567         GenIndents(1) + "if unionType == " + union_type + "()." + variant + ":";
1568     if (parser_.opts.include_dependence_headers) {
1569       auto package_reference = GenPackageReference(ev.union_type);
1570       code += GenIndents(2) + "import " + package_reference;
1571       field_type = package_reference + "." + field_type;
1572     }
1573     code += GenIndents(2) + "return " + field_type +
1574             ".InitFromBuf(table.Bytes, table.Pos)";
1575   }
1576 
GenUnionCreatorForString(const EnumDef & enum_def,const EnumVal & ev,std::string * code_ptr) const1577   void GenUnionCreatorForString(const EnumDef &enum_def, const EnumVal &ev,
1578                                 std::string *code_ptr) const {
1579     auto &code = *code_ptr;
1580     const auto union_type = namer_.Type(enum_def);
1581     const auto variant = namer_.Variant(ev);
1582 
1583     code +=
1584         GenIndents(1) + "if unionType == " + union_type + "()." + variant + ":";
1585     code += GenIndents(2) + "tab = Table(table.Bytes, table.Pos)";
1586     code += GenIndents(2) + "union = tab.String(table.Pos)";
1587     code += GenIndents(2) + "return union";
1588   }
1589 
1590   // Creates an union object based on union type.
GenUnionCreator(const EnumDef & enum_def,std::string * code_ptr) const1591   void GenUnionCreator(const EnumDef &enum_def, std::string *code_ptr) const {
1592     if (enum_def.generated) return;
1593 
1594     auto &code = *code_ptr;
1595     const auto enum_fn = namer_.Function(enum_def);
1596 
1597     code += "\n";
1598     code += "def " + enum_fn + "Creator(unionType, table):";
1599     code += GenIndents(1) + "from flatbuffers.table import Table";
1600     code += GenIndents(1) + "if not isinstance(table, Table):";
1601     code += GenIndents(2) + "return None";
1602 
1603     for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
1604       auto &ev = **it;
1605       // Union only supports string and table.
1606       switch (ev.union_type.base_type) {
1607         case BASE_TYPE_STRUCT:
1608           GenUnionCreatorForStruct(enum_def, ev, &code);
1609           break;
1610         case BASE_TYPE_STRING:
1611           GenUnionCreatorForString(enum_def, ev, &code);
1612           break;
1613         default: break;
1614       }
1615     }
1616     code += GenIndents(1) + "return None";
1617     code += "\n";
1618   }
1619 
1620   // Generate enum declarations.
GenEnum(const EnumDef & enum_def,std::string * code_ptr) const1621   void GenEnum(const EnumDef &enum_def, std::string *code_ptr) const {
1622     if (enum_def.generated) return;
1623 
1624     GenComment(enum_def.doc_comment, code_ptr, &def_comment);
1625     BeginEnum(enum_def, code_ptr);
1626     for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
1627       auto &ev = **it;
1628       GenComment(ev.doc_comment, code_ptr, &def_comment, Indent.c_str());
1629       EnumMember(enum_def, ev, code_ptr);
1630     }
1631   }
1632 
1633   // Returns the function name that is able to read a value of the given type.
GenGetter(const Type & type) const1634   std::string GenGetter(const Type &type) const {
1635     switch (type.base_type) {
1636       case BASE_TYPE_STRING: return "self._tab.String(";
1637       case BASE_TYPE_UNION: return "self._tab.Union(";
1638       case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
1639       default:
1640         return "self._tab.Get(flatbuffers.number_types." +
1641                namer_.Method(GenTypeGet(type)) + "Flags, ";
1642     }
1643   }
1644 
1645   // Returns the method name for use with add/put calls.
GenMethod(const FieldDef & field) const1646   std::string GenMethod(const FieldDef &field) const {
1647     return (IsScalar(field.value.type.base_type) || IsArray(field.value.type))
1648                ? namer_.Method(GenTypeBasic(field.value.type))
1649                : (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative");
1650   }
1651 
GenTypeBasic(const Type & type) const1652   std::string GenTypeBasic(const Type &type) const {
1653     // clang-format off
1654     static const char *ctypename[] = {
1655       #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
1656               CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, ...) \
1657         #PTYPE,
1658         FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
1659       #undef FLATBUFFERS_TD
1660     };
1661     // clang-format on
1662     return ctypename[IsArray(type) ? type.VectorType().base_type
1663                                    : type.base_type];
1664   }
1665 
GenTypePointer(const Type & type) const1666   std::string GenTypePointer(const Type &type) const {
1667     switch (type.base_type) {
1668       case BASE_TYPE_STRING: return "string";
1669       case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
1670       case BASE_TYPE_STRUCT: return type.struct_def->name;
1671       case BASE_TYPE_UNION:
1672         // fall through
1673       default: return "*flatbuffers.Table";
1674     }
1675   }
1676 
GenTypeGet(const Type & type) const1677   std::string GenTypeGet(const Type &type) const {
1678     return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
1679   }
1680 
TypeName(const FieldDef & field) const1681   std::string TypeName(const FieldDef &field) const {
1682     return GenTypeGet(field.value.type);
1683   }
1684 
1685   // Create a struct with a builder and the struct's arguments.
GenStructBuilder(const StructDef & struct_def,std::string * code_ptr) const1686   void GenStructBuilder(const StructDef &struct_def,
1687                         std::string *code_ptr) const {
1688     BeginBuilderArgs(struct_def, code_ptr);
1689     StructBuilderArgs(struct_def,
1690                       /* nameprefix = */ "",
1691                       /* namesuffix = */ "",
1692                       /* has_field_name = */ true,
1693                       /* fieldname_suffix = */ "_", code_ptr);
1694     EndBuilderArgs(code_ptr);
1695 
1696     StructBuilderBody(struct_def, "", code_ptr);
1697     EndBuilderBody(code_ptr);
1698   }
1699 
generate()1700   bool generate() {
1701     std::string one_file_code;
1702     if (!generateEnums(&one_file_code)) return false;
1703     if (!generateStructs(&one_file_code)) return false;
1704 
1705     if (parser_.opts.one_file) {
1706       // Legacy file format uses keep casing.
1707       return SaveType(file_name_ + "_generated.py", *parser_.current_namespace_,
1708                       one_file_code, true);
1709     }
1710 
1711     return true;
1712   }
1713 
1714  private:
generateEnums(std::string * one_file_code) const1715   bool generateEnums(std::string *one_file_code) const {
1716     for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
1717          ++it) {
1718       auto &enum_def = **it;
1719       std::string enumcode;
1720       GenEnum(enum_def, &enumcode);
1721       if (parser_.opts.generate_object_based_api & enum_def.is_union) {
1722         GenUnionCreator(enum_def, &enumcode);
1723       }
1724 
1725       if (parser_.opts.one_file && !enumcode.empty()) {
1726         *one_file_code += enumcode + "\n\n";
1727       } else {
1728         if (!SaveType(namer_.File(enum_def, SkipFile::Suffix),
1729                       *enum_def.defined_namespace, enumcode, false))
1730           return false;
1731       }
1732     }
1733     return true;
1734   }
1735 
generateStructs(std::string * one_file_code) const1736   bool generateStructs(std::string *one_file_code) const {
1737     for (auto it = parser_.structs_.vec.begin();
1738          it != parser_.structs_.vec.end(); ++it) {
1739       auto &struct_def = **it;
1740       std::string declcode;
1741       GenStruct(struct_def, &declcode);
1742       if (parser_.opts.generate_object_based_api) {
1743         GenStructForObjectAPI(struct_def, &declcode);
1744       }
1745 
1746       if (parser_.opts.one_file && !declcode.empty()) {
1747         *one_file_code += declcode + "\n\n";
1748       } else {
1749         if (!SaveType(namer_.File(struct_def, SkipFile::Suffix),
1750                       *struct_def.defined_namespace, declcode, true))
1751           return false;
1752       }
1753     }
1754     return true;
1755   }
1756 
1757   // Begin by declaring namespace and imports.
BeginFile(const std::string & name_space_name,const bool needs_imports,std::string * code_ptr) const1758   void BeginFile(const std::string &name_space_name, const bool needs_imports,
1759                  std::string *code_ptr) const {
1760     auto &code = *code_ptr;
1761     code = code + "# " + FlatBuffersGeneratedWarning() + "\n\n";
1762     code += "# namespace: " + name_space_name + "\n\n";
1763     if (needs_imports) {
1764       code += "import flatbuffers\n";
1765       code += "from flatbuffers.compat import import_numpy\n";
1766       code += "np = import_numpy()\n\n";
1767     }
1768   }
1769 
1770   // Save out the generated code for a Python Table type.
SaveType(const std::string & defname,const Namespace & ns,const std::string & classcode,bool needs_imports) const1771   bool SaveType(const std::string &defname, const Namespace &ns,
1772                 const std::string &classcode, bool needs_imports) const {
1773     if (!classcode.length()) return true;
1774 
1775     std::string code = "";
1776     BeginFile(LastNamespacePart(ns), needs_imports, &code);
1777     code += classcode;
1778 
1779     const std::string directories =
1780         parser_.opts.one_file ? path_ : namer_.Directories(ns.components);
1781     EnsureDirExists(directories);
1782 
1783     for (size_t i = path_.size() + 1; i != std::string::npos;
1784          i = directories.find(kPathSeparator, i + 1)) {
1785       const std::string init_py =
1786           directories.substr(0, i) + kPathSeparator + "__init__.py";
1787       SaveFile(init_py.c_str(), "", false);
1788     }
1789 
1790     const std::string filename = directories + defname;
1791     return SaveFile(filename.c_str(), code, false);
1792   }
1793 
1794  private:
1795   const SimpleFloatConstantGenerator float_const_gen_;
1796   const IdlNamer namer_;
1797 };
1798 
1799 }  // namespace python
1800 
GeneratePython(const Parser & parser,const std::string & path,const std::string & file_name)1801 bool GeneratePython(const Parser &parser, const std::string &path,
1802                     const std::string &file_name) {
1803   python::PythonGenerator generator(parser, path, file_name);
1804   return generator.generate();
1805 }
1806 
1807 }  // namespace flatbuffers
1808