code: def send_reply(*types, **options):
      
      major = options.pop('major', DEFAULT_KATCP_MAJOR)
      if len(options) > 0:
          raise TypeError('send_reply does not take keyword argument(s) %r.'
                          % options.keys())
  
      def decorator(handler):
          @wraps(handler)
          def raw_handler(self, *args):
              reply_args = handler(self, *args)
              req = reply_args[0]
              reply = make_reply(req.msg.name, types, reply_args[1:], major)
              req.reply_with_message(reply)
          return raw_handler
  
      return decorator
docs: Decorator for sending replies from request callback methods.
  
      This decorator constructs a reply from a list or tuple returned
      from a callback method, but unlike the return_reply decorator it
      also sends the reply rather than returning it.
  
      The list/tuple returned from the callback method must have req (a
      ClientRequestConnection instance) as its first parameter and the original
      message as the second. The original message is needed to determine the
      message name and ID.
  
      The device with the callback method must have a reply method.
  
      Parameters
      ----------
      types : list of kattypes
          The types of the reply message parameters (in order).
  
      Keyword Arguments
      -----------------
      major : int, optional
          Major version of KATCP to use when interpreting types.
          Defaults to latest implemented KATCP version.
  
      Examples
      --------
      >>> class MyDevice(DeviceServer):
      ...     @send_reply(Int(), Float())
      ...     def my_callback(self, req):
      ...         return (req, "ok", 5, 2.0)
      ...