Mercurial > libervia-backend
comparison src/bridge/DBus.py @ 595:1f160467f5de
Fix pep8 support in src/bridge.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Fri, 18 Jan 2013 17:55:35 +0100 |
parents | 952322b1d490 |
children | 84a6e83157c2 |
comparison
equal
deleted
inserted
replaced
594:e629371a28d3 | 595:1f160467f5de |
---|---|
16 GNU Affero General Public License for more details. | 16 GNU Affero General Public License for more details. |
17 | 17 |
18 You should have received a copy of the GNU Affero General Public License | 18 You should have received a copy of the GNU Affero General Public License |
19 along with this program. If not, see <http://www.gnu.org/licenses/>. | 19 along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 """ | 20 """ |
21 | |
22 | 21 |
23 from bridge import Bridge | 22 from bridge import Bridge |
24 import dbus | 23 import dbus |
25 import dbus.service | 24 import dbus.service |
26 import dbus.mainloop.glib | 25 import dbus.mainloop.glib |
27 import inspect | 26 import inspect |
28 from logging import debug, info, error | 27 from logging import debug, info, error |
29 from twisted.internet.defer import Deferred | 28 from twisted.internet.defer import Deferred |
30 | 29 |
31 const_INT_PREFIX = "org.goffi.SAT" #Interface prefix | 30 const_INT_PREFIX = "org.goffi.SAT" # Interface prefix |
32 const_ERROR_PREFIX = const_INT_PREFIX+".error" | 31 const_ERROR_PREFIX = const_INT_PREFIX + ".error" |
33 const_OBJ_PATH = '/org/goffi/SAT/bridge' | 32 const_OBJ_PATH = '/org/goffi/SAT/bridge' |
34 const_CORE_SUFFIX = ".core" | 33 const_CORE_SUFFIX = ".core" |
35 const_PLUGIN_SUFFIX = ".plugin" | 34 const_PLUGIN_SUFFIX = ".plugin" |
36 | 35 |
36 | |
37 class ParseError(Exception): | 37 class ParseError(Exception): |
38 pass | 38 pass |
39 | 39 |
40 | |
40 class MethodNotRegistered(dbus.DBusException): | 41 class MethodNotRegistered(dbus.DBusException): |
41 _dbus_error_name = const_ERROR_PREFIX + ".MethodNotRegistered" | 42 _dbus_error_name = const_ERROR_PREFIX + ".MethodNotRegistered" |
42 | 43 |
44 | |
43 class InternalError(dbus.DBusException): | 45 class InternalError(dbus.DBusException): |
44 _dbus_error_name = const_ERROR_PREFIX + ".InternalError" | 46 _dbus_error_name = const_ERROR_PREFIX + ".InternalError" |
45 | 47 |
48 | |
46 class AsyncNotDeferred(dbus.DBusException): | 49 class AsyncNotDeferred(dbus.DBusException): |
47 _dbus_error_name = const_ERROR_PREFIX + ".AsyncNotDeferred" | 50 _dbus_error_name = const_ERROR_PREFIX + ".AsyncNotDeferred" |
48 | 51 |
52 | |
49 class DeferredNotAsync(dbus.DBusException): | 53 class DeferredNotAsync(dbus.DBusException): |
50 _dbus_error_name = const_ERROR_PREFIX + ".DeferredNotAsync" | 54 _dbus_error_name = const_ERROR_PREFIX + ".DeferredNotAsync" |
51 | 55 |
56 | |
52 class GenericException(dbus.DBusException): | 57 class GenericException(dbus.DBusException): |
53 def __init__(self, twisted_error): | 58 def __init__(self, twisted_error): |
54 super(GenericException,self).__init__() | 59 super(GenericException, self).__init__() |
55 mess = twisted_error.getErrorMessage() | 60 mess = twisted_error.getErrorMessage() |
56 self._dbus_error_name = const_ERROR_PREFIX+"."+ (mess or str(twisted_error.__class__)) | 61 self._dbus_error_name = const_ERROR_PREFIX + "." + (mess or str(twisted_error.__class__)) |
62 | |
57 | 63 |
58 class DbusObject(dbus.service.Object): | 64 class DbusObject(dbus.service.Object): |
59 | 65 |
60 def __init__(self, bus, path): | 66 def __init__(self, bus, path): |
61 dbus.service.Object.__init__(self, bus, path) | 67 dbus.service.Object.__init__(self, bus, path) |
62 debug("Init DbusObject...") | 68 debug("Init DbusObject...") |
63 self.cb={} | 69 self.cb = {} |
64 | 70 |
65 def register(self, name, cb): | 71 def register(self, name, cb): |
66 self.cb[name]=cb | 72 self.cb[name] = cb |
67 | 73 |
68 def _callback(self, name, *args, **kwargs): | 74 def _callback(self, name, *args, **kwargs): |
69 """call the callback if it exists, raise an exception else | 75 """call the callback if it exists, raise an exception else |
70 if the callback return a deferred, use async methods""" | 76 if the callback return a deferred, use async methods""" |
71 if not name in self.cb: | 77 if not name in self.cb: |
84 result = self.cb[name](*args, **kwargs) | 90 result = self.cb[name](*args, **kwargs) |
85 if async: | 91 if async: |
86 if not isinstance(result, Deferred): | 92 if not isinstance(result, Deferred): |
87 error("Asynchronous method [%s] does not return a Deferred." % name) | 93 error("Asynchronous method [%s] does not return a Deferred." % name) |
88 raise AsyncNotDeferred | 94 raise AsyncNotDeferred |
89 result.addCallback(lambda result: callback() if result==None else callback(result)) | 95 result.addCallback(lambda result: callback() if result is None else callback(result)) |
90 result.addErrback(lambda err:errback(GenericException(err))) | 96 result.addErrback(lambda err: errback(GenericException(err))) |
91 else: | 97 else: |
92 if isinstance(result, Deferred): | 98 if isinstance(result, Deferred): |
93 error("Synchronous method [%s] return a Deferred." % name) | 99 error("Synchronous method [%s] return a Deferred." % name) |
94 raise DeferredNotAsync | 100 raise DeferredNotAsync |
95 return result | 101 return result |
96 | |
97 ### signals ### | 102 ### signals ### |
98 | 103 |
99 @dbus.service.signal(const_INT_PREFIX+const_PLUGIN_SUFFIX, | 104 @dbus.service.signal(const_INT_PREFIX + const_PLUGIN_SUFFIX, |
100 signature='') | 105 signature='') |
101 def dummySignal(self): | 106 def dummySignal(self): |
102 #FIXME: workaround for addSignal (doesn't work if one method doensn't | 107 #FIXME: workaround for addSignal (doesn't work if one method doensn't |
103 # already exist for plugins), probably missing some initialisation, need | 108 # already exist for plugins), probably missing some initialisation, need |
104 # further investigations | 109 # further investigations |
172 @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX, | 177 @dbus.service.signal(const_INT_PREFIX+const_CORE_SUFFIX, |
173 signature='sss') | 178 signature='sss') |
174 def subscribe(self, sub_type, entity_jid, profile): | 179 def subscribe(self, sub_type, entity_jid, profile): |
175 pass | 180 pass |
176 | 181 |
177 | |
178 ### methods ### | 182 ### methods ### |
179 | 183 |
180 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, | 184 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, |
181 in_signature='ss', out_signature='', | 185 in_signature='ss', out_signature='', |
182 async_callbacks=None) | 186 async_callbacks=None) |
408 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, | 412 @dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX, |
409 in_signature='ssass', out_signature='', | 413 in_signature='ssass', out_signature='', |
410 async_callbacks=None) | 414 async_callbacks=None) |
411 def updateContact(self, entity_jid, name, groups, profile_key="@DEFAULT@"): | 415 def updateContact(self, entity_jid, name, groups, profile_key="@DEFAULT@"): |
412 return self._callback("updateContact", unicode(entity_jid), unicode(name), groups, unicode(profile_key)) | 416 return self._callback("updateContact", unicode(entity_jid), unicode(name), groups, unicode(profile_key)) |
413 | |
414 | 417 |
415 def __attributes(self, in_sign): | 418 def __attributes(self, in_sign): |
416 """Return arguments to user given a in_sign | 419 """Return arguments to user given a in_sign |
417 @param in_sign: in_sign in the short form (using s,a,i,b etc) | 420 @param in_sign: in_sign in the short form (using s,a,i,b etc) |
418 @return: list of arguments that correspond to a in_sign (e.g.: "sss" return "arg1, arg2, arg3")""" | 421 @return: list of arguments that correspond to a in_sign (e.g.: "sss" return "arg1, arg2, arg3")""" |
419 i=0 | 422 i = 0 |
420 idx=0 | 423 idx = 0 |
421 attr=[] | 424 attr = [] |
422 while i<len(in_sign): | 425 while i < len(in_sign): |
423 if in_sign[i] not in ['b','y','n','i','x','q','u','t','d','s','a']: | 426 if in_sign[i] not in ['b', 'y', 'n', 'i', 'x', 'q', 'u', 't', 'd', 's', 'a']: |
424 raise ParseError("Unmanaged attribute type [%c]" % in_sign[i]) | 427 raise ParseError("Unmanaged attribute type [%c]" % in_sign[i]) |
425 | 428 |
426 attr.append("arg_%i" % idx) | 429 attr.append("arg_%i" % idx) |
427 idx+=1 | 430 idx += 1 |
428 | 431 |
429 if in_sign[i] == 'a': | 432 if in_sign[i] == 'a': |
430 i+=1 | 433 i += 1 |
431 if in_sign[i]!='{' and in_sign[i]!='(': #FIXME: must manage tuples out of arrays | 434 if in_sign[i] != '{' and in_sign[i] != '(': # FIXME: must manage tuples out of arrays |
432 i+=1 | 435 i += 1 |
433 continue #we have a simple type for the array | 436 continue # we have a simple type for the array |
434 opening_car = in_sign[i] | 437 opening_car = in_sign[i] |
435 assert(opening_car in ['{','(']) | 438 assert(opening_car in ['{', '(']) |
436 closing_car = '}' if opening_car == '{' else ')' | 439 closing_car = '}' if opening_car == '{' else ')' |
437 opening_count = 1 | 440 opening_count = 1 |
438 while (True): #we have a dict or a list of tuples | 441 while (True): # we have a dict or a list of tuples |
439 i+=1 | 442 i += 1 |
440 if i>=len(in_sign): | 443 if i >= len(in_sign): |
441 raise ParseError("missing }") | 444 raise ParseError("missing }") |
442 if in_sign[i] == opening_car: | 445 if in_sign[i] == opening_car: |
443 opening_count+=1 | 446 opening_count += 1 |
444 if in_sign[i] == closing_car: | 447 if in_sign[i] == closing_car: |
445 opening_count-=1 | 448 opening_count -= 1 |
446 if opening_count == 0: | 449 if opening_count == 0: |
447 break | 450 break |
448 i+=1 | 451 i += 1 |
449 return attr | 452 return attr |
450 | 453 |
451 def addMethod(self, name, int_suffix, in_sign, out_sign, method, async=False): | 454 def addMethod(self, name, int_suffix, in_sign, out_sign, method, async=False): |
452 """Dynamically add a method to Dbus Bridge""" | 455 """Dynamically add a method to Dbus Bridge""" |
453 inspect_args = inspect.getargspec(method) | 456 inspect_args = inspect.getargspec(method) |
458 if inspect.ismethod(method): | 461 if inspect.ismethod(method): |
459 #if we have a method, we don't want the first argument (usually 'self') | 462 #if we have a method, we don't want the first argument (usually 'self') |
460 del(_arguments[0]) | 463 del(_arguments[0]) |
461 | 464 |
462 #first arguments are for the _callback method | 465 #first arguments are for the _callback method |
463 arguments_callback = ', '.join([repr(name)] + ((_arguments + ['callback=callback','errback=errback']) if async else _arguments)) | 466 arguments_callback = ', '.join([repr(name)] + ((_arguments + ['callback=callback', 'errback=errback']) if async else _arguments)) |
464 | 467 |
465 if async: | 468 if async: |
466 _arguments.extend(['callback','errback']) | 469 _arguments.extend(['callback', 'errback']) |
467 _defaults.extend([None, None]) | 470 _defaults.extend([None, None]) |
468 | 471 |
469 | |
470 #now we create a second list with default values | 472 #now we create a second list with default values |
471 for i in range(1, len(_defaults)+1): | 473 for i in range(1, len(_defaults) + 1): |
472 _arguments[-i] = "%s = %s" % (_arguments[-i], repr(_defaults[-i])) | 474 _arguments[-i] = "%s = %s" % (_arguments[-i], repr(_defaults[-i])) |
473 | 475 |
474 arguments_defaults = ', '.join(_arguments) | 476 arguments_defaults = ', '.join(_arguments) |
475 | 477 |
476 code = compile ('def %(name)s (self,%(arguments_defaults)s): return self._callback(%(arguments_callback)s)' % | 478 code = compile('def %(name)s (self,%(arguments_defaults)s): return self._callback(%(arguments_callback)s)' % |
477 {'name':name, 'arguments_defaults':arguments_defaults, 'arguments_callback':arguments_callback}, '<DBus bridge>','exec') | 479 {'name': name, 'arguments_defaults': arguments_defaults, 'arguments_callback': arguments_callback}, '<DBus bridge>', 'exec') |
478 exec (code) #FIXME: to the same thing in a cleaner way, without compile/exec | 480 exec (code) # FIXME: to the same thing in a cleaner way, without compile/exec |
479 method = locals()[name] | 481 method = locals()[name] |
480 async_callbacks = ('callback', 'errback') if async else None | 482 async_callbacks = ('callback', 'errback') if async else None |
481 setattr(DbusObject, name, dbus.service.method( | 483 setattr(DbusObject, name, dbus.service.method( |
482 const_INT_PREFIX+int_suffix, in_signature=in_sign, out_signature=out_sign, | 484 const_INT_PREFIX + int_suffix, in_signature=in_sign, out_signature=out_sign, |
483 async_callbacks=async_callbacks)(method)) | 485 async_callbacks=async_callbacks)(method)) |
484 function = getattr(self, name) | 486 function = getattr(self, name) |
485 func_table = self._dbus_class_table[self.__class__.__module__ + '.' + self.__class__.__name__][function._dbus_interface] | 487 func_table = self._dbus_class_table[self.__class__.__module__ + '.' + self.__class__.__name__][function._dbus_interface] |
486 func_table[function.__name__] = function #Needed for introspection | 488 func_table[function.__name__] = function # Needed for introspection |
487 | 489 |
488 def addSignal(self, name, int_suffix, signature, doc={}): | 490 def addSignal(self, name, int_suffix, signature, doc={}): |
489 """Dynamically add a signal to Dbus Bridge""" | 491 """Dynamically add a signal to Dbus Bridge""" |
490 attributes = ', '.join(self.__attributes(signature)) | 492 attributes = ', '.join(self.__attributes(signature)) |
491 #TODO: use doc parameter to name attributes | 493 #TODO: use doc parameter to name attributes |
492 | 494 |
493 #code = compile ('def '+name+' (self,'+attributes+'): debug ("'+name+' signal")', '<DBus bridge>','exec') #XXX: the debug is too annoying with xmllog | 495 #code = compile ('def '+name+' (self,'+attributes+'): debug ("'+name+' signal")', '<DBus bridge>','exec') #XXX: the debug is too annoying with xmllog |
494 code = compile ('def '+name+' (self,'+attributes+'): pass', '<DBus bridge>','exec') | 496 code = compile('def ' + name + ' (self,' + attributes + '): pass', '<DBus bridge>', 'exec') |
495 exec (code) | 497 exec (code) |
496 signal = locals()[name] | 498 signal = locals()[name] |
497 setattr(DbusObject, name, dbus.service.signal( | 499 setattr(DbusObject, name, dbus.service.signal( |
498 const_INT_PREFIX+int_suffix, signature=signature)(signal)) | 500 const_INT_PREFIX + int_suffix, signature=signature)(signal)) |
499 function = getattr(self, name) | 501 function = getattr(self, name) |
500 func_table = self._dbus_class_table[self.__class__.__module__ + '.' + self.__class__.__name__][function._dbus_interface] | 502 func_table = self._dbus_class_table[self.__class__.__module__ + '.' + self.__class__.__name__][function._dbus_interface] |
501 func_table[function.__name__] = function #Needed for introspection | 503 func_table[function.__name__] = function # Needed for introspection |
504 | |
502 | 505 |
503 class DBusBridge(Bridge): | 506 class DBusBridge(Bridge): |
504 def __init__(self): | 507 def __init__(self): |
505 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) | 508 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) |
506 Bridge.__init__(self) | 509 Bridge.__init__(self) |
507 info ("Init DBus...") | 510 info("Init DBus...") |
508 self.session_bus = dbus.SessionBus() | 511 self.session_bus = dbus.SessionBus() |
509 self.dbus_name = dbus.service.BusName(const_INT_PREFIX, self.session_bus) | 512 self.dbus_name = dbus.service.BusName(const_INT_PREFIX, self.session_bus) |
510 self.dbus_bridge = DbusObject(self.session_bus, const_OBJ_PATH) | 513 self.dbus_bridge = DbusObject(self.session_bus, const_OBJ_PATH) |
511 | 514 |
512 def actionResult(self, answer_type, id, data, profile): | 515 def actionResult(self, answer_type, id, data, profile): |
548 def presenceUpdate(self, entity_jid, show, priority, statuses, profile): | 551 def presenceUpdate(self, entity_jid, show, priority, statuses, profile): |
549 self.dbus_bridge.presenceUpdate(entity_jid, show, priority, statuses, profile) | 552 self.dbus_bridge.presenceUpdate(entity_jid, show, priority, statuses, profile) |
550 | 553 |
551 def subscribe(self, sub_type, entity_jid, profile): | 554 def subscribe(self, sub_type, entity_jid, profile): |
552 self.dbus_bridge.subscribe(sub_type, entity_jid, profile) | 555 self.dbus_bridge.subscribe(sub_type, entity_jid, profile) |
553 | |
554 | 556 |
555 def register(self, name, callback): | 557 def register(self, name, callback): |
556 debug("registering DBus bridge method [%s]", name) | 558 debug("registering DBus bridge method [%s]", name) |
557 self.dbus_bridge.register(name, callback) | 559 self.dbus_bridge.register(name, callback) |
558 | 560 |