comparison src/bridge/bridge_constructor/dbus_core_template.py @ 468:c97640c90a94

D-Bus Bridge: use inspection to name attribute + fix asynchronous calls for dynamically added method, it now use deferred return value instead of callback/errback attributes
author Goffi <goffi@goffi.org>
date Fri, 30 Mar 2012 09:23:23 +0200
parents cf005701624b
children db4c2b82bab6
comparison
equal deleted inserted replaced
467:47af60767013 468:c97640c90a94
22 22
23 from bridge import Bridge 23 from bridge import Bridge
24 import dbus 24 import dbus
25 import dbus.service 25 import dbus.service
26 import dbus.mainloop.glib 26 import dbus.mainloop.glib
27 import inspect
27 from logging import debug, info, error 28 from logging import debug, info, error
28 from twisted.internet.defer import Deferred 29 from twisted.internet.defer import Deferred
29 30
30 const_INT_PREFIX = "org.goffi.SAT" #Interface prefix 31 const_INT_PREFIX = "org.goffi.SAT" #Interface prefix
31 const_ERROR_PREFIX = const_INT_PREFIX+".error" 32 const_ERROR_PREFIX = const_INT_PREFIX+".error"
80 result = self.cb[name](*args, **kwargs) 81 result = self.cb[name](*args, **kwargs)
81 if async: 82 if async:
82 if not isinstance(result, Deferred): 83 if not isinstance(result, Deferred):
83 error("Asynchronous method [%s] does not return a Deferred." % name) 84 error("Asynchronous method [%s] does not return a Deferred." % name)
84 raise AsyncNotDeferred 85 raise AsyncNotDeferred
85 result.addCallback(callback) 86 result.addCallback(lambda result: callback() if result==None else callback(result))
86 result.addErrback(lambda err:errback(GenericException(err))) 87 result.addErrback(lambda err:errback(GenericException(err)))
87 else: 88 else:
88 if isinstance(result, Deferred): 89 if isinstance(result, Deferred):
89 error("Synchronous method [%s] return a Deferred." % name) 90 error("Synchronous method [%s] return a Deferred." % name)
90 raise DeferredNotAsync 91 raise DeferredNotAsync
140 if opening_count == 0: 141 if opening_count == 0:
141 break 142 break
142 i+=1 143 i+=1
143 return attr 144 return attr
144 145
145 def addMethod(self, name, int_suffix, in_sign, out_sign, async=False, doc={}): 146 def addMethod(self, name, int_suffix, in_sign, out_sign, method, async=False):
146 """Dynamically add a method to Dbus Bridge""" 147 """Dynamically add a method to Dbus Bridge"""
147 _attributes = self.__attributes(in_sign) 148 inspect_args = inspect.getargspec(method)
149
150 _attributes = inspect_args.args
151 _defaults = list(inspect_args.defaults or [])
152
153 if inspect.ismethod(method):
154 #if we have a method, we don't want the first argument (usually 'self')
155 del(_attributes[0])
148 156
149 if async: 157 if async:
150 _attributes.extend(['callback','errback']) 158 _attributes.extend(['callback','errback'])
159 _defaults.extend(['callback', 'errback'])
151 160
152 attributes = ', '.join(_attributes) 161 attributes = ', '.join(_attributes)
153 162
154 code = compile ('def '+name+' (self,'+attributes+'): return self.cb["'+name+'"]('+attributes+')', '<DBus bridge>','exec') 163 #now we create a second list with default values
155 exec (code) 164 for i in range(1, len(_defaults)+1):
165 _attributes[-i] = "%s = %s" % (_attributes[-i], repr(_defaults[-i]))
166
167 attributes_defaults = ', '.join(_attributes)
168
169 code = compile ('def %(name)s (self,%(attributes_defaults)s): return self.cb["%(name)s"](%(attributes)s)' %
170 {'name':name, 'attributes_defaults':attributes_defaults, 'attributes':attributes}, '<DBus bridge>','exec')
171 exec (code) #FIXME: to the same thing in a cleaner way, without compile/exec
156 method = locals()[name] 172 method = locals()[name]
157 async_callbacks = ('callback', 'errback') if async else None 173 async_callbacks = ('callback', 'errback') if async else None
158 setattr(DbusObject, name, dbus.service.method( 174 setattr(DbusObject, name, dbus.service.method(
159 const_INT_PREFIX+int_suffix, in_signature=in_sign, out_signature=out_sign, 175 const_INT_PREFIX+int_suffix, in_signature=in_sign, out_signature=out_sign,
160 async_callbacks=async_callbacks)(method)) 176 async_callbacks=async_callbacks)(method))
163 func_table[function.__name__] = function #Needed for introspection 179 func_table[function.__name__] = function #Needed for introspection
164 180
165 def addSignal(self, name, int_suffix, signature, doc={}): 181 def addSignal(self, name, int_suffix, signature, doc={}):
166 """Dynamically add a signal to Dbus Bridge""" 182 """Dynamically add a signal to Dbus Bridge"""
167 attributes = ', '.join(self.__attributes(signature)) 183 attributes = ', '.join(self.__attributes(signature))
184 #TODO: use doc parameter to name attributes
168 185
169 #code = compile ('def '+name+' (self,'+attributes+'): debug ("'+name+' signal")', '<DBus bridge>','exec') #XXX: the debug is too annoying with xmllog 186 #code = compile ('def '+name+' (self,'+attributes+'): debug ("'+name+' signal")', '<DBus bridge>','exec') #XXX: the debug is too annoying with xmllog
170 code = compile ('def '+name+' (self,'+attributes+'): pass', '<DBus bridge>','exec') 187 code = compile ('def '+name+' (self,'+attributes+'): pass', '<DBus bridge>','exec')
171 exec (code) 188 exec (code)
172 signal = locals()[name] 189 signal = locals()[name]
191 debug("registering DBus bridge method [%s]", name) 208 debug("registering DBus bridge method [%s]", name)
192 self.dbus_bridge.register(name, callback) 209 self.dbus_bridge.register(name, callback)
193 210
194 def addMethod(self, name, int_suffix, in_sign, out_sign, method, async=False, doc={}): 211 def addMethod(self, name, int_suffix, in_sign, out_sign, method, async=False, doc={}):
195 """Dynamically add a method to Dbus Bridge""" 212 """Dynamically add a method to Dbus Bridge"""
213 #FIXME: doc parameter is kept only temporary, the time to remove it from calls
196 print ("Adding method [%s] to DBus bridge" % name) 214 print ("Adding method [%s] to DBus bridge" % name)
197 self.dbus_bridge.addMethod(name, int_suffix, in_sign, out_sign, async, doc) 215 self.dbus_bridge.addMethod(name, int_suffix, in_sign, out_sign, method, async)
198 self.register(name, method) 216 self.register(name, method)
199 217
200 def addSignal(self, name, int_suffix, signature, doc={}): 218 def addSignal(self, name, int_suffix, signature, doc={}):
201 self.dbus_bridge.addSignal(name, int_suffix, signature, doc) 219 self.dbus_bridge.addSignal(name, int_suffix, signature, doc)
202 setattr(DBusBridge, name, getattr(self.dbus_bridge, name)) 220 setattr(DBusBridge, name, getattr(self.dbus_bridge, name))