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;
}
}