diff options
author | Simon McVittie <smcv@collabora.com> | 2023-08-16 12:25:41 +0000 |
---|---|---|
committer | Simon McVittie <smcv@collabora.com> | 2023-08-16 12:25:41 +0000 |
commit | af204e52ddae8084516a98bbf2f75f58ee1de353 (patch) | |
tree | 6af106bb7a09476702c041b2b3be237e431cd4dc | |
parent | d8c0e6ae3223085379f18164f9e102f7c3eea58a (diff) | |
parent | d159c6115f53b83b934e5537ba94268ce4bffa49 (diff) |
Merge branch 'arg0namespace' into 'master'
Add support for arg0namespace in add_signal_receiver
See merge request dbus/dbus-python!27
-rw-r--r-- | dbus/connection.py | 24 | ||||
-rw-r--r-- | dbus/proxies.py | 5 | ||||
-rwxr-xr-x | test/test-standalone.py | 36 |
3 files changed, 63 insertions, 2 deletions
diff --git a/dbus/connection.py b/dbus/connection.py index 46d74d4..621e54b 100644 --- a/dbus/connection.py +++ b/dbus/connection.py @@ -55,7 +55,9 @@ class SignalMatch(object): '_byte_arrays', '_conn_weakref', '_destination_keyword', '_interface_keyword', '_message_keyword', '_member_keyword', - '_sender_keyword', '_path_keyword', '_int_args_match'] + '_sender_keyword', '_path_keyword', '_int_args_match', + '_arg0namespace' + ] __slots__ = tuple(_slots) @@ -64,7 +66,7 @@ class SignalMatch(object): sender_keyword=None, path_keyword=None, interface_keyword=None, member_keyword=None, message_keyword=None, destination_keyword=None, - **kwargs): + arg0namespace=None, **kwargs): if member is not None: validate_member_name(member) if dbus_interface is not None: @@ -80,6 +82,7 @@ class SignalMatch(object): self._interface = dbus_interface self._member = member self._path = object_path + self._arg0namespace = arg0namespace self._handler = handler # if the connection is actually a bus, it's responsible for changing @@ -141,6 +144,8 @@ class SignalMatch(object): rule.append("interface='%s'" % self._interface) if self._member is not None: rule.append("member='%s'" % self._member) + if self._arg0namespace is not None: + rule.append("arg0namespace='%s'" % self._arg0namespace) if self._int_args_match is not None: for index, value in self._int_args_match.items(): rule.append("arg%d='%s'" % (index, value)) @@ -187,6 +192,16 @@ class SignalMatch(object): or not isinstance(args[index], String) or args[index] != value): return False + if self._arg0namespace is not None: + kwargs = dict(byte_arrays=True) + args = message.get_args_list(**kwargs) + namespace_len = len(self._arg0namespace) + if ( len(args) == 0 + or not isinstance(args[0], String) + or not args[0].startswith(self._arg0namespace) + or args[0][namespace_len:namespace_len + 1] not in ('', '.') + ): + return False # these have likely already been checked by the match tree if self._member not in (None, message.get_member()): @@ -382,6 +397,11 @@ class Connection(_Connection): is the value given for that keyword parameter. As of this time only string arguments can be matched (in particular, object paths and signatures can't). + `arg0namespace` : str + If not None (the default) match only signals where the first + argument is a string that either is equal to the + keyword parameter, or starts with the keyword parameter + followed by a dot (and optionally more text). `named_service` : str A deprecated alias for `bus_name`. """ diff --git a/dbus/proxies.py b/dbus/proxies.py index 487976c..a31b5ea 100644 --- a/dbus/proxies.py +++ b/dbus/proxies.py @@ -361,6 +361,11 @@ class ProxyObject(object): is the value given for that keyword parameter. As of this time only string arguments can be matched (in particular, object paths and signatures can't). + `arg0namespace` : str + If not None (the default) match only signals where the first + argument is a string that either is equal to the + keyword parameter, or starts with the keyword parameter + followed by a dot (and optionally more text). """ return \ self._bus.add_signal_receiver(handler_function, diff --git a/test/test-standalone.py b/test/test-standalone.py index c091228..7cca6a0 100755 --- a/test/test-standalone.py +++ b/test/test-standalone.py @@ -581,6 +581,42 @@ class TestMatching(unittest.TestCase): self._message.append('/', signature='o') self.assertFalse(self._match.maybe_handle_message(self._message)) +class TestArg0Namespace(unittest.TestCase): + def setUp(self): + self._match = dbus.connection.SignalMatch(object, None, '/', None, None, + None, arg0namespace='org.freedesktop.dbus-python') + + def test_invalid_arg1namespace(self): + try: + dbus.connection.SignalMatch(object, None, '/', None, None, + None, arg1namespace='org.freedesktop.dbus-python') + except TypeError: + pass + else: + raise AssertionError('arg1namespace is not a valid keyword argument') + + def test_namespace_match(self): + message = _dbus_bindings.SignalMessage('/', 'a.b', 'c') + message.append('org.freedesktop.dbus-python', signature='s') + self.assertTrue(self._match.maybe_handle_message(message)) + + def test_namespace_match2(self): + message = _dbus_bindings.SignalMessage('/', 'a.b', 'c') + message.append('org.freedesktop.dbus-python.test', signature='s') + self.assertTrue(self._match.maybe_handle_message(message)) + + def test_namespace_mismatch(self): + message = _dbus_bindings.SignalMessage('/', 'a.b', 'c') + message.append('org.freedesktop.dbus-python-test', signature='s') + self.assertFalse(self._match.maybe_handle_message(message)) + + def test_namespace_type_mismatch(self): + match = dbus.connection.SignalMatch(object, None, '/', None, None, + None, arg0namespace='1') + message = _dbus_bindings.SignalMessage('/', 'a.b', 'c') + message.append(1, signature='i') + self.assertFalse(match.maybe_handle_message(message)) + class TestVersion(unittest.TestCase): if sys.version_info[:2] < (2, 7): def assertGreater(self, first, second): |