Add timeout handling to gdbus (#2053)

* Add timeout handling to gdbus

* fix bus name

* make it silent

* fix tests

* add more wraper
This commit is contained in:
Pascal Vizeli 2020-09-14 14:22:38 +02:00 committed by GitHub
parent c9db42583b
commit ca60a69b22
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 15 deletions

View File

@ -52,18 +52,15 @@ RE_MONITOR_OUTPUT: re.Pattern[Any] = re.compile(r".+?: (?P<signal>[^ ].+) (?P<da
# Map GDBus to errors # Map GDBus to errors
MAP_GDBUS_ERROR: Dict[str, Any] = { MAP_GDBUS_ERROR: Dict[str, Any] = {
"GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown": DBusInterfaceError, "GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown": DBusInterfaceError,
"GDBus.Error:org.freedesktop.DBus.Error.Spawn.ChildExited": DBusFatalError,
"No such file or directory": DBusNotConnectedError, "No such file or directory": DBusNotConnectedError,
} }
# Commands for dbus # Commands for dbus
INTROSPECT: str = ( INTROSPECT: str = "gdbus introspect --system --dest {bus} --object-path {object} --xml"
"gdbus introspect --system --dest {bus} " "--object-path {object} --xml" CALL: str = "gdbus call --system --dest {bus} --object-path {object} --timeout 10 --method {method} {args}"
)
CALL: str = (
"gdbus call --system --dest {bus} --object-path {object} "
"--method {method} {args}"
)
MONITOR: str = "gdbus monitor --system --dest {bus}" MONITOR: str = "gdbus monitor --system --dest {bus}"
WAIT: str = "gdbus wait --system --activate {bus} --timeout 5 {bus}"
DBUS_METHOD_GETALL: str = "org.freedesktop.DBus.Properties.GetAll" DBUS_METHOD_GETALL: str = "org.freedesktop.DBus.Properties.GetAll"
@ -104,12 +101,15 @@ class DBus:
async def _init_proxy(self) -> None: async def _init_proxy(self) -> None:
"""Read interface data.""" """Read interface data."""
command = shlex.split( # Wait for dbus object to be available after restart
command_wait = shlex.split(WAIT.format(bus=self.bus_name))
await self._send(command_wait, silent=True)
# Introspect object & Parse XML
command_introspect = shlex.split(
INTROSPECT.format(bus=self.bus_name, object=self.object_path) INTROSPECT.format(bus=self.bus_name, object=self.object_path)
) )
data = await self._send(command_introspect)
# Parse XML
data = await self._send(command)
try: try:
xml = ET.fromstring(data) xml = ET.fromstring(data)
except ET.ParseError as err: except ET.ParseError as err:
@ -219,7 +219,7 @@ class DBus:
_LOGGER.error("No attributes returned for %s", interface) _LOGGER.error("No attributes returned for %s", interface)
raise DBusFatalError() from err raise DBusFatalError() from err
async def _send(self, command: List[str]) -> str: async def _send(self, command: List[str], silent=False) -> str:
"""Send command over dbus.""" """Send command over dbus."""
# Run command # Run command
_LOGGER.debug("Send dbus command: %s", command) _LOGGER.debug("Send dbus command: %s", command)
@ -237,7 +237,7 @@ class DBus:
raise DBusFatalError() from err raise DBusFatalError() from err
# Success? # Success?
if proc.returncode == 0: if proc.returncode == 0 or silent:
return data.decode() return data.decode()
# Filter error # Filter error
@ -248,7 +248,7 @@ class DBus:
raise exception() raise exception()
# General # General
_LOGGER.error("DBus return error: %s", error.strip()) _LOGGER.error("DBus return: %s", error.strip())
raise DBusFatalError() raise DBusFatalError()
def attach_signals(self, filters=None): def attach_signals(self, filters=None):

View File

@ -44,7 +44,10 @@ def dbus() -> DBus:
async def mock_get_properties(_, interface): async def mock_get_properties(_, interface):
return load_json_fixture(f"{interface.replace('.', '_')}.json") return load_json_fixture(f"{interface.replace('.', '_')}.json")
async def mock_send(_, command): async def mock_send(_, command, silent=False):
if silent:
return ""
filetype = "xml" if "--xml" in command else "fixture" filetype = "xml" if "--xml" in command else "fixture"
fixture = f"{command[6].replace('/', '_')[1:]}.{filetype}" fixture = f"{command[6].replace('/', '_')[1:]}.{filetype}"
return load_fixture(fixture) return load_fixture(fixture)