comparison sat/bridge/bridge_constructor/constructors/dbus/dbus_frontend_template.py @ 3042:964abd07dc03

bridge (dbus): AsyncIO version of D-Bus bridge: The frontends D-Bus bridge has now an AIOBridge version which can be instantiated to use asyncio (the loop must be managed by frontends).
author Goffi <goffi@goffi.org>
date Tue, 01 Oct 2019 22:49:10 +0200
parents ab2696e34d29
children 9d0df638c8b4
comparison
equal deleted inserted replaced
3041:72583524cfd3 3042:964abd07dc03
15 # GNU Affero General Public License for more details. 15 # GNU Affero General Public License for more details.
16 16
17 # You should have received a copy of the GNU Affero General Public License 17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19
20 import asyncio
21 import dbus
22 import ast
20 from sat.core.i18n import _ 23 from sat.core.i18n import _
21 from bridge_frontend import BridgeException 24 from .bridge_frontend import BridgeException
22 import dbus
23 from sat.core.log import getLogger 25 from sat.core.log import getLogger
26 from sat.core.exceptions import BridgeExceptionNoService, BridgeInitError
27 from dbus.mainloop.glib import DBusGMainLoop
28
29 DBusGMainLoop(set_as_default=True)
24 log = getLogger(__name__) 30 log = getLogger(__name__)
25 from sat.core.exceptions import BridgeExceptionNoService, BridgeInitError
26 31
27 from dbus.mainloop.glib import DBusGMainLoop
28 DBusGMainLoop(set_as_default=True)
29
30 import ast
31 32
32 const_INT_PREFIX = "org.salutatoi.SAT" # Interface prefix 33 const_INT_PREFIX = "org.salutatoi.SAT" # Interface prefix
33 const_ERROR_PREFIX = const_INT_PREFIX + ".error" 34 const_ERROR_PREFIX = const_INT_PREFIX + ".error"
34 const_OBJ_PATH = '/org/salutatoi/SAT/bridge' 35 const_OBJ_PATH = '/org/salutatoi/SAT/bridge'
35 const_CORE_SUFFIX = ".core" 36 const_CORE_SUFFIX = ".core"
57 except (SyntaxError, ValueError, TypeError): 58 except (SyntaxError, ValueError, TypeError):
58 condition = '' 59 condition = ''
59 return BridgeException(name, message, condition) 60 return BridgeException(name, message, condition)
60 61
61 62
62 class Bridge(object): 63 class Bridge:
63 64
64 def bridgeConnect(self, callback, errback): 65 def bridgeConnect(self, callback, errback):
65 try: 66 try:
66 self.sessions_bus = dbus.SessionBus() 67 self.sessions_bus = dbus.SessionBus()
67 self.db_object = self.sessions_bus.get_object(const_INT_PREFIX, 68 self.db_object = self.sessions_bus.get_object(const_INT_PREFIX,
77 elif e._dbus_error_name == 'org.freedesktop.DBus.Error.NotSupported': 78 elif e._dbus_error_name == 'org.freedesktop.DBus.Error.NotSupported':
78 log.error(_("D-Bus is not launched, please see README to see instructions on how to launch it")) 79 log.error(_("D-Bus is not launched, please see README to see instructions on how to launch it"))
79 errback(BridgeInitError) 80 errback(BridgeInitError)
80 else: 81 else:
81 errback(e) 82 errback(e)
82 callback() 83 else:
84 callback()
83 #props = self.db_core_iface.getProperties() 85 #props = self.db_core_iface.getProperties()
84 86
85 def register_signal(self, functionName, handler, iface="core"): 87 def register_signal(self, functionName, handler, iface="core"):
86 if iface == "core": 88 if iface == "core":
87 self.db_core_iface.connect_to_signal(functionName, handler) 89 self.db_core_iface.connect_to_signal(functionName, handler)
135 return method(*args, **kwargs) 137 return method(*args, **kwargs)
136 138
137 return getPluginMethod 139 return getPluginMethod
138 140
139 ##METHODS_PART## 141 ##METHODS_PART##
142
143 class AIOBridge(Bridge):
144
145 def register_signal(self, functionName, handler, iface="core"):
146 loop = asyncio.get_running_loop()
147 async_handler = lambda *args: asyncio.run_coroutine_threadsafe(handler(*args), loop)
148 return super().register_signal(functionName, async_handler, iface)
149
150 def __getattribute__(self, name):
151 """ usual __getattribute__ if the method exists, else try to find a plugin method """
152 try:
153 return object.__getattribute__(self, name)
154 except AttributeError:
155 # The attribute is not found, we try the plugin proxy to find the requested method
156 def getPluginMethod(*args, **kwargs):
157 loop = asyncio.get_running_loop()
158 fut = loop.create_future()
159 method = getattr(self.db_plugin_iface, name)
160 reply_handler = lambda ret=None: loop.call_soon_threadsafe(
161 fut.set_result, ret)
162 error_handler = lambda err: loop.call_soon_threadsafe(
163 fut.set_exception, dbus_to_bridge_exception(err))
164 method(
165 *args,
166 **kwargs,
167 timeout=const_TIMEOUT,
168 reply_handler=reply_handler,
169 error_handler=error_handler
170 )
171 return fut
172
173 return getPluginMethod
174
175 def bridgeConnect(self):
176 loop = asyncio.get_running_loop()
177 fut = loop.create_future()
178 super().bridgeConnect(
179 callback=lambda: loop.call_soon_threadsafe(fut.set_result, None),
180 errback=lambda e: loop.call_soon_threadsafe(fut.set_exception, e)
181 )
182 return fut
183
184 ##ASYNC_METHODS_PART##