void t_py_generator::generate_py_thrift_spec()

in thrift/compiler/generate/t_py_generator.cc [1449:1591]


void t_py_generator::generate_py_thrift_spec(
    ofstream& out, const t_struct* tstruct, bool /*is_exception*/) {
  const vector<t_field*>& members = tstruct->get_members();
  const vector<t_field*>& sorted_members = tstruct->get_sorted_members();
  vector<t_field*>::const_iterator m_iter;

  indent(out) << "all_structs.append("
              << rename_reserved_keywords(tstruct->get_name()) << ")" << endl
              << rename_reserved_keywords(tstruct->get_name())
              << ".thrift_spec = (" << endl;

  indent_up();

  int sorted_keys_pos = 0;
  for (m_iter = sorted_members.begin(); m_iter != sorted_members.end();
       ++m_iter) {
    if (sorted_keys_pos >= 0 && (*m_iter)->get_key() < 0) {
      sorted_keys_pos = (*m_iter)->get_key();
    }

    for (; sorted_keys_pos != (*m_iter)->get_key(); sorted_keys_pos++) {
      indent(out) << "None, # " << sorted_keys_pos << endl;
    }

    indent(out) << "(" << (*m_iter)->get_key() << ", "
                << type_to_enum((*m_iter)->get_type()) << ", "
                << "'" << rename_reserved_keywords((*m_iter)->get_name()) << "'"
                << ", " << type_to_spec_args((*m_iter)->get_type()) << ", "
                << render_field_default_value(*m_iter) << ", "
                << static_cast<int>((*m_iter)->get_req()) << ", ),"
                << " # " << sorted_keys_pos << endl;

    sorted_keys_pos++;
  }

  indent_down();
  indent(out) << ")" << endl << endl;

  generate_py_annotations(out, tstruct);

  if (members.size() > 0) {
    out << indent() << "def " << rename_reserved_keywords(tstruct->get_name())
        << "__init__(self,";
    if (members.size() > 255) {
      out << " **kwargs";
    } else {
      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
        // This fills in default values, as opposed to nulls
        out << " " << declare_argument(tstruct, *m_iter) << ",";
      }
    }
    out << "):" << endl;

    indent_up();

    if (members.size() > 255) {
      for (const auto& member : members) {
        indent(out) << rename_reserved_keywords(member->get_name())
                    << " = kwargs.pop(\n";
        indent(out) << "  \"" << rename_reserved_keywords(member->get_name())
                    << "\",\n";
        if (member->get_value() != nullptr) {
          indent(out) << "  " << rename_reserved_keywords(tstruct->get_name())
                      << ".thrift_spec[" << get_thrift_spec_key(tstruct, member)
                      << "][4],\n";
        } else {
          indent(out) << "  None,\n";
        }
        indent(out) << ")\n";
      }
      indent(out) << "if kwargs:\n";
      indent(out) << "  key, _value = kwargs.popitem()\n";
      indent(out)
          << "  raise TypeError(\"{}() got an unexpected keyword argument '{}'\".format(\""
          << rename_reserved_keywords(tstruct->get_name())
          << "__init__\", key))\n";
    }

    if (tstruct->is_union()) {
      indent(out) << "self.field = 0" << endl;
      indent(out) << "self.value = None" << endl;

      for (auto& member : sorted_members) {
        indent(out) << "if " << rename_reserved_keywords(member->get_name())
                    << " is not None:" << endl;
        indent(out) << "  assert self.field == 0 and self.value is None"
                    << endl;
        indent(out) << "  self.field = " << member->get_key() << endl;
        indent(out) << "  self.value = "
                    << rename_reserved_keywords(member->get_name()) << endl;
      }
    } else {
      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
        // Initialize fields
        const t_type* type = (*m_iter)->get_type();
        if (!type->is_base_type() && !type->is_enum() &&
            (*m_iter)->get_value() != nullptr) {
          indent(out) << "if "
                      << rename_reserved_keywords((*m_iter)->get_name())
                      << " is self.thrift_spec["
                      << get_thrift_spec_key(tstruct, *m_iter)
                      << "][4]:" << endl;
          indent(out) << "  " << rename_reserved_keywords((*m_iter)->get_name())
                      << " = " << render_field_default_value(*m_iter) << endl;
        }
        indent(out) << "self."
                    << rename_reserved_keywords((*m_iter)->get_name()) << " = "
                    << rename_reserved_keywords((*m_iter)->get_name()) << endl;
      }
    }
    indent_down();

    out << endl;
    out << indent() << rename_reserved_keywords(tstruct->get_name())
        << ".__init__ = " << rename_reserved_keywords(tstruct->get_name())
        << "__init__" << endl
        << endl;
  }

  // ThriftStruct.__setstate__: Ensure that unpickled objects have all expected
  // fields.
  if (members.size() > 0 && !tstruct->is_union() && !gen_slots_) {
    out << indent() << "def " << rename_reserved_keywords(tstruct->get_name())
        << "__setstate__(self, state):" << endl;

    indent_up();
    for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
      indent(out) << "state.setdefault('"
                  << rename_reserved_keywords((*m_iter)->get_name()) << "', "
                  << render_field_default_value(*m_iter) << ")" << endl;
    }
    indent(out) << "self.__dict__ = state" << endl;
    indent_down();

    out << endl;
    out << indent() << rename_reserved_keywords(tstruct->get_name())
        << ".__getstate__ = lambda self: self.__dict__.copy()" << endl;
    out << indent() << rename_reserved_keywords(tstruct->get_name())
        << ".__setstate__ = " << rename_reserved_keywords(tstruct->get_name())
        << "__setstate__" << endl
        << endl;
  }
}