void t_py_generator::generate_process_function()

in thrift/compiler/generate/t_py_generator.cc [2860:3040]


void t_py_generator::generate_process_function(
    const t_service* /*tservice*/,
    const t_function* tfunction,
    bool with_context,
    bool future) {
  const string& fn_name = tfunction->get_name();

  // Open function
  if (future) {
    indent(f_service_) << "def then_" << fn_name
                       << "(self, args, handler_ctx):" << endl;
  } else {
    indent(f_service_) << "@thrift_process_method(" << fn_name << "_args, "
                       << "oneway="
                       << (tfunction->qualifier() ==
                                   t_function_qualifier::one_way
                               ? "True"
                               : "False")
                       << (gen_asyncio_ ? ", asyncio=True" : "") << ")" << endl;

    f_service_ << indent() << "def process_" << fn_name
               << "(self, args, handler_ctx"
               << (gen_asyncio_ ? ", seqid, oprot, fn_name):" : "):") << endl;
  }
  indent_up();

  const t_struct* xs = tfunction->get_xceptions();
  const std::vector<t_field*>& xceptions = xs->get_members();
  vector<t_field*>::const_iterator x_iter;

  // Declare result for non oneway function
  if (tfunction->qualifier() != t_function_qualifier::one_way) {
    f_service_ << indent() << "result = " << fn_name + "_result()" << endl;
  }

  if (gen_asyncio_) {
    const t_struct* arg_struct = tfunction->get_paramlist();
    const std::vector<t_field*>& fields = arg_struct->get_members();
    vector<t_field*>::const_iterator f_iter;

    string handler =
        "self._handler." + rename_reserved_keywords(tfunction->get_name());

    string args_list = "";
    bool first = true;
    if (with_context) {
      args_list += "handler_ctx";
      first = false;
    }
    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
      if (first) {
        first = false;
      } else {
        args_list += ", ";
      }
      args_list += "args.";
      args_list += rename_reserved_keywords((*f_iter)->get_name());
    }

    f_service_ << indent() << "if should_run_on_thread(" << handler
               << "):" << endl
               << indent() << "  fut = self._loop.run_in_executor(None, "
               << handler << ", " << args_list << ")" << endl
               << indent() << "else:" << endl
               << indent() << "  fut = call_as_future(" << handler
               << ", self._loop, " << args_list << ")" << endl;

    if (tfunction->qualifier() != t_function_qualifier::one_way) {
      string known_exceptions = "{";
      int exc_num;
      for (exc_num = 0, x_iter = xceptions.begin(); x_iter != xceptions.end();
           ++x_iter, ++exc_num) {
        if (exc_num > 0) {
          known_exceptions += ", ";
        }
        known_exceptions += "'";
        known_exceptions += rename_reserved_keywords((*x_iter)->get_name());
        known_exceptions += "': ";
        known_exceptions += type_name((*x_iter)->get_type());
      }
      known_exceptions += "}";

      f_service_
          << indent() << "fut.add_done_callback("
          << "lambda f: write_results_after_future("
          << "result, self._event_handler, handler_ctx, seqid, oprot, fn_name, "
          << known_exceptions + ", f))" << endl;
    }
    f_service_ << indent() << "return fut" << endl;
    indent_down();
    f_service_ << endl;
  } else {
    // Try block to wrap call to handler
    f_service_ << indent() << "try:" << endl;
    indent_up();

    // Generate the function call
    const t_struct* arg_struct = tfunction->get_paramlist();
    const std::vector<t_field*>& fields = arg_struct->get_members();
    vector<t_field*>::const_iterator f_iter;

    string handler = (future ? "self._handler.future_" : "self._handler.") +
        rename_reserved_keywords(tfunction->get_name());

    f_service_ << indent();

    if (tfunction->qualifier() != t_function_qualifier::one_way &&
        !tfunction->get_returntype()->is_void()) {
      f_service_ << "result.success = ";
    }
    f_service_ << handler << "(";
    bool first = true;
    if (with_context) {
      f_service_ << "handler_ctx";
      first = false;
    }
    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
      if (first) {
        first = false;
      } else {
        f_service_ << ", ";
      }
      f_service_ << "args." << rename_reserved_keywords((*f_iter)->get_name());
    }
    f_service_ << ")" << (future ? ".result()" : "") << endl;

    indent_down();
    int exc_num;
    for (exc_num = 0, x_iter = xceptions.begin(); x_iter != xceptions.end();
         ++x_iter, ++exc_num) {
      f_service_ << indent() << "except " << type_name((*x_iter)->get_type())
                 << " as exc" << exc_num << ":" << endl;
      if (tfunction->qualifier() != t_function_qualifier::one_way) {
        indent_up();
        f_service_ << indent()
                   << "self._event_handler.handlerException(handler_ctx, '"
                   << fn_name << "', exc" << exc_num << ")" << endl
                   << indent() << "result."
                   << rename_reserved_keywords((*x_iter)->get_name())
                   << " = exc" << exc_num << endl;
        indent_down();
      } else {
        f_service_ << indent() << "pass" << endl;
      }
    }
    f_service_ << indent() << "except:" << endl
               << indent() << "  ex = sys.exc_info()[1]" << endl
               << indent()
               << "  self._event_handler.handlerError(handler_ctx, '" << fn_name
               << "', ex)" << endl
               << indent() << "  result = Thrift.TApplicationException(message="
               << "repr(ex))" << endl;
    if (tfunction->qualifier() != t_function_qualifier::one_way) {
      f_service_ << indent() << "return result" << endl;
    }

    // Close function
    indent_down();

    if (future) {
      f_service_ << endl;

      f_service_ << indent() << "@future_process_method(" << fn_name
                 << "_args, oneway="
                 << (tfunction->qualifier() == t_function_qualifier::one_way
                         ? "True"
                         : "False")
                 << ")" << endl;

      f_service_ << indent() << "def future_process_" << fn_name
                 << "(self, args, handler_ctx):" << endl;

      indent_up();
      f_service_ << indent() << "return self._executor.submit(self.then_"
                 << fn_name << ", args, handler_ctx)" << endl;
      indent_down();
    }

    f_service_ << endl;
  }
}