...

Text file src/github.com/google/flatbuffers/src/idl_gen_python.cpp

Documentation: github.com/google/flatbuffers/src

     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