diff --git a/somafm_tui/mpris.py b/somafm_tui/mpris.py index 9e21ffa..d5721c7 100644 --- a/somafm_tui/mpris.py +++ b/somafm_tui/mpris.py @@ -44,9 +44,39 @@ except Exception: # pragma: no cover def emit_properties_changed(self, *args: Any, **kwargs: Any) -> None: return None + class _StubProperty: # type: ignore[no-redef] + """Stand-in for ``dbus_next.service.dbus_property`` on D-Bus-less hosts. + + It has to behave like a descriptor that also supports ``.setter()``, + because the interfaces below define read/write properties with the + usual decorator idiom. Importing this module must never fail just + because there is no session bus (macOS, Windows, minimal containers). + """ + + def __init__(self, fget: Any = None) -> None: + self.fget = fget + self.fset: Any = None + + def getter(self, fget: Any) -> "_StubProperty": + self.fget = fget + return self + + def setter(self, fset: Any) -> "_StubProperty": + self.fset = fset + return self + + def __get__(self, obj: Any, objtype: Any = None) -> Any: + if obj is None or self.fget is None: + return self + return self.fget(obj) + + def __set__(self, obj: Any, value: Any) -> None: + if self.fset is not None: + self.fset(obj, value) + def dbus_property(*args: Any, **kwargs: Any): # type: ignore[no-redef] - def decorator(function): - return function + def decorator(function: Any) -> _StubProperty: + return _StubProperty(function) return decorator @@ -254,6 +284,9 @@ class _PlayerInterface(ServiceInterface): class MprisService: + #: Status-bar name for this backend (see :mod:`somafm_tui.mediasession`). + label = "mpris" + def __init__( self, actions: "queue.Queue[str]", enabled: bool = True ) -> None: