eric6/E5Network/E5XmlRpcClient.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7192
a22eee00b052
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/E5Network/E5XmlRpcClient.py	Sun Apr 14 15:09:21 2019 +0200
@@ -0,0 +1,126 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a xmlrpc client for Qt.
+"""
+
+from __future__ import unicode_literals
+try:
+    import xmlrpclib as xmlrpc
+except ImportError:
+    import xmlrpc.client as xmlrpc
+
+from PyQt5.QtCore import QObject, QUrl, QByteArray
+from PyQt5.QtNetwork import QNetworkAccessManager, \
+    QNetworkRequest, QNetworkReply
+
+from E5Network.E5NetworkProxyFactory import proxyAuthenticationRequired
+try:
+    from E5Network.E5SslErrorHandler import E5SslErrorHandler
+    SSL_AVAILABLE = True
+except ImportError:
+    SSL_AVAILABLE = False
+
+
+class E5XmlRpcClient(QObject):
+    """
+    Class implementing a xmlrpc client for Qt.
+    """
+    def __init__(self, url, parent=None):
+        """
+        Constructor
+        
+        @param url xmlrpc handler URL (string or QUrl)
+        @param parent parent object (QObject)
+        """
+        super(E5XmlRpcClient, self).__init__(parent)
+        
+        # attributes for the network objects
+        self.__networkManager = QNetworkAccessManager(self)
+        self.__networkManager.proxyAuthenticationRequired.connect(
+            proxyAuthenticationRequired)
+        self.__networkManager.finished.connect(self.__replyFinished)
+        if SSL_AVAILABLE:
+            self.__sslErrorHandler = E5SslErrorHandler(self)
+            self.__networkManager.sslErrors.connect(self.__sslErrors)
+        
+        self.__callmap = {}
+        
+        self.__request = QNetworkRequest(QUrl(url))
+        self.__request.setRawHeader(b"User-Agent", b"E5XmlRpcClient/1.0")
+        self.__request.setHeader(QNetworkRequest.ContentTypeHeader, "text/xml")
+    
+    def setUrl(self, url):
+        """
+        Public slot to set the xmlrpc handler URL.
+        
+        @param url xmlrpc handler URL (string or QUrl)
+        """
+        url = QUrl(url)
+        if url.isValid():
+            self.__request.setUrl(url)
+    
+    def call(self, method, args, responseCallback, errorCallback):
+        """
+        Public method to call the remote server.
+        
+        @param method name of the remote method to be called (string)
+        @param args tuple of method arguments (tuple)
+        @param responseCallback method to be called with the returned
+            result as a tuple (function)
+        @param errorCallback method to be called in case of an error
+            with error code and error string (function)
+        """
+        assert isinstance(args, tuple), \
+            "argument must be tuple or Fault instance"
+        
+        data = xmlrpc.dumps(args, method).encode("utf-8")
+        reply = self.__networkManager.post(
+            self.__request, QByteArray(data))
+        self.__callmap[reply] = (responseCallback, errorCallback)
+    
+    def abort(self):
+        """
+        Public method to abort all calls.
+        """
+        for reply in list(self.__callmap):
+            if reply.isRunning():
+                reply.abort()
+    
+    def __sslErrors(self, reply, errors):
+        """
+        Private slot to handle SSL errors.
+        
+        @param reply reference to the reply object (QNetworkReply)
+        @param errors list of SSL errors (list of QSslError)
+        """
+        ignored = self.__sslErrorHandler.sslErrorsReply(reply, errors)[0]
+        if ignored == E5SslErrorHandler.NotIgnored and reply in self.__callmap:
+            self.__callmap[reply][1](xmlrpc.TRANSPORT_ERROR, self.tr(
+                "SSL Error"))
+    
+    def __replyFinished(self, reply):
+        """
+        Private slot handling the receipt of a reply.
+        
+        @param reply reference to the finished reply (QNetworkReply)
+        """
+        if reply not in self.__callmap:
+            return
+        
+        if reply.error() != QNetworkReply.NoError:
+            self.__callmap[reply][1](xmlrpc.TRANSPORT_ERROR,
+                                     reply.errorString())
+        else:
+            data = bytes(reply.readAll()).decode("utf-8")
+            try:
+                data = xmlrpc.loads(data)[0]
+                self.__callmap[reply][0](data)
+            except xmlrpc.Fault as fault:
+                self.__callmap[reply][1](fault.faultCode, fault.faultString)
+        
+        reply.deleteLater()
+        del self.__callmap[reply]

eric ide

mercurial