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