Mercurial > libervia-backend
comparison sat/bridge/bridge_constructor/constructors/dbus/dbus_core_template.py @ 2624:56f94936df1e
code style reformatting using black
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 27 Jun 2018 20:14:46 +0200 |
parents | 26edcf3a30eb |
children | 779351da2c13 |
comparison
equal
deleted
inserted
replaced
2623:49533de4540b | 2624:56f94936df1e |
---|---|
1 #!/usr/bin/env python2 | 1 #!/usr/bin/env python2 |
2 #-*- coding: utf-8 -*- | 2 # -*- coding: utf-8 -*- |
3 | 3 |
4 # SAT: a jabber client | 4 # SAT: a jabber client |
5 # Copyright (C) 2009-2018 Jérôme Poisson (goffi@goffi.org) | 5 # Copyright (C) 2009-2018 Jérôme Poisson (goffi@goffi.org) |
6 | 6 |
7 # This program is free software: you can redistribute it and/or modify | 7 # This program is free software: you can redistribute it and/or modify |
21 import dbus | 21 import dbus |
22 import dbus.service | 22 import dbus.service |
23 import dbus.mainloop.glib | 23 import dbus.mainloop.glib |
24 import inspect | 24 import inspect |
25 from sat.core.log import getLogger | 25 from sat.core.log import getLogger |
26 | |
26 log = getLogger(__name__) | 27 log = getLogger(__name__) |
27 from twisted.internet.defer import Deferred | 28 from twisted.internet.defer import Deferred |
28 from sat.core.exceptions import BridgeInitError | 29 from sat.core.exceptions import BridgeInitError |
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" |
32 const_OBJ_PATH = '/org/goffi/SAT/bridge' | 33 const_OBJ_PATH = "/org/goffi/SAT/bridge" |
33 const_CORE_SUFFIX = ".core" | 34 const_CORE_SUFFIX = ".core" |
34 const_PLUGIN_SUFFIX = ".plugin" | 35 const_PLUGIN_SUFFIX = ".plugin" |
35 | 36 |
36 | 37 |
37 class ParseError(Exception): | 38 class ParseError(Exception): |
71 message = twisted_error.getErrorMessage() | 72 message = twisted_error.getErrorMessage() |
72 try: | 73 try: |
73 self.args = (message, twisted_error.value.condition) | 74 self.args = (message, twisted_error.value.condition) |
74 except AttributeError: | 75 except AttributeError: |
75 self.args = (message,) | 76 self.args = (message,) |
76 self._dbus_error_name = '.'.join([const_ERROR_PREFIX, class_.__module__, class_.__name__]) | 77 self._dbus_error_name = ".".join( |
78 [const_ERROR_PREFIX, class_.__module__, class_.__name__] | |
79 ) | |
77 | 80 |
78 | 81 |
79 class DbusObject(dbus.service.Object): | 82 class DbusObject(dbus.service.Object): |
80 | |
81 def __init__(self, bus, path): | 83 def __init__(self, bus, path): |
82 dbus.service.Object.__init__(self, bus, path) | 84 dbus.service.Object.__init__(self, bus, path) |
83 log.debug("Init DbusObject...") | 85 log.debug("Init DbusObject...") |
84 self.cb = {} | 86 self.cb = {} |
85 | 87 |
91 if the callback return a deferred, use async methods""" | 93 if the callback return a deferred, use async methods""" |
92 if not name in self.cb: | 94 if not name in self.cb: |
93 raise MethodNotRegistered | 95 raise MethodNotRegistered |
94 | 96 |
95 if "callback" in kwargs: | 97 if "callback" in kwargs: |
96 #we must have errback too | 98 # we must have errback too |
97 if not "errback" in kwargs: | 99 if not "errback" in kwargs: |
98 log.error("errback is missing in method call [%s]" % name) | 100 log.error("errback is missing in method call [%s]" % name) |
99 raise InternalError | 101 raise InternalError |
100 callback = kwargs.pop("callback") | 102 callback = kwargs.pop("callback") |
101 errback = kwargs.pop("errback") | 103 errback = kwargs.pop("errback") |
105 result = self.cb[name](*args, **kwargs) | 107 result = self.cb[name](*args, **kwargs) |
106 if async: | 108 if async: |
107 if not isinstance(result, Deferred): | 109 if not isinstance(result, Deferred): |
108 log.error("Asynchronous method [%s] does not return a Deferred." % name) | 110 log.error("Asynchronous method [%s] does not return a Deferred." % name) |
109 raise AsyncNotDeferred | 111 raise AsyncNotDeferred |
110 result.addCallback(lambda result: callback() if result is None else callback(result)) | 112 result.addCallback( |
113 lambda result: callback() if result is None else callback(result) | |
114 ) | |
111 result.addErrback(lambda err: errback(GenericException(err))) | 115 result.addErrback(lambda err: errback(GenericException(err))) |
112 else: | 116 else: |
113 if isinstance(result, Deferred): | 117 if isinstance(result, Deferred): |
114 log.error("Synchronous method [%s] return a Deferred." % name) | 118 log.error("Synchronous method [%s] return a Deferred." % name) |
115 raise DeferredNotAsync | 119 raise DeferredNotAsync |
116 return result | 120 return result |
121 | |
117 ### signals ### | 122 ### signals ### |
118 | 123 |
119 @dbus.service.signal(const_INT_PREFIX + const_PLUGIN_SUFFIX, | 124 @dbus.service.signal(const_INT_PREFIX + const_PLUGIN_SUFFIX, signature="") |
120 signature='') | |
121 def dummySignal(self): | 125 def dummySignal(self): |
122 #FIXME: workaround for addSignal (doesn't work if one method doensn't | 126 # FIXME: workaround for addSignal (doesn't work if one method doensn't |
123 # already exist for plugins), probably missing some initialisation, need | 127 # already exist for plugins), probably missing some initialisation, need |
124 # further investigations | 128 # further investigations |
125 pass | 129 pass |
126 | 130 |
127 ##SIGNALS_PART## | 131 ##SIGNALS_PART## |
128 ### methods ### | 132 ### methods ### |
129 | 133 |
130 ##METHODS_PART## | 134 ##METHODS_PART## |
131 def __attributes(self, in_sign): | 135 def __attributes(self, in_sign): |
132 """Return arguments to user given a in_sign | 136 """Return arguments to user given a in_sign |
133 @param in_sign: in_sign in the short form (using s,a,i,b etc) | 137 @param in_sign: in_sign in the short form (using s,a,i,b etc) |
134 @return: list of arguments that correspond to a in_sign (e.g.: "sss" return "arg1, arg2, arg3")""" | 138 @return: list of arguments that correspond to a in_sign (e.g.: "sss" return "arg1, arg2, arg3")""" |
135 i = 0 | 139 i = 0 |
136 idx = 0 | 140 idx = 0 |
137 attr = [] | 141 attr = [] |
138 while i < len(in_sign): | 142 while i < len(in_sign): |
139 if in_sign[i] not in ['b', 'y', 'n', 'i', 'x', 'q', 'u', 't', 'd', 's', 'a']: | 143 if in_sign[i] not in ["b", "y", "n", "i", "x", "q", "u", "t", "d", "s", "a"]: |
140 raise ParseError("Unmanaged attribute type [%c]" % in_sign[i]) | 144 raise ParseError("Unmanaged attribute type [%c]" % in_sign[i]) |
141 | 145 |
142 attr.append("arg_%i" % idx) | 146 attr.append("arg_%i" % idx) |
143 idx += 1 | 147 idx += 1 |
144 | 148 |
145 if in_sign[i] == 'a': | 149 if in_sign[i] == "a": |
146 i += 1 | 150 i += 1 |
147 if in_sign[i] != '{' and in_sign[i] != '(': # FIXME: must manage tuples out of arrays | 151 if ( |
152 in_sign[i] != "{" and in_sign[i] != "(" | |
153 ): # FIXME: must manage tuples out of arrays | |
148 i += 1 | 154 i += 1 |
149 continue # we have a simple type for the array | 155 continue # we have a simple type for the array |
150 opening_car = in_sign[i] | 156 opening_car = in_sign[i] |
151 assert(opening_car in ['{', '(']) | 157 assert opening_car in ["{", "("] |
152 closing_car = '}' if opening_car == '{' else ')' | 158 closing_car = "}" if opening_car == "{" else ")" |
153 opening_count = 1 | 159 opening_count = 1 |
154 while (True): # we have a dict or a list of tuples | 160 while True: # we have a dict or a list of tuples |
155 i += 1 | 161 i += 1 |
156 if i >= len(in_sign): | 162 if i >= len(in_sign): |
157 raise ParseError("missing }") | 163 raise ParseError("missing }") |
158 if in_sign[i] == opening_car: | 164 if in_sign[i] == opening_car: |
159 opening_count += 1 | 165 opening_count += 1 |
170 | 176 |
171 _arguments = inspect_args.args | 177 _arguments = inspect_args.args |
172 _defaults = list(inspect_args.defaults or []) | 178 _defaults = list(inspect_args.defaults or []) |
173 | 179 |
174 if inspect.ismethod(method): | 180 if inspect.ismethod(method): |
175 #if we have a method, we don't want the first argument (usually 'self') | 181 # if we have a method, we don't want the first argument (usually 'self') |
176 del(_arguments[0]) | 182 del (_arguments[0]) |
177 | 183 |
178 #first arguments are for the _callback method | 184 # first arguments are for the _callback method |
179 arguments_callback = ', '.join([repr(name)] + ((_arguments + ['callback=callback', 'errback=errback']) if async else _arguments)) | 185 arguments_callback = ", ".join( |
186 [repr(name)] | |
187 + ( | |
188 (_arguments + ["callback=callback", "errback=errback"]) | |
189 if async | |
190 else _arguments | |
191 ) | |
192 ) | |
180 | 193 |
181 if async: | 194 if async: |
182 _arguments.extend(['callback', 'errback']) | 195 _arguments.extend(["callback", "errback"]) |
183 _defaults.extend([None, None]) | 196 _defaults.extend([None, None]) |
184 | 197 |
185 #now we create a second list with default values | 198 # now we create a second list with default values |
186 for i in range(1, len(_defaults) + 1): | 199 for i in range(1, len(_defaults) + 1): |
187 _arguments[-i] = "%s = %s" % (_arguments[-i], repr(_defaults[-i])) | 200 _arguments[-i] = "%s = %s" % (_arguments[-i], repr(_defaults[-i])) |
188 | 201 |
189 arguments_defaults = ', '.join(_arguments) | 202 arguments_defaults = ", ".join(_arguments) |
190 | 203 |
191 code = compile('def %(name)s (self,%(arguments_defaults)s): return self._callback(%(arguments_callback)s)' % | 204 code = compile( |
192 {'name': name, 'arguments_defaults': arguments_defaults, 'arguments_callback': arguments_callback}, '<DBus bridge>', 'exec') | 205 "def %(name)s (self,%(arguments_defaults)s): return self._callback(%(arguments_callback)s)" |
193 exec (code) # FIXME: to the same thing in a cleaner way, without compile/exec | 206 % { |
207 "name": name, | |
208 "arguments_defaults": arguments_defaults, | |
209 "arguments_callback": arguments_callback, | |
210 }, | |
211 "<DBus bridge>", | |
212 "exec", | |
213 ) | |
214 exec(code) # FIXME: to the same thing in a cleaner way, without compile/exec | |
194 method = locals()[name] | 215 method = locals()[name] |
195 async_callbacks = ('callback', 'errback') if async else None | 216 async_callbacks = ("callback", "errback") if async else None |
196 setattr(DbusObject, name, dbus.service.method( | 217 setattr( |
197 const_INT_PREFIX + int_suffix, in_signature=in_sign, out_signature=out_sign, | 218 DbusObject, |
198 async_callbacks=async_callbacks)(method)) | 219 name, |
220 dbus.service.method( | |
221 const_INT_PREFIX + int_suffix, | |
222 in_signature=in_sign, | |
223 out_signature=out_sign, | |
224 async_callbacks=async_callbacks, | |
225 )(method), | |
226 ) | |
199 function = getattr(self, name) | 227 function = getattr(self, name) |
200 func_table = self._dbus_class_table[self.__class__.__module__ + '.' + self.__class__.__name__][function._dbus_interface] | 228 func_table = self._dbus_class_table[ |
229 self.__class__.__module__ + "." + self.__class__.__name__ | |
230 ][function._dbus_interface] | |
201 func_table[function.__name__] = function # Needed for introspection | 231 func_table[function.__name__] = function # Needed for introspection |
202 | 232 |
203 def addSignal(self, name, int_suffix, signature, doc={}): | 233 def addSignal(self, name, int_suffix, signature, doc={}): |
204 """Dynamically add a signal to Dbus Bridge""" | 234 """Dynamically add a signal to Dbus Bridge""" |
205 attributes = ', '.join(self.__attributes(signature)) | 235 attributes = ", ".join(self.__attributes(signature)) |
206 #TODO: use doc parameter to name attributes | 236 # TODO: use doc parameter to name attributes |
207 | 237 |
208 #code = compile ('def '+name+' (self,'+attributes+'): log.debug ("'+name+' signal")', '<DBus bridge>','exec') #XXX: the log.debug is too annoying with xmllog | 238 # code = compile ('def '+name+' (self,'+attributes+'): log.debug ("'+name+' signal")', '<DBus bridge>','exec') #XXX: the log.debug is too annoying with xmllog |
209 code = compile('def ' + name + ' (self,' + attributes + '): pass', '<DBus bridge>', 'exec') | 239 code = compile( |
210 exec (code) | 240 "def " + name + " (self," + attributes + "): pass", "<DBus bridge>", "exec" |
241 ) | |
242 exec(code) | |
211 signal = locals()[name] | 243 signal = locals()[name] |
212 setattr(DbusObject, name, dbus.service.signal( | 244 setattr( |
213 const_INT_PREFIX + int_suffix, signature=signature)(signal)) | 245 DbusObject, |
246 name, | |
247 dbus.service.signal(const_INT_PREFIX + int_suffix, signature=signature)( | |
248 signal | |
249 ), | |
250 ) | |
214 function = getattr(self, name) | 251 function = getattr(self, name) |
215 func_table = self._dbus_class_table[self.__class__.__module__ + '.' + self.__class__.__name__][function._dbus_interface] | 252 func_table = self._dbus_class_table[ |
253 self.__class__.__module__ + "." + self.__class__.__name__ | |
254 ][function._dbus_interface] | |
216 func_table[function.__name__] = function # Needed for introspection | 255 func_table[function.__name__] = function # Needed for introspection |
217 | 256 |
218 | 257 |
219 class Bridge(object): | 258 class Bridge(object): |
220 def __init__(self): | 259 def __init__(self): |
221 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) | 260 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) |
222 log.info("Init DBus...") | 261 log.info("Init DBus...") |
223 try: | 262 try: |
224 self.session_bus = dbus.SessionBus() | 263 self.session_bus = dbus.SessionBus() |
225 except dbus.DBusException as e: | 264 except dbus.DBusException as e: |
226 if e._dbus_error_name == 'org.freedesktop.DBus.Error.NotSupported': | 265 if e._dbus_error_name == "org.freedesktop.DBus.Error.NotSupported": |
227 log.error(_(u"D-Bus is not launched, please see README to see instructions on how to launch it")) | 266 log.error( |
267 _( | |
268 u"D-Bus is not launched, please see README to see instructions on how to launch it" | |
269 ) | |
270 ) | |
228 raise BridgeInitError | 271 raise BridgeInitError |
229 self.dbus_name = dbus.service.BusName(const_INT_PREFIX, self.session_bus) | 272 self.dbus_name = dbus.service.BusName(const_INT_PREFIX, self.session_bus) |
230 self.dbus_bridge = DbusObject(self.session_bus, const_OBJ_PATH) | 273 self.dbus_bridge = DbusObject(self.session_bus, const_OBJ_PATH) |
231 | 274 |
232 ##SIGNAL_DIRECT_CALLS_PART## | 275 ##SIGNAL_DIRECT_CALLS_PART## |
233 def register_method(self, name, callback): | 276 def register_method(self, name, callback): |
234 log.debug("registering DBus bridge method [%s]" % name) | 277 log.debug("registering DBus bridge method [%s]" % name) |
235 self.dbus_bridge.register_method(name, callback) | 278 self.dbus_bridge.register_method(name, callback) |
236 | 279 |
237 def addMethod(self, name, int_suffix, in_sign, out_sign, method, async=False, doc={}): | 280 def addMethod(self, name, int_suffix, in_sign, out_sign, method, async=False, doc={}): |
238 """Dynamically add a method to Dbus Bridge""" | 281 """Dynamically add a method to Dbus Bridge""" |
239 #FIXME: doc parameter is kept only temporary, the time to remove it from calls | 282 # FIXME: doc parameter is kept only temporary, the time to remove it from calls |
240 log.debug("Adding method [%s] to DBus bridge" % name) | 283 log.debug("Adding method [%s] to DBus bridge" % name) |
241 self.dbus_bridge.addMethod(name, int_suffix, in_sign, out_sign, method, async) | 284 self.dbus_bridge.addMethod(name, int_suffix, in_sign, out_sign, method, async) |
242 self.register_method(name, method) | 285 self.register_method(name, method) |
243 | 286 |
244 def addSignal(self, name, int_suffix, signature, doc={}): | 287 def addSignal(self, name, int_suffix, signature, doc={}): |