How can I create my custom xmlrpc fault error in python
Question: When using `xmlrpclib` in python an error on the server side is reported by
the client side as an `xmlrpclib.Fault`. A `division by zero` error in a
method on the server side (using `SimpleXMLRPCServer`) usually gives an output
like the following:

    
    
    xmlrpclib.Fault: <Fault 1: "<type 'exceptions.ZeroDivisionError'>:integer division or modulo by zero">
    

This is useful as it notes the type of error, but now _where_ it happened. How
is it possible to overwrite/modify the `xmlrpclib.Fault` method (in
`SimpleXMLRPCServer`?) so it reports the error e.g. as follows:

    
    
    xmlrpclib.Fault: <Fault 1: "<type 'exceptions.ZeroDivisionError'>:integer division or modulo by zero MODULE: myMethod.py  LINE: 657">
    

i.e. to include the name of the module the error appeared and the line number.
Is that possible to do on the server-side, without raising custom exceptions?
ANY error should reported in the same way on the client side.


Answer: If you use `SimpleXMLRPCServer`, you can override the internal
`_marshaled_dispatch` method to add information to the `Fault()` instance
generated:

This is the original method:

    
    
    def _marshaled_dispatch(self, data, dispatch_method = None, path = None):
        try:
            params, method = xmlrpclib.loads(data)
    
            # generate response
            if dispatch_method is not None:
                response = dispatch_method(method, params)
            else:
                response = self._dispatch(method, params)
            # wrap response in a singleton tuple
            response = (response,)
            response = xmlrpclib.dumps(response, methodresponse=1,
                                       allow_none=self.allow_none, encoding=self.encoding)
        except:
            # report low level exception back to server
            # (each dispatcher should have handled their own
            # exceptions)
            exc_type, exc_value = sys.exc_info()[:2]
            response = xmlrpclib.dumps(
                xmlrpclib.Fault(1, "%s:%s" % (exc_type, exc_value)),
                encoding=self.encoding, allow_none=self.allow_none)
        return response
    

You can subclass `SimpleXMLRPCServer.SimpleXMLRPCServer` and override this
method:

    
    
    import SimpleXMLRPCServer
    import sys
    import xmlrbclib
    
    class VerboseFaultXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):
        def _marshaled_dispatch(self, data, dispatch_method = None, path = None):
            try:
                params, method = xmlrpclib.loads(data)
    
                # generate response
                if dispatch_method is not None:
                    response = dispatch_method(method, params)
                else:
                    response = self._dispatch(method, params)
                # wrap response in a singleton tuple
                response = (response,)
                response = xmlrpclib.dumps(response, methodresponse=1,
                                           allow_none=self.allow_none, encoding=self.encoding)
            except:
                # report low level exception back to server
                # (each dispatcher should have handled their own
                # exceptions)
                exc_type, exc_value, tb = sys.exc_info()
                while tb.tb_next is not None:
                    tb = tb.tb_next  # find last frame of the traceback
                lineno = tb.tb_lineno
                code = tb.tb_frame.f_code
                filename = code.co_filename
                name = code.co_name
                response = xmlrpclib.dumps(
                    xmlrpclib.Fault(1, "%s:%s FILENAME: %s LINE: %s NAME: %s" % (
                        exc_type, exc_value, filename, lineno, name)),
                    encoding=self.encoding, allow_none=self.allow_none)
            return response
    

Then use `VerboseFaultXMLRPCServer` instead of
`SimpleXMLRPCServer.SimpleXMLRPCServer`.

