comparison sat_frontends/bridge/dbus_bridge.py @ 3648:71cfe9334f73

bridge (dbus/frontend): reintrospect signature in case of guess error: When a "Unable to guess signature […]" `ValueError` is raised during a method call, the signatures are re-introspected. This should fix this issue when a frontend is launched just after to the backend (this happens notably with tests).
author Goffi <goffi@goffi.org>
date Wed, 08 Sep 2021 11:16:21 +0200
parents 7550ae9cfbac
children 524856bd7b19
comparison
equal deleted inserted replaced
3647:57d43e3e0095 3648:71cfe9334f73
138 if async_: 138 if async_:
139 kwargs['timeout'] = const_TIMEOUT 139 kwargs['timeout'] = const_TIMEOUT
140 kwargs['reply_handler'] = _callback 140 kwargs['reply_handler'] = _callback
141 kwargs['error_handler'] = lambda err: _errback(dbus_to_bridge_exception(err)) 141 kwargs['error_handler'] = lambda err: _errback(dbus_to_bridge_exception(err))
142 142
143 return method(*args, **kwargs) 143 try:
144 return method(*args, **kwargs)
145 except ValueError as e:
146 if e.args[0].startswith("Unable to guess signature"):
147 # XXX: if frontend is started too soon after backend, the
148 # inspection misses methods (notably plugin dynamically added
149 # methods). The following hack works around that by redoing the
150 # cache of introspected methods signatures.
151 log.debug("using hack to work around inspection issue")
152 proxy = self.db_plugin_iface.proxy_object
153 IN_PROGRESS = proxy.INTROSPECT_STATE_INTROSPECT_IN_PROGRESS
154 proxy._introspect_state = IN_PROGRESS
155 proxy._Introspect()
156 return self.db_plugin_iface.get_dbus_method(name)(*args, **kwargs)
157 raise e
144 158
145 return getPluginMethod 159 return getPluginMethod
146 160
147 def actionsGet(self, profile_key="@DEFAULT@", callback=None, errback=None): 161 def actionsGet(self, profile_key="@DEFAULT@", callback=None, errback=None):
148 if callback is None: 162 if callback is None:
928 method = getattr(self.db_plugin_iface, name) 942 method = getattr(self.db_plugin_iface, name)
929 reply_handler = lambda ret=None: loop.call_soon_threadsafe( 943 reply_handler = lambda ret=None: loop.call_soon_threadsafe(
930 fut.set_result, ret) 944 fut.set_result, ret)
931 error_handler = lambda err: loop.call_soon_threadsafe( 945 error_handler = lambda err: loop.call_soon_threadsafe(
932 fut.set_exception, dbus_to_bridge_exception(err)) 946 fut.set_exception, dbus_to_bridge_exception(err))
933 method( 947 try:
934 *args, 948 method(
935 **kwargs, 949 *args,
936 timeout=const_TIMEOUT, 950 **kwargs,
937 reply_handler=reply_handler, 951 timeout=const_TIMEOUT,
938 error_handler=error_handler 952 reply_handler=reply_handler,
939 ) 953 error_handler=error_handler
954 )
955 except ValueError as e:
956 if e.args[0].startswith("Unable to guess signature"):
957 # same hack as for Bridge.__getattribute__
958 log.warning("using hack to work around inspection issue")
959 proxy = self.db_plugin_iface.proxy_object
960 IN_PROGRESS = proxy.INTROSPECT_STATE_INTROSPECT_IN_PROGRESS
961 proxy._introspect_state = IN_PROGRESS
962 proxy._Introspect()
963 self.db_plugin_iface.get_dbus_method(name)(
964 *args,
965 **kwargs,
966 timeout=const_TIMEOUT,
967 reply_handler=reply_handler,
968 error_handler=error_handler
969 )
970
971 else:
972 raise e
940 return fut 973 return fut
941 974
942 return getPluginMethod 975 return getPluginMethod
943 976
944 def bridgeConnect(self): 977 def bridgeConnect(self):