diff -r e9e7eca7efee -r bf71ee032bb4 src/eric7/Plugins/UiExtensionPlugins/Translator/TranslatorEngines/IbmWatsonEngine.py --- a/src/eric7/Plugins/UiExtensionPlugins/Translator/TranslatorEngines/IbmWatsonEngine.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/Plugins/UiExtensionPlugins/Translator/TranslatorEngines/IbmWatsonEngine.py Wed Jul 13 14:55:47 2022 +0200 @@ -10,9 +10,7 @@ import json from PyQt6.QtCore import QUrl, QByteArray, QTimer -from PyQt6.QtNetwork import ( - QNetworkAccessManager, QNetworkRequest, QNetworkReply -) +from PyQt6.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply from EricWidgets import EricMessageBox @@ -26,59 +24,61 @@ Class implementing the translation engine for the IBM Watson Language Translator service. """ + # Documentation: # https://www.ibm.com/watson/developercloud/language-translator # # Start page: # https://www.ibm.com/watson/services/language-translator/ - + def __init__(self, plugin, parent=None): """ Constructor - + @param plugin reference to the plugin object @type TranslatorPlugin @param parent reference to the parent object @type QObject """ super().__init__(plugin, parent) - + self.__ui = parent - + self.__networkManager = QNetworkAccessManager(self) self.__networkManager.proxyAuthenticationRequired.connect( - proxyAuthenticationRequired) - + proxyAuthenticationRequired + ) + self.__availableTranslations = {} # dictionary of sets of available translations - + self.__replies = [] - + QTimer.singleShot(0, self.__getTranslationModels) - + def engineName(self): """ Public method to return the name of the engine. - + @return engine name @rtype str """ return "ibm_watson" - + def supportedLanguages(self): """ Public method to get the supported languages. - + @return list of supported language codes @rtype list of str """ return list(self.__availableTranslations.keys()) - + def supportedTargetLanguages(self, original): """ Public method to get a list of supported target languages for an original language. - + @param original original language @type str @return list of supported target languages for the given original @@ -86,21 +86,22 @@ """ targets = self.__availableTranslations.get(original, set()) return list(targets) - + def hasTTS(self): """ Public method indicating the Text-to-Speech capability. - + @return flag indicating the Text-to-Speech capability @rtype bool """ return False - - def getTranslation(self, requestObject, text, originalLanguage, - translationLanguage): + + def getTranslation( + self, requestObject, text, originalLanguage, translationLanguage + ): """ Public method to translate the given text. - + @param requestObject reference to the request object @type TranslatorRequest @param text text to be translated @@ -114,40 +115,46 @@ """ apiKey = self.plugin.getPreferences("IbmKey") if not apiKey: - return self.tr("IBM Watson: A valid Language Translator key is" - " required."), False + return ( + self.tr("IBM Watson: A valid Language Translator key is" " required."), + False, + ) translatorUrl = self.plugin.getPreferences("IbmUrl") if not translatorUrl: - return self.tr("IBM Watson: A valid Language Translator URL is" - " required."), False - + return ( + self.tr("IBM Watson: A valid Language Translator URL is" " required."), + False, + ) + params = "?version=2018-05-01" url = QUrl(translatorUrl + "/v3/translate" + params) - + requestDict = { "text": [text], "source": originalLanguage, "target": translationLanguage, } request = QByteArray(json.dumps(requestDict).encode("utf-8")) - + extraHeaders = [ - (b"Authorization", - b"Basic " + QByteArray( - b"apikey:" + apiKey.encode("utf-8")).toBase64()) + ( + b"Authorization", + b"Basic " + QByteArray(b"apikey:" + apiKey.encode("utf-8")).toBase64(), + ) ] - - response, ok = requestObject.post(url, request, dataType="json", - extraHeaders=extraHeaders) + + response, ok = requestObject.post( + url, request, dataType="json", extraHeaders=extraHeaders + ) if ok: try: responseDict = json.loads(response) except ValueError: return self.tr("IBM Watson: Invalid response received"), False - + if "translations" not in responseDict: return self.tr("IBM Watson: No translation available."), False - + result = "" translations = responseDict["translations"] for translation in translations: @@ -157,11 +164,11 @@ else: result = response return result, ok - + def __adjustLanguageCode(self, code): """ Private method to adjust a given language code. - + @param code code to be adjusted @type str @return adjusted language code @@ -171,7 +178,7 @@ return "zh-CN" else: return code - + def __getTranslationModels(self): """ Private method to get the translation models supported by IBM Watson @@ -182,8 +189,7 @@ EricMessageBox.critical( self.__ui, self.tr("Error Getting Available Translations"), - self.tr("IBM Watson: A valid Language Translator key is" - " required.") + self.tr("IBM Watson: A valid Language Translator key is" " required."), ) return translatorUrl = self.plugin.getPreferences("IbmUrl") @@ -191,47 +197,48 @@ EricMessageBox.critical( self.__ui, self.tr("Error Getting Available Translations"), - self.tr("IBM Watson: A valid Language Translator URL is" - " required.") + self.tr("IBM Watson: A valid Language Translator URL is" " required."), ) return - + params = "?version=2018-05-01" url = QUrl(translatorUrl + "/v3/models" + params) - + extraHeaders = [ - (b"Authorization", - b"Basic " + QByteArray( - b"apikey:" + apiKey.encode("utf-8")).toBase64()) + ( + b"Authorization", + b"Basic " + QByteArray(b"apikey:" + apiKey.encode("utf-8")).toBase64(), + ) ] - + request = QNetworkRequest(url) if extraHeaders: for name, value in extraHeaders: request.setRawHeader(name, value) reply = self.__networkManager.get(request) - reply.finished.connect( - lambda: self.__getTranslationModelsReplyFinished(reply)) + reply.finished.connect(lambda: self.__getTranslationModelsReplyFinished(reply)) self.__replies.append(reply) - + def __getTranslationModelsReplyFinished(self, reply): """ Private slot handling the receipt of the available translations. - + @param reply reference to the network reply object @type QNetworkReply """ if reply in self.__replies: self.__replies.remove(reply) reply.deleteLater() - + if reply.error() != QNetworkReply.NetworkError.NoError: errorStr = reply.errorString() EricMessageBox.critical( self.__ui, self.tr("Error Getting Available Translations"), - self.tr("IBM Watson: The server sent an error indication." - "\n Error: {0}").format(errorStr) + self.tr( + "IBM Watson: The server sent an error indication." + "\n Error: {0}" + ).format(errorStr), ) return else: @@ -242,18 +249,18 @@ EricMessageBox.critical( self.__ui, self.tr("Error Getting Available Translations"), - self.tr("IBM Watson: Invalid response received") + self.tr("IBM Watson: Invalid response received"), ) return - + if "models" not in responseDict: EricMessageBox.critical( self.__ui, self.tr("Error Getting Available Translations"), - self.tr("IBM Watson: No translation available.") + self.tr("IBM Watson: No translation available."), ) return - + for model in responseDict["models"]: if model["status"] == "available": source = self.__adjustLanguageCode(model["source"]) @@ -261,5 +268,5 @@ if source not in self.__availableTranslations: self.__availableTranslations[source] = set() self.__availableTranslations[source].add(target) - + self.availableTranslationsLoaded.emit()