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={}):