comparison sat/bridge/dbus_bridge.py @ 3539:60d3861e5996

bridge (dbus): use Tx DBus for backend part of D-Bus bridge: Due to recent SQLAlchemy integration, Libervia is now using AsyncIO loop exclusively as main loop, thus GLib's one can't be used anymore (event if it could be in a separate thread). Furthermore Python-DBus is known to have design flaws mentioned even in the official documentation. Tx DBus is now used to replace Python-DBus, but only for the backend for now, as it will need some work on the frontend before we can get completely rid of it.
author Goffi <goffi@goffi.org>
date Thu, 03 Jun 2021 15:21:43 +0200
parents 7550ae9cfbac
children 524856bd7b19
comparison
equal deleted inserted replaced
3538:c605a0d6506f 3539:60d3861e5996
1 #!/usr/bin/env python3 1 #!/usr/bin/env python3
2 2
3 # SàT communication bridge 3 # Libervia communication bridge
4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org) 4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org)
5 5
6 # This program is free software: you can redistribute it and/or modify 6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU Affero General Public License as published by 7 # it under the terms of the GNU Affero General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or 8 # the Free Software Foundation, either version 3 of the License, or
14 # GNU Affero General Public License for more details. 14 # GNU Affero General Public License for more details.
15 15
16 # You should have received a copy of the GNU Affero General Public License 16 # You should have received a copy of the GNU Affero General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. 17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 18
19 from types import MethodType
20 from functools import partialmethod
21 from twisted.internet import defer, reactor
19 from sat.core.i18n import _ 22 from sat.core.i18n import _
20 import dbus
21 import dbus.service
22 import dbus.mainloop.glib
23 import inspect
24 from sat.core.log import getLogger 23 from sat.core.log import getLogger
24 from sat.core.exceptions import BridgeInitError
25 from sat.tools import config 25 from sat.tools import config
26 from twisted.internet.defer import Deferred 26 from txdbus import client, objects, error
27 from sat.core.exceptions import BridgeInitError 27 from txdbus.interface import DBusInterface, Method, Signal
28 28
29 29
30 log = getLogger(__name__) 30 log = getLogger(__name__)
31 31
32 # Interface prefix 32 # Interface prefix
43 43
44 class ParseError(Exception): 44 class ParseError(Exception):
45 pass 45 pass
46 46
47 47
48 class MethodNotRegistered(dbus.DBusException): 48 class DBusException(Exception):
49 _dbus_error_name = const_ERROR_PREFIX + ".MethodNotRegistered" 49 pass
50 50
51 51
52 class InternalError(dbus.DBusException): 52 class MethodNotRegistered(DBusException):
53 _dbus_error_name = const_ERROR_PREFIX + ".InternalError" 53 dbusErrorName = const_ERROR_PREFIX + ".MethodNotRegistered"
54 54
55 55
56 class AsyncNotDeferred(dbus.DBusException): 56 class GenericException(DBusException):
57 _dbus_error_name = const_ERROR_PREFIX + ".AsyncNotDeferred"
58
59
60 class DeferredNotAsync(dbus.DBusException):
61 _dbus_error_name = const_ERROR_PREFIX + ".DeferredNotAsync"
62
63
64 class GenericException(dbus.DBusException):
65 def __init__(self, twisted_error): 57 def __init__(self, twisted_error):
66 """ 58 """
67 59
68 @param twisted_error (Failure): instance of twisted Failure 60 @param twisted_error (Failure): instance of twisted Failure
69 @return: DBusException 61 error message is used to store a repr of message and condition in a tuple,
62 so it can be evaluated by the frontend bridge.
70 """ 63 """
71 super(GenericException, self).__init__()
72 try: 64 try:
73 # twisted_error.value is a class 65 # twisted_error.value is a class
74 class_ = twisted_error.value().__class__ 66 class_ = twisted_error.value().__class__
75 except TypeError: 67 except TypeError:
76 # twisted_error.value is an instance 68 # twisted_error.value is an instance
77 class_ = twisted_error.value.__class__ 69 class_ = twisted_error.value.__class__
78 message = twisted_error.getErrorMessage() 70 data = twisted_error.getErrorMessage()
79 try: 71 try:
80 self.args = (message, twisted_error.value.condition) 72 data = (data, twisted_error.value.condition)
81 except AttributeError: 73 except AttributeError:
82 self.args = (message,) 74 data = (data,)
83 self._dbus_error_name = ".".join( 75 else:
84 [const_ERROR_PREFIX, class_.__module__, class_.__name__] 76 data = (str(twisted_error),)
77 self.dbusErrorName = ".".join(
78 (const_ERROR_PREFIX, class_.__module__, class_.__name__)
85 ) 79 )
86 80 super(GenericException, self).__init__(repr(data))
87 81
88 class DbusObject(dbus.service.Object): 82 @classmethod
89 def __init__(self, bus, path): 83 def create_and_raise(cls, exc):
90 dbus.service.Object.__init__(self, bus, path) 84 raise cls(exc)
91 log.debug("Init DbusObject...") 85
86
87 class DBusObject(objects.DBusObject):
88
89 core_iface = DBusInterface(
90 const_INT_PREFIX + const_CORE_SUFFIX,
91 Method('actionsGet', arguments='s', returns='a(a{ss}si)'),
92 Method('addContact', arguments='ss', returns=''),
93 Method('asyncDeleteProfile', arguments='s', returns=''),
94 Method('asyncGetParamA', arguments='sssis', returns='s'),
95 Method('asyncGetParamsValuesFromCategory', arguments='sisss', returns='a{ss}'),
96 Method('connect', arguments='ssa{ss}', returns='b'),
97 Method('contactGet', arguments='ss', returns='(a{ss}as)'),
98 Method('delContact', arguments='ss', returns=''),
99 Method('devicesInfosGet', arguments='ss', returns='s'),
100 Method('discoFindByFeatures', arguments='asa(ss)bbbbbs', returns='(a{sa(sss)}a{sa(sss)}a{sa(sss)})'),
101 Method('discoInfos', arguments='ssbs', returns='(asa(sss)a{sa(a{ss}as)})'),
102 Method('discoItems', arguments='ssbs', returns='a(sss)'),
103 Method('disconnect', arguments='s', returns=''),
104 Method('encryptionNamespaceGet', arguments='s', returns='s'),
105 Method('encryptionPluginsGet', arguments='', returns='s'),
106 Method('encryptionTrustUIGet', arguments='sss', returns='s'),
107 Method('getConfig', arguments='ss', returns='s'),
108 Method('getContacts', arguments='s', returns='a(sa{ss}as)'),
109 Method('getContactsFromGroup', arguments='ss', returns='as'),
110 Method('getEntitiesData', arguments='asass', returns='a{sa{ss}}'),
111 Method('getEntityData', arguments='sass', returns='a{ss}'),
112 Method('getFeatures', arguments='s', returns='a{sa{ss}}'),
113 Method('getMainResource', arguments='ss', returns='s'),
114 Method('getParamA', arguments='ssss', returns='s'),
115 Method('getParamsCategories', arguments='', returns='as'),
116 Method('getParamsUI', arguments='isss', returns='s'),
117 Method('getPresenceStatuses', arguments='s', returns='a{sa{s(sia{ss})}}'),
118 Method('getReady', arguments='', returns=''),
119 Method('getVersion', arguments='', returns='s'),
120 Method('getWaitingSub', arguments='s', returns='a{ss}'),
121 Method('historyGet', arguments='ssiba{ss}s', returns='a(sdssa{ss}a{ss}ss)'),
122 Method('imageCheck', arguments='s', returns='s'),
123 Method('imageConvert', arguments='ssss', returns='s'),
124 Method('imageGeneratePreview', arguments='ss', returns='s'),
125 Method('imageResize', arguments='sii', returns='s'),
126 Method('isConnected', arguments='s', returns='b'),
127 Method('launchAction', arguments='sa{ss}s', returns='a{ss}'),
128 Method('loadParamsTemplate', arguments='s', returns='b'),
129 Method('menuHelpGet', arguments='ss', returns='s'),
130 Method('menuLaunch', arguments='sasa{ss}is', returns='a{ss}'),
131 Method('menusGet', arguments='si', returns='a(ssasasa{ss})'),
132 Method('messageEncryptionGet', arguments='ss', returns='s'),
133 Method('messageEncryptionStart', arguments='ssbs', returns=''),
134 Method('messageEncryptionStop', arguments='ss', returns=''),
135 Method('messageSend', arguments='sa{ss}a{ss}sss', returns=''),
136 Method('namespacesGet', arguments='', returns='a{ss}'),
137 Method('paramsRegisterApp', arguments='sis', returns=''),
138 Method('privateDataDelete', arguments='sss', returns=''),
139 Method('privateDataGet', arguments='sss', returns='s'),
140 Method('privateDataSet', arguments='ssss', returns=''),
141 Method('profileCreate', arguments='sss', returns=''),
142 Method('profileIsSessionStarted', arguments='s', returns='b'),
143 Method('profileNameGet', arguments='s', returns='s'),
144 Method('profileSetDefault', arguments='s', returns=''),
145 Method('profileStartSession', arguments='ss', returns='b'),
146 Method('profilesListGet', arguments='bb', returns='as'),
147 Method('progressGet', arguments='ss', returns='a{ss}'),
148 Method('progressGetAll', arguments='s', returns='a{sa{sa{ss}}}'),
149 Method('progressGetAllMetadata', arguments='s', returns='a{sa{sa{ss}}}'),
150 Method('rosterResync', arguments='s', returns=''),
151 Method('saveParamsTemplate', arguments='s', returns='b'),
152 Method('sessionInfosGet', arguments='s', returns='a{ss}'),
153 Method('setParam', arguments='sssis', returns=''),
154 Method('setPresence', arguments='ssa{ss}s', returns=''),
155 Method('subscription', arguments='sss', returns=''),
156 Method('updateContact', arguments='ssass', returns=''),
157 Signal('_debug', 'sa{ss}s'),
158 Signal('actionNew', 'a{ss}sis'),
159 Signal('connected', 'ss'),
160 Signal('contactDeleted', 'ss'),
161 Signal('disconnected', 's'),
162 Signal('entityDataUpdated', 'ssss'),
163 Signal('messageEncryptionStarted', 'sss'),
164 Signal('messageEncryptionStopped', 'sa{ss}s'),
165 Signal('messageNew', 'sdssa{ss}a{ss}sss'),
166 Signal('newContact', 'sa{ss}ass'),
167 Signal('paramUpdate', 'ssss'),
168 Signal('presenceUpdate', 'ssia{ss}s'),
169 Signal('progressError', 'sss'),
170 Signal('progressFinished', 'sa{ss}s'),
171 Signal('progressStarted', 'sa{ss}s'),
172 Signal('subscribe', 'sss'),
173 )
174 plugin_iface = DBusInterface(
175 const_INT_PREFIX + const_PLUGIN_SUFFIX
176 )
177
178 dbusInterfaces = [core_iface, plugin_iface]
179
180 def __init__(self, path):
181 super().__init__(path)
182 log.debug("Init DBusObject...")
92 self.cb = {} 183 self.cb = {}
93 184
94 def register_method(self, name, cb): 185 def register_method(self, name, cb):
95 self.cb[name] = cb 186 self.cb[name] = cb
96 187
97 def _callback(self, name, *args, **kwargs): 188 def _callback(self, name, *args, **kwargs):
98 """call the callback if it exists, raise an exception else 189 """Call the callback if it exists, raise an exception else"""
99 if the callback return a deferred, use async methods""" 190 try:
100 if not name in self.cb: 191 cb = self.cb[name]
192 except KeyError:
101 raise MethodNotRegistered 193 raise MethodNotRegistered
102
103 if "callback" in kwargs:
104 # we must have errback too
105 if not "errback" in kwargs:
106 log.error("errback is missing in method call [%s]" % name)
107 raise InternalError
108 callback = kwargs.pop("callback")
109 errback = kwargs.pop("errback")
110 async_ = True
111 else: 194 else:
112 async_ = False 195 d = defer.maybeDeferred(cb, *args, **kwargs)
113 result = self.cb[name](*args, **kwargs) 196 d.addErrback(GenericException.create_and_raise)
114 if async_: 197 return d
115 if not isinstance(result, Deferred): 198
116 log.error("Asynchronous method [%s] does not return a Deferred." % name) 199 def dbus_actionsGet(self, profile_key="@DEFAULT@"):
117 raise AsyncNotDeferred 200 return self._callback("actionsGet", profile_key)
118 result.addCallback( 201
119 lambda result: callback() if result is None else callback(result) 202 def dbus_addContact(self, entity_jid, profile_key="@DEFAULT@"):
120 ) 203 return self._callback("addContact", entity_jid, profile_key)
121 result.addErrback(lambda err: errback(GenericException(err))) 204
122 else: 205 def dbus_asyncDeleteProfile(self, profile):
123 if isinstance(result, Deferred): 206 return self._callback("asyncDeleteProfile", profile)
124 log.error("Synchronous method [%s] return a Deferred." % name) 207
125 raise DeferredNotAsync 208 def dbus_asyncGetParamA(self, name, category, attribute="value", security_limit=-1, profile_key="@DEFAULT@"):
126 return result 209 return self._callback("asyncGetParamA", name, category, attribute, security_limit, profile_key)
127 210
128 ### signals ### 211 def dbus_asyncGetParamsValuesFromCategory(self, category, security_limit=-1, app="", extra="", profile_key="@DEFAULT@"):
129 212 return self._callback("asyncGetParamsValuesFromCategory", category, security_limit, app, extra, profile_key)
130 @dbus.service.signal(const_INT_PREFIX + const_PLUGIN_SUFFIX, signature="") 213
131 def dummySignal(self): 214 def dbus_connect(self, profile_key="@DEFAULT@", password='', options={}):
132 # FIXME: workaround for addSignal (doesn't work if one method doensn't 215 return self._callback("connect", profile_key, password, options)
133 # already exist for plugins), probably missing some initialisation, need 216
134 # further investigations 217 def dbus_contactGet(self, arg_0, profile_key="@DEFAULT@"):
135 pass 218 return self._callback("contactGet", arg_0, profile_key)
136 219
137 @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX, 220 def dbus_delContact(self, entity_jid, profile_key="@DEFAULT@"):
138 signature='sa{ss}s') 221 return self._callback("delContact", entity_jid, profile_key)
139 def _debug(self, action, params, profile): 222
140 pass 223 def dbus_devicesInfosGet(self, bare_jid, profile_key):
141 224 return self._callback("devicesInfosGet", bare_jid, profile_key)
142 @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX, 225
143 signature='a{ss}sis') 226 def dbus_discoFindByFeatures(self, namespaces, identities, bare_jid=False, service=True, roster=True, own_jid=True, local_device=False, profile_key="@DEFAULT@"):
144 def actionNew(self, action_data, id, security_limit, profile): 227 return self._callback("discoFindByFeatures", namespaces, identities, bare_jid, service, roster, own_jid, local_device, profile_key)
145 pass 228
146 229 def dbus_discoInfos(self, entity_jid, node=u'', use_cache=True, profile_key="@DEFAULT@"):
147 @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX, 230 return self._callback("discoInfos", entity_jid, node, use_cache, profile_key)
148 signature='ss') 231
149 def connected(self, jid_s, profile): 232 def dbus_discoItems(self, entity_jid, node=u'', use_cache=True, profile_key="@DEFAULT@"):
150 pass 233 return self._callback("discoItems", entity_jid, node, use_cache, profile_key)
151 234
152 @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX, 235 def dbus_disconnect(self, profile_key="@DEFAULT@"):
153 signature='ss') 236 return self._callback("disconnect", profile_key)
154 def contactDeleted(self, entity_jid, profile): 237
155 pass 238 def dbus_encryptionNamespaceGet(self, arg_0):
156 239 return self._callback("encryptionNamespaceGet", arg_0)
157 @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX, 240
158 signature='s') 241 def dbus_encryptionPluginsGet(self, ):
159 def disconnected(self, profile):
160 pass
161
162 @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
163 signature='ssss')
164 def entityDataUpdated(self, jid, name, value, profile):
165 pass
166
167 @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
168 signature='sss')
169 def messageEncryptionStarted(self, to_jid, encryption_data, profile_key):
170 pass
171
172 @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
173 signature='sa{ss}s')
174 def messageEncryptionStopped(self, to_jid, encryption_data, profile_key):
175 pass
176
177 @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
178 signature='sdssa{ss}a{ss}sss')
179 def messageNew(self, uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile):
180 pass
181
182 @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
183 signature='sa{ss}ass')
184 def newContact(self, contact_jid, attributes, groups, profile):
185 pass
186
187 @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
188 signature='ssss')
189 def paramUpdate(self, name, value, category, profile):
190 pass
191
192 @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
193 signature='ssia{ss}s')
194 def presenceUpdate(self, entity_jid, show, priority, statuses, profile):
195 pass
196
197 @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
198 signature='sss')
199 def progressError(self, id, error, profile):
200 pass
201
202 @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
203 signature='sa{ss}s')
204 def progressFinished(self, id, metadata, profile):
205 pass
206
207 @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
208 signature='sa{ss}s')
209 def progressStarted(self, id, metadata, profile):
210 pass
211
212 @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX,
213 signature='sss')
214 def subscribe(self, sub_type, entity_jid, profile):
215 pass
216
217 ### methods ###
218
219 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
220 in_signature='s', out_signature='a(a{ss}si)',
221 async_callbacks=None)
222 def actionsGet(self, profile_key="@DEFAULT@"):
223 return self._callback("actionsGet", str(profile_key))
224
225 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
226 in_signature='ss', out_signature='',
227 async_callbacks=None)
228 def addContact(self, entity_jid, profile_key="@DEFAULT@"):
229 return self._callback("addContact", str(entity_jid), str(profile_key))
230
231 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
232 in_signature='s', out_signature='',
233 async_callbacks=('callback', 'errback'))
234 def asyncDeleteProfile(self, profile, callback=None, errback=None):
235 return self._callback("asyncDeleteProfile", str(profile), callback=callback, errback=errback)
236
237 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
238 in_signature='sssis', out_signature='s',
239 async_callbacks=('callback', 'errback'))
240 def asyncGetParamA(self, name, category, attribute="value", security_limit=-1, profile_key="@DEFAULT@", callback=None, errback=None):
241 return self._callback("asyncGetParamA", str(name), str(category), str(attribute), security_limit, str(profile_key), callback=callback, errback=errback)
242
243 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
244 in_signature='sisss', out_signature='a{ss}',
245 async_callbacks=('callback', 'errback'))
246 def asyncGetParamsValuesFromCategory(self, category, security_limit=-1, app="", extra="", profile_key="@DEFAULT@", callback=None, errback=None):
247 return self._callback("asyncGetParamsValuesFromCategory", str(category), security_limit, str(app), str(extra), str(profile_key), callback=callback, errback=errback)
248
249 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
250 in_signature='ssa{ss}', out_signature='b',
251 async_callbacks=('callback', 'errback'))
252 def connect(self, profile_key="@DEFAULT@", password='', options={}, callback=None, errback=None):
253 return self._callback("connect", str(profile_key), str(password), options, callback=callback, errback=errback)
254
255 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
256 in_signature='ss', out_signature='(a{ss}as)',
257 async_callbacks=('callback', 'errback'))
258 def contactGet(self, arg_0, profile_key="@DEFAULT@", callback=None, errback=None):
259 return self._callback("contactGet", str(arg_0), str(profile_key), callback=callback, errback=errback)
260
261 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
262 in_signature='ss', out_signature='',
263 async_callbacks=('callback', 'errback'))
264 def delContact(self, entity_jid, profile_key="@DEFAULT@", callback=None, errback=None):
265 return self._callback("delContact", str(entity_jid), str(profile_key), callback=callback, errback=errback)
266
267 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
268 in_signature='ss', out_signature='s',
269 async_callbacks=('callback', 'errback'))
270 def devicesInfosGet(self, bare_jid, profile_key, callback=None, errback=None):
271 return self._callback("devicesInfosGet", str(bare_jid), str(profile_key), callback=callback, errback=errback)
272
273 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
274 in_signature='asa(ss)bbbbbs', out_signature='(a{sa(sss)}a{sa(sss)}a{sa(sss)})',
275 async_callbacks=('callback', 'errback'))
276 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):
277 return self._callback("discoFindByFeatures", namespaces, identities, bare_jid, service, roster, own_jid, local_device, str(profile_key), callback=callback, errback=errback)
278
279 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
280 in_signature='ssbs', out_signature='(asa(sss)a{sa(a{ss}as)})',
281 async_callbacks=('callback', 'errback'))
282 def discoInfos(self, entity_jid, node=u'', use_cache=True, profile_key="@DEFAULT@", callback=None, errback=None):
283 return self._callback("discoInfos", str(entity_jid), str(node), use_cache, str(profile_key), callback=callback, errback=errback)
284
285 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
286 in_signature='ssbs', out_signature='a(sss)',
287 async_callbacks=('callback', 'errback'))
288 def discoItems(self, entity_jid, node=u'', use_cache=True, profile_key="@DEFAULT@", callback=None, errback=None):
289 return self._callback("discoItems", str(entity_jid), str(node), use_cache, str(profile_key), callback=callback, errback=errback)
290
291 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
292 in_signature='s', out_signature='',
293 async_callbacks=('callback', 'errback'))
294 def disconnect(self, profile_key="@DEFAULT@", callback=None, errback=None):
295 return self._callback("disconnect", str(profile_key), callback=callback, errback=errback)
296
297 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
298 in_signature='s', out_signature='s',
299 async_callbacks=None)
300 def encryptionNamespaceGet(self, arg_0):
301 return self._callback("encryptionNamespaceGet", str(arg_0))
302
303 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
304 in_signature='', out_signature='s',
305 async_callbacks=None)
306 def encryptionPluginsGet(self, ):
307 return self._callback("encryptionPluginsGet", ) 242 return self._callback("encryptionPluginsGet", )
308 243
309 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 244 def dbus_encryptionTrustUIGet(self, to_jid, namespace, profile_key):
310 in_signature='sss', out_signature='s', 245 return self._callback("encryptionTrustUIGet", to_jid, namespace, profile_key)
311 async_callbacks=('callback', 'errback')) 246
312 def encryptionTrustUIGet(self, to_jid, namespace, profile_key, callback=None, errback=None): 247 def dbus_getConfig(self, section, name):
313 return self._callback("encryptionTrustUIGet", str(to_jid), str(namespace), str(profile_key), callback=callback, errback=errback) 248 return self._callback("getConfig", section, name)
314 249
315 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 250 def dbus_getContacts(self, profile_key="@DEFAULT@"):
316 in_signature='ss', out_signature='s', 251 return self._callback("getContacts", profile_key)
317 async_callbacks=None) 252
318 def getConfig(self, section, name): 253 def dbus_getContactsFromGroup(self, group, profile_key="@DEFAULT@"):
319 return self._callback("getConfig", str(section), str(name)) 254 return self._callback("getContactsFromGroup", group, profile_key)
320 255
321 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 256 def dbus_getEntitiesData(self, jids, keys, profile):
322 in_signature='s', out_signature='a(sa{ss}as)', 257 return self._callback("getEntitiesData", jids, keys, profile)
323 async_callbacks=('callback', 'errback')) 258
324 def getContacts(self, profile_key="@DEFAULT@", callback=None, errback=None): 259 def dbus_getEntityData(self, jid, keys, profile):
325 return self._callback("getContacts", str(profile_key), callback=callback, errback=errback) 260 return self._callback("getEntityData", jid, keys, profile)
326 261
327 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 262 def dbus_getFeatures(self, profile_key):
328 in_signature='ss', out_signature='as', 263 return self._callback("getFeatures", profile_key)
329 async_callbacks=None) 264
330 def getContactsFromGroup(self, group, profile_key="@DEFAULT@"): 265 def dbus_getMainResource(self, contact_jid, profile_key="@DEFAULT@"):
331 return self._callback("getContactsFromGroup", str(group), str(profile_key)) 266 return self._callback("getMainResource", contact_jid, profile_key)
332 267
333 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 268 def dbus_getParamA(self, name, category, attribute="value", profile_key="@DEFAULT@"):
334 in_signature='asass', out_signature='a{sa{ss}}', 269 return self._callback("getParamA", name, category, attribute, profile_key)
335 async_callbacks=None) 270
336 def getEntitiesData(self, jids, keys, profile): 271 def dbus_getParamsCategories(self, ):
337 return self._callback("getEntitiesData", jids, keys, str(profile))
338
339 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
340 in_signature='sass', out_signature='a{ss}',
341 async_callbacks=None)
342 def getEntityData(self, jid, keys, profile):
343 return self._callback("getEntityData", str(jid), keys, str(profile))
344
345 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
346 in_signature='s', out_signature='a{sa{ss}}',
347 async_callbacks=('callback', 'errback'))
348 def getFeatures(self, profile_key, callback=None, errback=None):
349 return self._callback("getFeatures", str(profile_key), callback=callback, errback=errback)
350
351 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
352 in_signature='ss', out_signature='s',
353 async_callbacks=None)
354 def getMainResource(self, contact_jid, profile_key="@DEFAULT@"):
355 return self._callback("getMainResource", str(contact_jid), str(profile_key))
356
357 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
358 in_signature='ssss', out_signature='s',
359 async_callbacks=None)
360 def getParamA(self, name, category, attribute="value", profile_key="@DEFAULT@"):
361 return self._callback("getParamA", str(name), str(category), str(attribute), str(profile_key))
362
363 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
364 in_signature='', out_signature='as',
365 async_callbacks=None)
366 def getParamsCategories(self, ):
367 return self._callback("getParamsCategories", ) 272 return self._callback("getParamsCategories", )
368 273
369 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 274 def dbus_getParamsUI(self, security_limit=-1, app='', extra='', profile_key="@DEFAULT@"):
370 in_signature='isss', out_signature='s', 275 return self._callback("getParamsUI", security_limit, app, extra, profile_key)
371 async_callbacks=('callback', 'errback')) 276
372 def getParamsUI(self, security_limit=-1, app='', extra='', profile_key="@DEFAULT@", callback=None, errback=None): 277 def dbus_getPresenceStatuses(self, profile_key="@DEFAULT@"):
373 return self._callback("getParamsUI", security_limit, str(app), str(extra), str(profile_key), callback=callback, errback=errback) 278 return self._callback("getPresenceStatuses", profile_key)
374 279
375 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 280 def dbus_getReady(self, ):
376 in_signature='s', out_signature='a{sa{s(sia{ss})}}', 281 return self._callback("getReady", )
377 async_callbacks=None) 282
378 def getPresenceStatuses(self, profile_key="@DEFAULT@"): 283 def dbus_getVersion(self, ):
379 return self._callback("getPresenceStatuses", str(profile_key))
380
381 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
382 in_signature='', out_signature='',
383 async_callbacks=('callback', 'errback'))
384 def getReady(self, callback=None, errback=None):
385 return self._callback("getReady", callback=callback, errback=errback)
386
387 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
388 in_signature='', out_signature='s',
389 async_callbacks=None)
390 def getVersion(self, ):
391 return self._callback("getVersion", ) 284 return self._callback("getVersion", )
392 285
393 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 286 def dbus_getWaitingSub(self, profile_key="@DEFAULT@"):
394 in_signature='s', out_signature='a{ss}', 287 return self._callback("getWaitingSub", profile_key)
395 async_callbacks=None) 288
396 def getWaitingSub(self, profile_key="@DEFAULT@"): 289 def dbus_historyGet(self, from_jid, to_jid, limit, between=True, filters='', profile="@NONE@"):
397 return self._callback("getWaitingSub", str(profile_key)) 290 return self._callback("historyGet", from_jid, to_jid, limit, between, filters, profile)
398 291
399 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 292 def dbus_imageCheck(self, arg_0):
400 in_signature='ssiba{ss}s', out_signature='a(sdssa{ss}a{ss}ss)', 293 return self._callback("imageCheck", arg_0)
401 async_callbacks=('callback', 'errback')) 294
402 def historyGet(self, from_jid, to_jid, limit, between=True, filters='', profile="@NONE@", callback=None, errback=None): 295 def dbus_imageConvert(self, source, dest, arg_2, extra):
403 return self._callback("historyGet", str(from_jid), str(to_jid), limit, between, filters, str(profile), callback=callback, errback=errback) 296 return self._callback("imageConvert", source, dest, arg_2, extra)
404 297
405 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 298 def dbus_imageGeneratePreview(self, image_path, profile_key):
406 in_signature='s', out_signature='s', 299 return self._callback("imageGeneratePreview", image_path, profile_key)
407 async_callbacks=None) 300
408 def imageCheck(self, arg_0): 301 def dbus_imageResize(self, image_path, width, height):
409 return self._callback("imageCheck", str(arg_0)) 302 return self._callback("imageResize", image_path, width, height)
410 303
411 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 304 def dbus_isConnected(self, profile_key="@DEFAULT@"):
412 in_signature='ssss', out_signature='s', 305 return self._callback("isConnected", profile_key)
413 async_callbacks=('callback', 'errback')) 306
414 def imageConvert(self, source, dest, arg_2, extra, callback=None, errback=None): 307 def dbus_launchAction(self, callback_id, data, profile_key="@DEFAULT@"):
415 return self._callback("imageConvert", str(source), str(dest), str(arg_2), str(extra), callback=callback, errback=errback) 308 return self._callback("launchAction", callback_id, data, profile_key)
416 309
417 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 310 def dbus_loadParamsTemplate(self, filename):
418 in_signature='ss', out_signature='s', 311 return self._callback("loadParamsTemplate", filename)
419 async_callbacks=('callback', 'errback')) 312
420 def imageGeneratePreview(self, image_path, profile_key, callback=None, errback=None): 313 def dbus_menuHelpGet(self, menu_id, language):
421 return self._callback("imageGeneratePreview", str(image_path), str(profile_key), callback=callback, errback=errback) 314 return self._callback("menuHelpGet", menu_id, language)
422 315
423 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 316 def dbus_menuLaunch(self, menu_type, path, data, security_limit, profile_key):
424 in_signature='sii', out_signature='s', 317 return self._callback("menuLaunch", menu_type, path, data, security_limit, profile_key)
425 async_callbacks=('callback', 'errback')) 318
426 def imageResize(self, image_path, width, height, callback=None, errback=None): 319 def dbus_menusGet(self, language, security_limit):
427 return self._callback("imageResize", str(image_path), width, height, callback=callback, errback=errback) 320 return self._callback("menusGet", language, security_limit)
428 321
429 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 322 def dbus_messageEncryptionGet(self, to_jid, profile_key):
430 in_signature='s', out_signature='b', 323 return self._callback("messageEncryptionGet", to_jid, profile_key)
431 async_callbacks=None) 324
432 def isConnected(self, profile_key="@DEFAULT@"): 325 def dbus_messageEncryptionStart(self, to_jid, namespace='', replace=False, profile_key="@NONE@"):
433 return self._callback("isConnected", str(profile_key)) 326 return self._callback("messageEncryptionStart", to_jid, namespace, replace, profile_key)
434 327
435 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 328 def dbus_messageEncryptionStop(self, to_jid, profile_key):
436 in_signature='sa{ss}s', out_signature='a{ss}', 329 return self._callback("messageEncryptionStop", to_jid, profile_key)
437 async_callbacks=('callback', 'errback')) 330
438 def launchAction(self, callback_id, data, profile_key="@DEFAULT@", callback=None, errback=None): 331 def dbus_messageSend(self, to_jid, message, subject={}, mess_type="auto", extra={}, profile_key="@NONE@"):
439 return self._callback("launchAction", str(callback_id), data, str(profile_key), callback=callback, errback=errback) 332 return self._callback("messageSend", to_jid, message, subject, mess_type, extra, profile_key)
440 333
441 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 334 def dbus_namespacesGet(self, ):
442 in_signature='s', out_signature='b',
443 async_callbacks=None)
444 def loadParamsTemplate(self, filename):
445 return self._callback("loadParamsTemplate", str(filename))
446
447 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
448 in_signature='ss', out_signature='s',
449 async_callbacks=None)
450 def menuHelpGet(self, menu_id, language):
451 return self._callback("menuHelpGet", str(menu_id), str(language))
452
453 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
454 in_signature='sasa{ss}is', out_signature='a{ss}',
455 async_callbacks=('callback', 'errback'))
456 def menuLaunch(self, menu_type, path, data, security_limit, profile_key, callback=None, errback=None):
457 return self._callback("menuLaunch", str(menu_type), path, data, security_limit, str(profile_key), callback=callback, errback=errback)
458
459 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
460 in_signature='si', out_signature='a(ssasasa{ss})',
461 async_callbacks=None)
462 def menusGet(self, language, security_limit):
463 return self._callback("menusGet", str(language), security_limit)
464
465 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
466 in_signature='ss', out_signature='s',
467 async_callbacks=None)
468 def messageEncryptionGet(self, to_jid, profile_key):
469 return self._callback("messageEncryptionGet", str(to_jid), str(profile_key))
470
471 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
472 in_signature='ssbs', out_signature='',
473 async_callbacks=('callback', 'errback'))
474 def messageEncryptionStart(self, to_jid, namespace='', replace=False, profile_key="@NONE@", callback=None, errback=None):
475 return self._callback("messageEncryptionStart", str(to_jid), str(namespace), replace, str(profile_key), callback=callback, errback=errback)
476
477 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
478 in_signature='ss', out_signature='',
479 async_callbacks=('callback', 'errback'))
480 def messageEncryptionStop(self, to_jid, profile_key, callback=None, errback=None):
481 return self._callback("messageEncryptionStop", str(to_jid), str(profile_key), callback=callback, errback=errback)
482
483 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
484 in_signature='sa{ss}a{ss}sss', out_signature='',
485 async_callbacks=('callback', 'errback'))
486 def messageSend(self, to_jid, message, subject={}, mess_type="auto", extra={}, profile_key="@NONE@", callback=None, errback=None):
487 return self._callback("messageSend", str(to_jid), message, subject, str(mess_type), str(extra), str(profile_key), callback=callback, errback=errback)
488
489 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
490 in_signature='', out_signature='a{ss}',
491 async_callbacks=None)
492 def namespacesGet(self, ):
493 return self._callback("namespacesGet", ) 335 return self._callback("namespacesGet", )
494 336
495 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 337 def dbus_paramsRegisterApp(self, xml, security_limit=-1, app=''):
496 in_signature='sis', out_signature='', 338 return self._callback("paramsRegisterApp", xml, security_limit, app)
497 async_callbacks=None) 339
498 def paramsRegisterApp(self, xml, security_limit=-1, app=''): 340 def dbus_privateDataDelete(self, namespace, key, arg_2):
499 return self._callback("paramsRegisterApp", str(xml), security_limit, str(app)) 341 return self._callback("privateDataDelete", namespace, key, arg_2)
500 342
501 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 343 def dbus_privateDataGet(self, namespace, key, profile_key):
502 in_signature='sss', out_signature='', 344 return self._callback("privateDataGet", namespace, key, profile_key)
503 async_callbacks=('callback', 'errback')) 345
504 def privateDataDelete(self, namespace, key, arg_2, callback=None, errback=None): 346 def dbus_privateDataSet(self, namespace, key, data, profile_key):
505 return self._callback("privateDataDelete", str(namespace), str(key), str(arg_2), callback=callback, errback=errback) 347 return self._callback("privateDataSet", namespace, key, data, profile_key)
506 348
507 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 349 def dbus_profileCreate(self, profile, password='', component=''):
508 in_signature='sss', out_signature='s', 350 return self._callback("profileCreate", profile, password, component)
509 async_callbacks=('callback', 'errback')) 351
510 def privateDataGet(self, namespace, key, profile_key, callback=None, errback=None): 352 def dbus_profileIsSessionStarted(self, profile_key="@DEFAULT@"):
511 return self._callback("privateDataGet", str(namespace), str(key), str(profile_key), callback=callback, errback=errback) 353 return self._callback("profileIsSessionStarted", profile_key)
512 354
513 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 355 def dbus_profileNameGet(self, profile_key="@DEFAULT@"):
514 in_signature='ssss', out_signature='', 356 return self._callback("profileNameGet", profile_key)
515 async_callbacks=('callback', 'errback')) 357
516 def privateDataSet(self, namespace, key, data, profile_key, callback=None, errback=None): 358 def dbus_profileSetDefault(self, profile):
517 return self._callback("privateDataSet", str(namespace), str(key), str(data), str(profile_key), callback=callback, errback=errback) 359 return self._callback("profileSetDefault", profile)
518 360
519 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 361 def dbus_profileStartSession(self, password='', profile_key="@DEFAULT@"):
520 in_signature='sss', out_signature='', 362 return self._callback("profileStartSession", password, profile_key)
521 async_callbacks=('callback', 'errback')) 363
522 def profileCreate(self, profile, password='', component='', callback=None, errback=None): 364 def dbus_profilesListGet(self, clients=True, components=False):
523 return self._callback("profileCreate", str(profile), str(password), str(component), callback=callback, errback=errback)
524
525 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
526 in_signature='s', out_signature='b',
527 async_callbacks=None)
528 def profileIsSessionStarted(self, profile_key="@DEFAULT@"):
529 return self._callback("profileIsSessionStarted", str(profile_key))
530
531 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
532 in_signature='s', out_signature='s',
533 async_callbacks=None)
534 def profileNameGet(self, profile_key="@DEFAULT@"):
535 return self._callback("profileNameGet", str(profile_key))
536
537 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
538 in_signature='s', out_signature='',
539 async_callbacks=None)
540 def profileSetDefault(self, profile):
541 return self._callback("profileSetDefault", str(profile))
542
543 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
544 in_signature='ss', out_signature='b',
545 async_callbacks=('callback', 'errback'))
546 def profileStartSession(self, password='', profile_key="@DEFAULT@", callback=None, errback=None):
547 return self._callback("profileStartSession", str(password), str(profile_key), callback=callback, errback=errback)
548
549 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
550 in_signature='bb', out_signature='as',
551 async_callbacks=None)
552 def profilesListGet(self, clients=True, components=False):
553 return self._callback("profilesListGet", clients, components) 365 return self._callback("profilesListGet", clients, components)
554 366
555 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 367 def dbus_progressGet(self, id, profile):
556 in_signature='ss', out_signature='a{ss}', 368 return self._callback("progressGet", id, profile)
557 async_callbacks=None) 369
558 def progressGet(self, id, profile): 370 def dbus_progressGetAll(self, profile):
559 return self._callback("progressGet", str(id), str(profile)) 371 return self._callback("progressGetAll", profile)
560 372
561 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 373 def dbus_progressGetAllMetadata(self, profile):
562 in_signature='s', out_signature='a{sa{sa{ss}}}', 374 return self._callback("progressGetAllMetadata", profile)
563 async_callbacks=None) 375
564 def progressGetAll(self, profile): 376 def dbus_rosterResync(self, profile_key="@DEFAULT@"):
565 return self._callback("progressGetAll", str(profile)) 377 return self._callback("rosterResync", profile_key)
566 378
567 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 379 def dbus_saveParamsTemplate(self, filename):
568 in_signature='s', out_signature='a{sa{sa{ss}}}', 380 return self._callback("saveParamsTemplate", filename)
569 async_callbacks=None) 381
570 def progressGetAllMetadata(self, profile): 382 def dbus_sessionInfosGet(self, profile_key):
571 return self._callback("progressGetAllMetadata", str(profile)) 383 return self._callback("sessionInfosGet", profile_key)
572 384
573 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 385 def dbus_setParam(self, name, value, category, security_limit=-1, profile_key="@DEFAULT@"):
574 in_signature='s', out_signature='', 386 return self._callback("setParam", name, value, category, security_limit, profile_key)
575 async_callbacks=('callback', 'errback')) 387
576 def rosterResync(self, profile_key="@DEFAULT@", callback=None, errback=None): 388 def dbus_setPresence(self, to_jid='', show='', statuses={}, profile_key="@DEFAULT@"):
577 return self._callback("rosterResync", str(profile_key), callback=callback, errback=errback) 389 return self._callback("setPresence", to_jid, show, statuses, profile_key)
578 390
579 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 391 def dbus_subscription(self, sub_type, entity, profile_key="@DEFAULT@"):
580 in_signature='s', out_signature='b', 392 return self._callback("subscription", sub_type, entity, profile_key)
581 async_callbacks=None) 393
582 def saveParamsTemplate(self, filename): 394 def dbus_updateContact(self, entity_jid, name, groups, profile_key="@DEFAULT@"):
583 return self._callback("saveParamsTemplate", str(filename)) 395 return self._callback("updateContact", entity_jid, name, groups, profile_key)
584 396
585 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, 397
586 in_signature='s', out_signature='a{ss}', 398 class Bridge:
587 async_callbacks=('callback', 'errback')) 399
588 def sessionInfosGet(self, profile_key, callback=None, errback=None):
589 return self._callback("sessionInfosGet", str(profile_key), callback=callback, errback=errback)
590
591 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
592 in_signature='sssis', out_signature='',
593 async_callbacks=None)
594 def setParam(self, name, value, category, security_limit=-1, profile_key="@DEFAULT@"):
595 return self._callback("setParam", str(name), str(value), str(category), security_limit, str(profile_key))
596
597 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
598 in_signature='ssa{ss}s', out_signature='',
599 async_callbacks=None)
600 def setPresence(self, to_jid='', show='', statuses={}, profile_key="@DEFAULT@"):
601 return self._callback("setPresence", str(to_jid), str(show), statuses, str(profile_key))
602
603 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
604 in_signature='sss', out_signature='',
605 async_callbacks=None)
606 def subscription(self, sub_type, entity, profile_key="@DEFAULT@"):
607 return self._callback("subscription", str(sub_type), str(entity), str(profile_key))
608
609 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
610 in_signature='ssass', out_signature='',
611 async_callbacks=None)
612 def updateContact(self, entity_jid, name, groups, profile_key="@DEFAULT@"):
613 return self._callback("updateContact", str(entity_jid), str(name), groups, str(profile_key))
614
615 def __attributes(self, in_sign):
616 """Return arguments to user given a in_sign
617 @param in_sign: in_sign in the short form (using s,a,i,b etc)
618 @return: list of arguments that correspond to a in_sign (e.g.: "sss" return "arg1, arg2, arg3")"""
619 i = 0
620 idx = 0
621 attr = []
622 while i < len(in_sign):
623 if in_sign[i] not in ["b", "y", "n", "i", "x", "q", "u", "t", "d", "s", "a"]:
624 raise ParseError("Unmanaged attribute type [%c]" % in_sign[i])
625
626 attr.append("arg_%i" % idx)
627 idx += 1
628
629 if in_sign[i] == "a":
630 i += 1
631 if (
632 in_sign[i] != "{" and in_sign[i] != "("
633 ): # FIXME: must manage tuples out of arrays
634 i += 1
635 continue # we have a simple type for the array
636 opening_car = in_sign[i]
637 assert opening_car in ["{", "("]
638 closing_car = "}" if opening_car == "{" else ")"
639 opening_count = 1
640 while True: # we have a dict or a list of tuples
641 i += 1
642 if i >= len(in_sign):
643 raise ParseError("missing }")
644 if in_sign[i] == opening_car:
645 opening_count += 1
646 if in_sign[i] == closing_car:
647 opening_count -= 1
648 if opening_count == 0:
649 break
650 i += 1
651 return attr
652
653 def addMethod(self, name, int_suffix, in_sign, out_sign, method, async_=False):
654 """Dynamically add a method to Dbus Bridge"""
655 inspect_args = inspect.getfullargspec(method)
656
657 _arguments = inspect_args.args
658 _defaults = list(inspect_args.defaults or [])
659
660 if inspect.ismethod(method):
661 # if we have a method, we don't want the first argument (usually 'self')
662 del (_arguments[0])
663
664 # first arguments are for the _callback method
665 arguments_callback = ", ".join(
666 [repr(name)]
667 + (
668 (_arguments + ["callback=callback", "errback=errback"])
669 if async_
670 else _arguments
671 )
672 )
673
674 if async_:
675 _arguments.extend(["callback", "errback"])
676 _defaults.extend([None, None])
677
678 # now we create a second list with default values
679 for i in range(1, len(_defaults) + 1):
680 _arguments[-i] = "%s = %s" % (_arguments[-i], repr(_defaults[-i]))
681
682 arguments_defaults = ", ".join(_arguments)
683
684 code = compile(
685 "def %(name)s (self,%(arguments_defaults)s): return self._callback(%(arguments_callback)s)"
686 % {
687 "name": name,
688 "arguments_defaults": arguments_defaults,
689 "arguments_callback": arguments_callback,
690 },
691 "<DBus bridge>",
692 "exec",
693 )
694 exec(code) # FIXME: to the same thing in a cleaner way, without compile/exec
695 method = locals()[name]
696 async_callbacks = ("callback", "errback") if async_ else None
697 setattr(
698 DbusObject,
699 name,
700 dbus.service.method(
701 const_INT_PREFIX + int_suffix,
702 in_signature=in_sign,
703 out_signature=out_sign,
704 async_callbacks=async_callbacks,
705 )(method),
706 )
707 function = getattr(self, name)
708 func_table = self._dbus_class_table[
709 self.__class__.__module__ + "." + self.__class__.__name__
710 ][function._dbus_interface]
711 func_table[function.__name__] = function # Needed for introspection
712
713 def addSignal(self, name, int_suffix, signature, doc={}):
714 """Dynamically add a signal to Dbus Bridge"""
715 attributes = ", ".join(self.__attributes(signature))
716 # TODO: use doc parameter to name attributes
717
718 # code = compile ('def '+name+' (self,'+attributes+'): log.debug ("'+name+' signal")', '<DBus bridge>','exec') #XXX: the log.debug is too annoying with xmllog
719 code = compile(
720 "def " + name + " (self," + attributes + "): pass", "<DBus bridge>", "exec"
721 )
722 exec(code)
723 signal = locals()[name]
724 setattr(
725 DbusObject,
726 name,
727 dbus.service.signal(const_INT_PREFIX + int_suffix, signature=signature)(
728 signal
729 ),
730 )
731 function = getattr(self, name)
732 func_table = self._dbus_class_table[
733 self.__class__.__module__ + "." + self.__class__.__name__
734 ][function._dbus_interface]
735 func_table[function.__name__] = function # Needed for introspection
736
737
738 class Bridge(object):
739 def __init__(self): 400 def __init__(self):
740 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
741 log.info("Init DBus...") 401 log.info("Init DBus...")
402 self._obj = DBusObject(const_OBJ_PATH)
403
404 async def postInit(self):
742 try: 405 try:
743 self.session_bus = dbus.SessionBus() 406 conn = await client.connect(reactor)
744 except dbus.DBusException as e: 407 except error.DBusException as e:
745 if e._dbus_error_name == "org.freedesktop.DBus.Error.NotSupported": 408 if e.errName == "org.freedesktop.DBus.Error.NotSupported":
746 log.error( 409 log.error(
747 _( 410 _(
748 "D-Bus is not launched, please see README to see instructions on how to launch it" 411 "D-Bus is not launched, please see README to see instructions on "
412 "how to launch it"
749 ) 413 )
750 ) 414 )
751 raise BridgeInitError 415 raise BridgeInitError(str(e))
752 self.dbus_name = dbus.service.BusName(const_INT_PREFIX, self.session_bus) 416
753 self.dbus_bridge = DbusObject(self.session_bus, const_OBJ_PATH) 417 conn.exportObject(self._obj)
418 await conn.requestBusName(const_INT_PREFIX)
754 419
755 def _debug(self, action, params, profile): 420 def _debug(self, action, params, profile):
756 self.dbus_bridge._debug(action, params, profile) 421 self._obj.emitSignal("_debug", action, params, profile)
757 422
758 def actionNew(self, action_data, id, security_limit, profile): 423 def actionNew(self, action_data, id, security_limit, profile):
759 self.dbus_bridge.actionNew(action_data, id, security_limit, profile) 424 self._obj.emitSignal("actionNew", action_data, id, security_limit, profile)
760 425
761 def connected(self, jid_s, profile): 426 def connected(self, jid_s, profile):
762 self.dbus_bridge.connected(jid_s, profile) 427 self._obj.emitSignal("connected", jid_s, profile)
763 428
764 def contactDeleted(self, entity_jid, profile): 429 def contactDeleted(self, entity_jid, profile):
765 self.dbus_bridge.contactDeleted(entity_jid, profile) 430 self._obj.emitSignal("contactDeleted", entity_jid, profile)
766 431
767 def disconnected(self, profile): 432 def disconnected(self, profile):
768 self.dbus_bridge.disconnected(profile) 433 self._obj.emitSignal("disconnected", profile)
769 434
770 def entityDataUpdated(self, jid, name, value, profile): 435 def entityDataUpdated(self, jid, name, value, profile):
771 self.dbus_bridge.entityDataUpdated(jid, name, value, profile) 436 self._obj.emitSignal("entityDataUpdated", jid, name, value, profile)
772 437
773 def messageEncryptionStarted(self, to_jid, encryption_data, profile_key): 438 def messageEncryptionStarted(self, to_jid, encryption_data, profile_key):
774 self.dbus_bridge.messageEncryptionStarted(to_jid, encryption_data, profile_key) 439 self._obj.emitSignal("messageEncryptionStarted", to_jid, encryption_data, profile_key)
775 440
776 def messageEncryptionStopped(self, to_jid, encryption_data, profile_key): 441 def messageEncryptionStopped(self, to_jid, encryption_data, profile_key):
777 self.dbus_bridge.messageEncryptionStopped(to_jid, encryption_data, profile_key) 442 self._obj.emitSignal("messageEncryptionStopped", to_jid, encryption_data, profile_key)
778 443
779 def messageNew(self, uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile): 444 def messageNew(self, uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile):
780 self.dbus_bridge.messageNew(uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile) 445 self._obj.emitSignal("messageNew", uid, timestamp, from_jid, to_jid, message, subject, mess_type, extra, profile)
781 446
782 def newContact(self, contact_jid, attributes, groups, profile): 447 def newContact(self, contact_jid, attributes, groups, profile):
783 self.dbus_bridge.newContact(contact_jid, attributes, groups, profile) 448 self._obj.emitSignal("newContact", contact_jid, attributes, groups, profile)
784 449
785 def paramUpdate(self, name, value, category, profile): 450 def paramUpdate(self, name, value, category, profile):
786 self.dbus_bridge.paramUpdate(name, value, category, profile) 451 self._obj.emitSignal("paramUpdate", name, value, category, profile)
787 452
788 def presenceUpdate(self, entity_jid, show, priority, statuses, profile): 453 def presenceUpdate(self, entity_jid, show, priority, statuses, profile):
789 self.dbus_bridge.presenceUpdate(entity_jid, show, priority, statuses, profile) 454 self._obj.emitSignal("presenceUpdate", entity_jid, show, priority, statuses, profile)
790 455
791 def progressError(self, id, error, profile): 456 def progressError(self, id, error, profile):
792 self.dbus_bridge.progressError(id, error, profile) 457 self._obj.emitSignal("progressError", id, error, profile)
793 458
794 def progressFinished(self, id, metadata, profile): 459 def progressFinished(self, id, metadata, profile):
795 self.dbus_bridge.progressFinished(id, metadata, profile) 460 self._obj.emitSignal("progressFinished", id, metadata, profile)
796 461
797 def progressStarted(self, id, metadata, profile): 462 def progressStarted(self, id, metadata, profile):
798 self.dbus_bridge.progressStarted(id, metadata, profile) 463 self._obj.emitSignal("progressStarted", id, metadata, profile)
799 464
800 def subscribe(self, sub_type, entity_jid, profile): 465 def subscribe(self, sub_type, entity_jid, profile):
801 self.dbus_bridge.subscribe(sub_type, entity_jid, profile) 466 self._obj.emitSignal("subscribe", sub_type, entity_jid, profile)
802 467
803 def register_method(self, name, callback): 468 def register_method(self, name, callback):
804 log.debug("registering DBus bridge method [%s]" % name) 469 log.debug(f"registering DBus bridge method [{name}]")
805 self.dbus_bridge.register_method(name, callback) 470 self._obj.register_method(name, callback)
806 471
807 def addMethod(self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}): 472 def emitSignal(self, name, *args):
808 """Dynamically add a method to Dbus Bridge""" 473 self._obj.emitSignal(name, *args)
474
475 def addMethod(
476 self, name, int_suffix, in_sign, out_sign, method, async_=False, doc={}
477 ):
478 """Dynamically add a method to D-Bus Bridge"""
809 # FIXME: doc parameter is kept only temporary, the time to remove it from calls 479 # FIXME: doc parameter is kept only temporary, the time to remove it from calls
810 log.debug("Adding method [%s] to DBus bridge" % name) 480 log.debug(f"Adding method {name!r} to D-Bus bridge")
811 self.dbus_bridge.addMethod(name, int_suffix, in_sign, out_sign, method, async_) 481 self._obj.plugin_iface.addMethod(
482 Method(name, arguments=in_sign, returns=out_sign)
483 )
484 # we have to create a method here instead of using partialmethod, because txdbus
485 # uses __func__ which doesn't work with partialmethod
486 def caller(self_, *args, **kwargs):
487 return self_._callback(name, *args, **kwargs)
488 setattr(self._obj, f"dbus_{name}", MethodType(caller, self._obj))
812 self.register_method(name, method) 489 self.register_method(name, method)
813 490
814 def addSignal(self, name, int_suffix, signature, doc={}): 491 def addSignal(self, name, int_suffix, signature, doc={}):
815 self.dbus_bridge.addSignal(name, int_suffix, signature, doc) 492 """Dynamically add a signal to D-Bus Bridge"""
816 setattr(Bridge, name, getattr(self.dbus_bridge, name)) 493 log.debug(f"Adding signal {name!r} to D-Bus bridge")
494 self._obj.plugin_iface.addSignal(Signal(name, signature))
495 setattr(Bridge, name, partialmethod(Bridge.emitSignal, name))