Added option for methods to inject the caller bus name into a keyword argument
This commit is contained in:
@@ -461,7 +461,12 @@ class MessageBus(BaseMessageBus):
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""A coroutine method handler."""
|
"""A coroutine method handler."""
|
||||||
args = msg_body_to_args(msg) if msg.unix_fds else msg.body
|
args = msg_body_to_args(msg) if msg.unix_fds else msg.body
|
||||||
fut: asyncio.Future = asyncio.ensure_future(method.fn(interface, *args))
|
kwargs = {}
|
||||||
|
if method.caller_argument is not None:
|
||||||
|
kwargs = {method.caller_argument: msg.sender}
|
||||||
|
fut: asyncio.Future = asyncio.ensure_future(
|
||||||
|
method.fn(interface, *args, **kwargs)
|
||||||
|
)
|
||||||
# Hold a strong reference to the future to ensure
|
# Hold a strong reference to the future to ensure
|
||||||
# it is not garbage collected before it is done.
|
# it is not garbage collected before it is done.
|
||||||
self._pending_futures.add(fut)
|
self._pending_futures.add(fut)
|
||||||
|
|||||||
@@ -38,7 +38,11 @@ class _MethodCallbackProtocol(Protocol):
|
|||||||
|
|
||||||
class _Method:
|
class _Method:
|
||||||
def __init__(
|
def __init__(
|
||||||
self, fn: _MethodCallbackProtocol, name: str, disabled: bool = False
|
self,
|
||||||
|
fn: _MethodCallbackProtocol,
|
||||||
|
name: str,
|
||||||
|
disabled: bool = False,
|
||||||
|
caller_arg: str | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
in_signature = ""
|
in_signature = ""
|
||||||
out_signature = ""
|
out_signature = ""
|
||||||
@@ -50,6 +54,9 @@ class _Method:
|
|||||||
if i == 0:
|
if i == 0:
|
||||||
# first is self
|
# first is self
|
||||||
continue
|
continue
|
||||||
|
if param.name == caller_arg:
|
||||||
|
# this is an internal argument and is not exposed to D-Bus
|
||||||
|
continue
|
||||||
annotation = parse_annotation(param.annotation)
|
annotation = parse_annotation(param.annotation)
|
||||||
if not annotation:
|
if not annotation:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
@@ -72,9 +79,12 @@ class _Method:
|
|||||||
self.out_signature = out_signature
|
self.out_signature = out_signature
|
||||||
self.in_signature_tree = get_signature_tree(in_signature)
|
self.in_signature_tree = get_signature_tree(in_signature)
|
||||||
self.out_signature_tree = get_signature_tree(out_signature)
|
self.out_signature_tree = get_signature_tree(out_signature)
|
||||||
|
self.caller_argument = caller_arg
|
||||||
|
|
||||||
|
|
||||||
def method(name: str | None = None, disabled: bool = False) -> Callable:
|
def method(
|
||||||
|
name: str | None = None, disabled: bool = False, inject_caller: bool | str = False
|
||||||
|
) -> Callable:
|
||||||
"""A decorator to mark a class method of a :class:`ServiceInterface` to be a DBus service method.
|
"""A decorator to mark a class method of a :class:`ServiceInterface` to be a DBus service method.
|
||||||
|
|
||||||
The parameters and return value must each be annotated with a signature
|
The parameters and return value must each be annotated with a signature
|
||||||
@@ -94,6 +104,8 @@ def method(name: str | None = None, disabled: bool = False) -> Callable:
|
|||||||
:type name: str
|
:type name: str
|
||||||
:param disabled: If set to true, the method will not be visible to clients.
|
:param disabled: If set to true, the method will not be visible to clients.
|
||||||
:type disabled: bool
|
:type disabled: bool
|
||||||
|
:param inject_caller: If set to true, will inject the caller bus name into the `caller` kwarg. If set to a string, will instead use that value as the kwarg.
|
||||||
|
:type inject_caller: str | bool
|
||||||
|
|
||||||
:example:
|
:example:
|
||||||
|
|
||||||
@@ -111,6 +123,14 @@ def method(name: str | None = None, disabled: bool = False) -> Callable:
|
|||||||
raise TypeError("name must be a string")
|
raise TypeError("name must be a string")
|
||||||
if type(disabled) is not bool:
|
if type(disabled) is not bool:
|
||||||
raise TypeError("disabled must be a bool")
|
raise TypeError("disabled must be a bool")
|
||||||
|
if type(inject_caller) is not bool or type(caller_arg) is not str:
|
||||||
|
raise TypeError("inject_caller must be a string or bool")
|
||||||
|
|
||||||
|
caller_arg = None
|
||||||
|
if inject_caller is True:
|
||||||
|
caller_arg = "caller"
|
||||||
|
elif type(inject_caller) is str:
|
||||||
|
caller_arg = inject_caller
|
||||||
|
|
||||||
def decorator(fn: Callable) -> Callable:
|
def decorator(fn: Callable) -> Callable:
|
||||||
@wraps(fn)
|
@wraps(fn)
|
||||||
@@ -118,7 +138,9 @@ def method(name: str | None = None, disabled: bool = False) -> Callable:
|
|||||||
fn(*args, **kwargs)
|
fn(*args, **kwargs)
|
||||||
|
|
||||||
fn_name = name if name else fn.__name__
|
fn_name = name if name else fn.__name__
|
||||||
wrapped.__dict__["__DBUS_METHOD"] = _Method(fn, fn_name, disabled=disabled)
|
wrapped.__dict__["__DBUS_METHOD"] = _Method(
|
||||||
|
fn, fn_name, disabled=disabled, caller_arg=caller_arg
|
||||||
|
)
|
||||||
|
|
||||||
return wrapped
|
return wrapped
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user