Он похож не готова библиотеки с моими требованиями, поэтому в конечном итоге с собственной реализацией:
class ApplicationError(Fault):
def __init__(self, exc_info):
Fault.__init__(self, xmlrpclib.APPLICATION_ERROR,
u'Application internal error')
class NotWellformedError(Fault):
def __init__(self, exc):
Fault.__init__(self, xmlrpclib.NOT_WELLFORMED_ERROR, str(exc))
class UnsupportedEncoding(Fault):
def __init__(self, exc):
Fault.__init__(self, xmlrpclib.UNSUPPORTED_ENCODING, str(exc))
# XXX INVALID_ENCODING_CHAR is masked by xmlrpclib, so the error code will be
# INVALID_XMLRPC.
class InvalidRequest(Fault):
def __init__(self, message):
ault.__init__(self, xmlrpclib.INVALID_XMLRPC, message)
class MethodNotFound(Fault):
def __init__(self, name):
Fault.__init__(self, xmlrpclib.METHOD_NOT_FOUND,
u'Method %r is not supported' % name)
class WrongMethodUsage(Fault):
def __init__(self, message):
Fault.__init__(self, xmlrpclib.INVALID_METHOD_PARAMS, message)
class WrongType(Fault):
def __init__(self, arg_name, type_name):
Fault.__init__(self, xmlrpclib.INVALID_METHOD_PARAMS,
u'Parameter %s must be %s' % (arg_name, type_name))
class XMLRPCDispatcher(SimpleXMLRPCDispatcher, XMLRPCDocGenerator):
server_name = server_title = 'Personalization center RPC interface'
server_documentation = 'Available methods'
def __init__(self, methods):
SimpleXMLRPCDispatcher.__init__(self, allow_none=True, encoding=None)
self.register_instance(methods)
self.register_multicall_functions()
#self.register_introspection_functions()
def _dispatch(self, method_name, args):
if self.funcs.has_key(method_name):
method = self.funcs[method_name]
else:
method = self.instance._getMethod(method_name)
arg_names, args_name, kwargs_name, defaults = \
inspect.getargspec(method)
assert arg_names[0]=='self'
arg_names = arg_names[1:]
n_args = len(args)
if not (args_name or defaults):
if n_args!=len(arg_names):
raise WrongMethodUsage(
u'Method %s takes exactly %d parameters (%d given)' % \
(method_name, len(arg_names), n_args))
else:
min_args = len(arg_names)-len(defaults)
if len(args)<min_args:
raise WrongMethodUsage(
u'Method %s requires at least %d parameters (%d given)' % \
(method_name, min_args, n_args))
if not args_name and n_args>len(arg_names):
raise WrongMethodUsage(
u'Method %s requires at most %d parameters (%d given)' % \
(method_name, len(arg_names), n_args))
try:
return method(*args)
except Fault:
raise
except:
logger.exception('Application internal error for %s%r',
method_name, args)
raise ApplicationError(sys.exc_info())
def dispatch(self, data):
try:
try:
args, method_name = xmlrpclib.loads(data)
except ExpatError, exc:
raise NotWellformedError(exc)
except LookupError, exc:
raise UnsupportedEncoding(exc)
except xmlrpclib.ResponseError:
raise InvalidRequest('Request structure is invalid')
method_name = method_name.encode('ascii', 'replace')
result = self._dispatch(method_name, args)
except Fault, exc:
logger.warning('Fault %s: %s', exc.faultCode, exc.faultString)
return xmlrpclib.dumps(exc)
else:
try:
return xmlrpclib.dumps((result,), methodresponse=1)
except:
logger.exception('Application internal error when marshalling'\
' result for %s%r', method_name, args)
return xmlrpclib.dumps(ApplicationError(sys.exc_info()))
class InterfaceMethods:
def _getMethod(self, name):
if name.startswith('_'):
raise MethodNotFound(name)
try:
method = getattr(self, name)
except AttributeError:
raise MethodNotFound(name)
if not inspect.ismethod(method):
raise MethodNotFound(name)
return method
Затем они попытаются описать что-то, потерпят неудачу, и вы, наконец, закончите с возможностью ведения журнала (возможно, огромных запросов), чтобы увидеть, что они на самом деле делают. Представьте себе сотни таких клиентов. Некоторые из них будут развиваться шаг за шагом, преодолевая все ошибки, которые вы можете себе представить, и даже больше. –