mirage / ocaml-rpc

Light library to deal with RPCs in OCaml
ISC License
95 stars 30 forks source link

pythongen: Generated X_test methods return named parameters incorrectly #107

Closed gaborigloi closed 6 years ago

gaborigloi commented 6 years ago

The behaviour of the X_test Python classes does not match the generated type checking code. If the return parameter is named, the test class will put the return value into a dictionary under that name, however, the typechecking code will still expect the return value itself, not a dictionary. I think the behaviour of the type checking code is the correct one, because there is no need to name the returned value, because we only return one value. For this interface:

module Interface(R : Idl.RPC) = struct
  open R

  let int_p_named_1 = Idl.Param.mk ~name:"int1" ~description:["first int param"] Rpc.Types.int
  let int_p_named_2 = Idl.Param.mk ~name:"int2" ~description:["second int param"] Rpc.Types.int
  let int_p_result = Idl.Param.mk ~name:"int" ~description:["int result"] Rpc.Types.int

  let add = R.declare "add"
      ["Add two numbers"]
      (int_p_named_1 @-> int_p_named_2 @-> returning int_p_result Idl.DefaultError.err)

  let implementation = implement
      { Idl.Interface.name = "Calc"; namespace = Some "Calc"; description = ["interface"]; version = (1,0,0) }
end

This is generated: We can see the discrepancy between the typechecking code and Calc_test:

class Calc_server_dispatcher:
    """
    interface
    """

    def __init__(self, impl):
        """impl is a proxy object whose methods contain the implementation"""
        self._impl = impl
        self._dispatcher_dict = {
            "Calc.add": self.add
        }

    def add(self, args):
        """type-check inputs, call implementation, type-check outputs and return"""
        if not isinstance(args, dict):
            raise (UnmarshalException('arguments', 'dict', repr(args)))
        if "int1" not in args:
            raise UnmarshalException('argument missing', 'int1', '')
        int1 = args["int1"]
        if not isinstance(int1, (int, long)):
            raise (TypeError("int", repr(int1)))
        if "int2" not in args:
            raise UnmarshalException('argument missing', 'int2', '')
        int2 = args["int2"]
        if not isinstance(int2, (int, long)):
            raise (TypeError("int", repr(int2)))
        results = self._impl.add(int1, int2)
        if not isinstance(results, (int, long)):
            raise (TypeError("int", repr(results)))
        return results

    def _dispatch(self, method, params):
        """type check inputs, call implementation, type check outputs and return"""
        args = params[0]
        return success(self._dispatcher_dict[method](args))

class Calc_test:
    """
    interface
    """

    def __init__(self):
        pass

    def add(self, int1, int2):
        """
        Add two numbers
        """
        result = {}
        result["int"] = 0L
        return result