X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sfa%2Fserver%2Fxmlrpcapi.py;h=51893285a2e69018256ae69500a7557de869e6f7;hb=fd395e1944dcd49f10a4d5b27ce4983ad389fb96;hp=456cd42ddd3977d121a16876b45546b3f71c7e6b;hpb=e39e728991b762ae0b52b52b06655f0c7f1b7421;p=sfa.git diff --git a/sfa/server/xmlrpcapi.py b/sfa/server/xmlrpcapi.py index 456cd42d..51893285 100644 --- a/sfa/server/xmlrpcapi.py +++ b/sfa/server/xmlrpcapi.py @@ -3,7 +3,6 @@ # import string -import xmlrpclib # SOAP support is optional try: @@ -19,6 +18,7 @@ except ImportError: #from sfa.util.faults import SfaNotImplemented, SfaAPIError, SfaInvalidAPIMethod, SfaFault from sfa.util.faults import SfaInvalidAPIMethod, SfaAPIError, SfaFault from sfa.util.sfalogging import logger +from sfa.util.py23 import xmlrpc_client #################### # See "2.2 Characters" in the XML specification: @@ -27,8 +27,13 @@ from sfa.util.sfalogging import logger # avoiding # [#x7F-#x84], [#x86-#x9F], [#xFDD0-#xFDDF] -invalid_xml_ascii = map(chr, range(0x0, 0x8) + [0xB, 0xC] + range(0xE, 0x1F)) -xml_escape_table = string.maketrans("".join(invalid_xml_ascii), "?" * len(invalid_xml_ascii)) +invalid_codepoints = range(0x0, 0x8) + [0xB, 0xC] + range(0xE, 0x1F) +# broke with f24, somehow we get a unicode as an incoming string to be translated +str_xml_escape_table = string.maketrans("".join((chr(x) for x in invalid_codepoints)), + "?" * len(invalid_codepoints)) +# loosely inspired from +# http://stackoverflow.com/questions/1324067/how-do-i-get-str-translate-to-work-with-unicode-strings +unicode_xml_escape_table = { invalid : u"?" for invalid in invalid_codepoints} def xmlrpclib_escape(s, replace = string.replace): """ @@ -43,7 +48,11 @@ def xmlrpclib_escape(s, replace = string.replace): s = replace(s, ">", ">",) # Replace invalid 7-bit control characters with '?' - return s.translate(xml_escape_table) + if isinstance(s, str): + return s.translate(str_xml_escape_table) + else: + return s.translate(unicode_xml_escape_table) + def xmlrpclib_dump(self, value, write): """ @@ -71,47 +80,51 @@ def xmlrpclib_dump(self, value, write): if isinstance(value, Type): f(*args) return - raise TypeError, "cannot marshal %s objects" % type(value) + raise TypeError("cannot marshal %s objects" % type(value)) else: f(*args) # You can't hide from me! -xmlrpclib.Marshaller._Marshaller__dump = xmlrpclib_dump +# Note: not quite sure if this will still cause +# the expected behaviour under python3 +xmlrpc_client.Marshaller._Marshaller__dump = xmlrpclib_dump + class XmlrpcApi: """ - The XmlrpcApi class implements a basic xmlrpc (or soap) service + The XmlrpcApi class implements a basic xmlrpc (or soap) service """ protocol = None - - def __init__ (self, encoding="utf-8", methods='sfa.methods'): + + def __init__(self, encoding="utf-8", methods='sfa.methods'): self.encoding = encoding - self.source = None - + self.source = None + # flat list of method names - self.methods_module = methods_module = __import__(methods, fromlist=[methods]) + self.methods_module = methods_module = __import__( + methods, fromlist=[methods]) self.methods = methods_module.all - self.logger = logger - def callable(self, method): """ Return a new instance of the specified method. """ # Look up method if method not in self.methods: - raise SfaInvalidAPIMethod, method - + raise SfaInvalidAPIMethod(method) + # Get new instance of method try: classname = method.split(".")[-1] - module = __import__(self.methods_module.__name__ + "." + method, globals(), locals(), [classname]) + module = __import__(self.methods_module.__name__ + + "." + method, globals(), locals(), [classname]) callablemethod = getattr(module, classname)(self) return getattr(module, classname)(self) except (ImportError, AttributeError): - raise SfaInvalidAPIMethod, method + logger.log_exc("Error importing method: %s" % method) + raise SfaInvalidAPIMethod(method) def call(self, source, method, *args): """ @@ -123,25 +136,25 @@ class XmlrpcApi: self.source = source return function(*args) - def handle(self, source, data, method_map): """ Handle an XML-RPC or SOAP request from the specified source. """ # Parse request into method name and arguments try: - interface = xmlrpclib - self.protocol = 'xmlrpclib' - (args, method) = xmlrpclib.loads(data) - if method_map.has_key(method): + interface = xmlrpc_client + self.protocol = 'xmlrpc' + (args, method) = xmlrpc_client.loads(data) + if method in method_map: method = method_map[method] methodresponse = True - - except Exception, e: + + except Exception as e: if SOAPpy is not None: self.protocol = 'soap' interface = SOAPpy - (r, header, body, attrs) = parseSOAPRPC(data, header = 1, body = 1, attrs = 1) + (r, header, body, attrs) = parseSOAPRPC( + data, header=1, body=1, attrs=1) method = r._name args = r._aslist() # XXX Support named arguments @@ -150,35 +163,38 @@ class XmlrpcApi: try: result = self.call(source, method, *args) - except SfaFault, fault: - result = fault - except Exception, fault: - self.logger.log_exc("XmlrpcApi.handle has caught Exception") + except SfaFault as fault: + result = fault + logger.log_exc("XmlrpcApi.handle has caught Exception") + except Exception as fault: + logger.log_exc("XmlrpcApi.handle has caught Exception") result = SfaAPIError(fault) - # Return result response = self.prepare_response(result, method) return response - + def prepare_response(self, result, method=""): """ convert result to a valid xmlrpc or soap response - """ - - if self.protocol == 'xmlrpclib': + """ + + if self.protocol == 'xmlrpc': if not isinstance(result, SfaFault): result = (result,) - response = xmlrpclib.dumps(result, methodresponse = True, encoding = self.encoding, allow_none = 1) + response = xmlrpc_client.dumps( + result, methodresponse=True, encoding=self.encoding, allow_none=1) elif self.protocol == 'soap': if isinstance(result, Exception): - result = faultParameter(NS.ENV_T + ":Server", "Method Failed", method) - result._setDetail("Fault %d: %s" % (result.faultCode, result.faultString)) + result = faultParameter( + NS.ENV_T + ":Server", "Method Failed", method) + result._setDetail("Fault %d: %s" % + (result.faultCode, result.faultString)) else: - response = buildSOAP(kw = {'%sResponse' % method: {'Result': result}}, encoding = self.encoding) + response = buildSOAP( + kw={'%sResponse' % method: {'Result': result}}, encoding=self.encoding) else: if isinstance(result, Exception): - raise result - - return response + raise result + return response