changeset 3243:f2e30aa031e9

bridge (pb): fixed conversions of Failure to BridgeException in non-AIO bridge
author Goffi <goffi@goffi.org>
date Wed, 01 Apr 2020 15:40:29 +0200
parents 6d0137022df2
children b10d207f95f9
files sat/bridge/bridge_constructor/constructors/pb/constructor.py sat/bridge/bridge_constructor/constructors/pb/pb_frontend_template.py sat_frontends/bridge/pb.py
diffstat 3 files changed, 216 insertions(+), 133 deletions(-) [+]
line wrap: on
line diff
--- a/sat/bridge/bridge_constructor/constructors/pb/constructor.py	Wed Apr 01 15:32:18 2020 +0200
+++ b/sat/bridge/bridge_constructor/constructors/pb/constructor.py	Wed Apr 01 15:40:29 2020 +0200
@@ -1,6 +1,5 @@
 #!/usr/bin/env python3
 
-
 # SàT: a XMPP client
 # Copyright (C) 2009-2020 Jérôme Poisson (goffi@goffi.org)
 
@@ -39,8 +38,9 @@
         if callback is not None:
             d.addCallback({callback})
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)\n""",
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)\n""",
         "async_methods": """\
     def {name}(self{args_comma}{args}):
         {debug}d = self.root.callRemote("{name}"{args_comma}{args_no_def})
--- a/sat/bridge/bridge_constructor/constructors/pb/pb_frontend_template.py	Wed Apr 01 15:32:18 2020 +0200
+++ b/sat/bridge/bridge_constructor/constructors/pb/pb_frontend_template.py	Wed Apr 01 15:40:29 2020 +0200
@@ -1,7 +1,6 @@
 #!/usr/bin/env python3
 
-
-# SAT communication bridge
+# SàT communication bridge
 # Copyright (C) 2009-2020 Jérôme Poisson (goffi@goffi.org)
 
 # This program is free software: you can redistribute it and/or modify
@@ -65,6 +64,15 @@
     def _generic_errback(self, err):
         log.error(f"bridge error: {err}")
 
+    def _errback(self, failure_, ori_errback):
+        """Convert Failure to BridgeException"""
+        ori_errback(
+            BridgeException(
+                name=failure_.type.decode('utf-8'),
+                message=str(failure_.value)
+            )
+        )
+
     def remoteCallback(self, result, callback):
         """call callback with argument or None
 
@@ -159,6 +167,7 @@
         self.signals_handler = AIOSignalsHandler()
 
     def _errback(self, failure_):
+        """Convert Failure to BridgeException"""
         raise BridgeException(
             name=failure_.type.decode('utf-8'),
             message=str(failure_.value)
--- a/sat_frontends/bridge/pb.py	Wed Apr 01 15:32:18 2020 +0200
+++ b/sat_frontends/bridge/pb.py	Wed Apr 01 15:40:29 2020 +0200
@@ -65,6 +65,15 @@
     def _generic_errback(self, err):
         log.error(f"bridge error: {err}")
 
+    def _errback(self, failure_, ori_errback):
+        """Convert Failure to BridgeException"""
+        ori_errback(
+            BridgeException(
+                name=failure_.type.decode('utf-8'),
+                message=str(failure_.value)
+            )
+        )
+
     def remoteCallback(self, result, callback):
         """call callback with argument or None
 
@@ -148,512 +157,576 @@
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def addContact(self, entity_jid, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("addContact", entity_jid, profile_key)
         if callback is not None:
             d.addCallback(lambda __: callback())
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def asyncDeleteProfile(self, profile, callback=None, errback=None):
         d = self.root.callRemote("asyncDeleteProfile", profile)
         if callback is not None:
             d.addCallback(lambda __: callback())
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def asyncGetParamA(self, name, category, attribute="value", security_limit=-1, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("asyncGetParamA", name, category, attribute, security_limit, profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def asyncGetParamsValuesFromCategory(self, category, security_limit=-1, app="", extra="", profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("asyncGetParamsValuesFromCategory", category, security_limit, app, extra, profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def connect(self, profile_key="@DEFAULT@", password='', options={}, callback=None, errback=None):
         d = self.root.callRemote("connect", profile_key, password, options)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def delContact(self, entity_jid, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("delContact", entity_jid, profile_key)
         if callback is not None:
             d.addCallback(lambda __: callback())
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def devicesInfosGet(self, bare_jid, profile_key, callback=None, errback=None):
         d = self.root.callRemote("devicesInfosGet", bare_jid, profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def discoFindByFeatures(self, namespaces, identities, bare_jid=False, service=True, roster=True, own_jid=True, local_device=False, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("discoFindByFeatures", namespaces, identities, bare_jid, service, roster, own_jid, local_device, profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def discoInfos(self, entity_jid, node=u'', use_cache=True, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("discoInfos", entity_jid, node, use_cache, profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def discoItems(self, entity_jid, node=u'', use_cache=True, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("discoItems", entity_jid, node, use_cache, profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def disconnect(self, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("disconnect", profile_key)
         if callback is not None:
             d.addCallback(lambda __: callback())
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def encryptionNamespaceGet(self, arg_0, callback=None, errback=None):
         d = self.root.callRemote("encryptionNamespaceGet", arg_0)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def encryptionPluginsGet(self, callback=None, errback=None):
         d = self.root.callRemote("encryptionPluginsGet")
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def encryptionTrustUIGet(self, to_jid, namespace, profile_key, callback=None, errback=None):
         d = self.root.callRemote("encryptionTrustUIGet", to_jid, namespace, profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def getConfig(self, section, name, callback=None, errback=None):
         d = self.root.callRemote("getConfig", section, name)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def getContacts(self, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("getContacts", profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def getContactsFromGroup(self, group, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("getContactsFromGroup", group, profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def getEntitiesData(self, jids, keys, profile, callback=None, errback=None):
         d = self.root.callRemote("getEntitiesData", jids, keys, profile)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def getEntityData(self, jid, keys, profile, callback=None, errback=None):
         d = self.root.callRemote("getEntityData", jid, keys, profile)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def getFeatures(self, profile_key, callback=None, errback=None):
         d = self.root.callRemote("getFeatures", profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def getMainResource(self, contact_jid, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("getMainResource", contact_jid, profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def getParamA(self, name, category, attribute="value", profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("getParamA", name, category, attribute, profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def getParamsCategories(self, callback=None, errback=None):
         d = self.root.callRemote("getParamsCategories")
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def getParamsUI(self, security_limit=-1, app='', extra='', profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("getParamsUI", security_limit, app, extra, profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def getPresenceStatuses(self, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("getPresenceStatuses", profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def getReady(self, callback=None, errback=None):
         d = self.root.callRemote("getReady")
         if callback is not None:
             d.addCallback(lambda __: callback())
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def getVersion(self, callback=None, errback=None):
         d = self.root.callRemote("getVersion")
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def getWaitingSub(self, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("getWaitingSub", profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def historyGet(self, from_jid, to_jid, limit, between=True, filters='', profile="@NONE@", callback=None, errback=None):
         d = self.root.callRemote("historyGet", from_jid, to_jid, limit, between, filters, profile)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def imageCheck(self, arg_0, callback=None, errback=None):
         d = self.root.callRemote("imageCheck", arg_0)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def imageGeneratePreview(self, image_path, profile_key, callback=None, errback=None):
         d = self.root.callRemote("imageGeneratePreview", image_path, profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def imageResize(self, image_path, width, height, callback=None, errback=None):
         d = self.root.callRemote("imageResize", image_path, width, height)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def isConnected(self, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("isConnected", profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def launchAction(self, callback_id, data, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("launchAction", callback_id, data, profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def loadParamsTemplate(self, filename, callback=None, errback=None):
         d = self.root.callRemote("loadParamsTemplate", filename)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def menuHelpGet(self, menu_id, language, callback=None, errback=None):
         d = self.root.callRemote("menuHelpGet", menu_id, language)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def menuLaunch(self, menu_type, path, data, security_limit, profile_key, callback=None, errback=None):
         d = self.root.callRemote("menuLaunch", menu_type, path, data, security_limit, profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def menusGet(self, language, security_limit, callback=None, errback=None):
         d = self.root.callRemote("menusGet", language, security_limit)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def messageEncryptionGet(self, to_jid, profile_key, callback=None, errback=None):
         d = self.root.callRemote("messageEncryptionGet", to_jid, profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def messageEncryptionStart(self, to_jid, namespace='', replace=False, profile_key="@NONE@", callback=None, errback=None):
         d = self.root.callRemote("messageEncryptionStart", to_jid, namespace, replace, profile_key)
         if callback is not None:
             d.addCallback(lambda __: callback())
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def messageEncryptionStop(self, to_jid, profile_key, callback=None, errback=None):
         d = self.root.callRemote("messageEncryptionStop", to_jid, profile_key)
         if callback is not None:
             d.addCallback(lambda __: callback())
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def messageSend(self, to_jid, message, subject={}, mess_type="auto", extra={}, profile_key="@NONE@", callback=None, errback=None):
         d = self.root.callRemote("messageSend", to_jid, message, subject, mess_type, extra, profile_key)
         if callback is not None:
             d.addCallback(lambda __: callback())
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def namespacesGet(self, callback=None, errback=None):
         d = self.root.callRemote("namespacesGet")
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def paramsRegisterApp(self, xml, security_limit=-1, app='', callback=None, errback=None):
         d = self.root.callRemote("paramsRegisterApp", xml, security_limit, app)
         if callback is not None:
             d.addCallback(lambda __: callback())
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def privateDataDelete(self, namespace, key, arg_2, callback=None, errback=None):
         d = self.root.callRemote("privateDataDelete", namespace, key, arg_2)
         if callback is not None:
             d.addCallback(lambda __: callback())
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def privateDataGet(self, namespace, key, profile_key, callback=None, errback=None):
         d = self.root.callRemote("privateDataGet", namespace, key, profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def privateDataSet(self, namespace, key, data, profile_key, callback=None, errback=None):
         d = self.root.callRemote("privateDataSet", namespace, key, data, profile_key)
         if callback is not None:
             d.addCallback(lambda __: callback())
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def profileCreate(self, profile, password='', component='', callback=None, errback=None):
         d = self.root.callRemote("profileCreate", profile, password, component)
         if callback is not None:
             d.addCallback(lambda __: callback())
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def profileIsSessionStarted(self, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("profileIsSessionStarted", profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def profileNameGet(self, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("profileNameGet", profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def profileSetDefault(self, profile, callback=None, errback=None):
         d = self.root.callRemote("profileSetDefault", profile)
         if callback is not None:
             d.addCallback(lambda __: callback())
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def profileStartSession(self, password='', profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("profileStartSession", password, profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def profilesListGet(self, clients=True, components=False, callback=None, errback=None):
         d = self.root.callRemote("profilesListGet", clients, components)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def progressGet(self, id, profile, callback=None, errback=None):
         d = self.root.callRemote("progressGet", id, profile)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def progressGetAll(self, profile, callback=None, errback=None):
         d = self.root.callRemote("progressGetAll", profile)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def progressGetAllMetadata(self, profile, callback=None, errback=None):
         d = self.root.callRemote("progressGetAllMetadata", profile)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def rosterResync(self, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("rosterResync", profile_key)
         if callback is not None:
             d.addCallback(lambda __: callback())
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def saveParamsTemplate(self, filename, callback=None, errback=None):
         d = self.root.callRemote("saveParamsTemplate", filename)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def sessionInfosGet(self, profile_key, callback=None, errback=None):
         d = self.root.callRemote("sessionInfosGet", profile_key)
         if callback is not None:
             d.addCallback(callback)
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def setParam(self, name, value, category, security_limit=-1, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("setParam", name, value, category, security_limit, profile_key)
         if callback is not None:
             d.addCallback(lambda __: callback())
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def setPresence(self, to_jid='', show='', statuses={}, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("setPresence", to_jid, show, statuses, profile_key)
         if callback is not None:
             d.addCallback(lambda __: callback())
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def subscription(self, sub_type, entity, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("subscription", sub_type, entity, profile_key)
         if callback is not None:
             d.addCallback(lambda __: callback())
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
     def updateContact(self, entity_jid, name, groups, profile_key="@DEFAULT@", callback=None, errback=None):
         d = self.root.callRemote("updateContact", entity_jid, name, groups, profile_key)
         if callback is not None:
             d.addCallback(lambda __: callback())
         if errback is None:
-            errback = self._generic_errback
-        d.addErrback(errback)
+            d.addErrback(self._generic_errback)
+        else:
+            d.addErrback(self._errback, ori_errback=errback)
 
 
 class AIOSignalsHandler(SignalsHandler):
@@ -670,6 +743,7 @@
         self.signals_handler = AIOSignalsHandler()
 
     def _errback(self, failure_):
+        """Convert Failure to BridgeException"""
         raise BridgeException(
             name=failure_.type.decode('utf-8'),
             message=str(failure_.value)