diff options
Diffstat (limited to 'python')
-rw-r--r-- | python/_dbus.py | 55 | ||||
-rw-r--r-- | python/examples/example-signal-recipient.py | 3 | ||||
-rw-r--r-- | python/matchrules.py | 64 |
3 files changed, 109 insertions, 13 deletions
diff --git a/python/_dbus.py b/python/_dbus.py index 6074be16..2a290bd6 100644 --- a/python/_dbus.py +++ b/python/_dbus.py @@ -41,9 +41,10 @@ dbus_object = dbus_service.get_object('/org/freedesktop/DBus', print(dbus_object.ListServices()) """ +import dbus + import dbus_bindings -import dbus from proxies import * from exceptions import * from matchrules import * @@ -104,25 +105,67 @@ class Bus: """Get a proxy object to call over the bus""" return self.ProxyObjectClass(self, named_service, object_path) - def add_signal_receiver(self, handler_function, signal_name=None, dbus_interface=None, named_service=None, path=None): + def _create_args_dict(self, keywords): + args_dict = None + for (key, value) in keywords.iteritems(): + if key.startswith('arg'): + try: + snum = key[3:] + num = int(snum) + + if not args_dict: + args_dict = {} + + args_dict[num] = value + except ValueError: + raise TypeError("Invalid arg index %s"%snum) + else: + raise TypeError("Unknown keyword %s"%(key)) + + return args_dict + + def add_signal_receiver(self, handler_function, + signal_name=None, + dbus_inteface=None, + named_service=None, + path=None, + **keywords): + + args_dict = self._create_args_dict(keywords) + if (named_service and named_service[0] != ':'): bus_object = self.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus') named_service = bus_object.GetNameOwner(named_service, dbus_interface='org.freedesktop.DBus') match_rule = SignalMatchRule(signal_name, dbus_interface, named_service, path) + + if args_dict: + match_rule.add_args_match(args_dict) + match_rule.add_handler(handler_function) self._match_rule_tree.add(match_rule) - dbus_bindings.bus_add_match(self._connection, str(match_rule)) + dbus_bindings.bus_add_match(self._connection, repr(match_rule)) - def remove_signal_receiver(self, handler_function, signal_name=None, dbus_interface=None, named_service=None, path=None): + def remove_signal_receiver(self, handler_function, + signal_name=None, + dbus_interface=None, + named_service=None, + path=None, + **keywords): + + args_dict = self._create_args_dict(keywords) + if (named_service and named_service[0] != ':'): bus_object = self.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus') named_service = bus_object.GetNameOwner(named_service, dbus_interface='org.freedesktop.DBus') match_rule = SignalMatchRule(signal_name, dbus_interface, named_service, path) + if (args_dict): + match_rule.add_args_match(args_dict) + if (handler_function): match_rule.add_handler(handler_function) @@ -139,8 +182,8 @@ class Bus: return dbus_bindings.HANDLER_RESULT_NOT_YET_HANDLED dbus_interface = message.get_interface() - named_service = message.get_sender() - path = message.get_path() + named_service = message.get_sender() + path = message.get_path() signal_name = message.get_member() match_rule = SignalMatchRule(signal_name, dbus_interface, named_service, path) diff --git a/python/examples/example-signal-recipient.py b/python/examples/example-signal-recipient.py index 558a41f0..a06d4943 100644 --- a/python/examples/example-signal-recipient.py +++ b/python/examples/example-signal-recipient.py @@ -38,13 +38,14 @@ def catchall_hello_signals_handler(hello_string): def catchall_testservice_interface_handler(hello_string, dbus_message): print "org.designfu.TestService interface says " + hello_string + " when it sent signal " + dbus_message.get_member() -object.connect_to_signal("HelloSignal", hello_signal_handler, dbus_interface="org.designfu.TestService") +object.connect_to_signal("HelloSignal", hello_signal_handler, dbus_interface="org.designfu.TestService", arg0="Hello") #lets make a catchall bus.add_signal_receiver(catchall_signal_handler) bus.add_signal_receiver(catchall_hello_signals_handler, dbus_interface = "org.designfu.TestService", signal_name = "HelloSignal") bus.add_signal_receiver(catchall_testservice_interface_handler, dbus_interface = "org.designfu.TestService") + gobject.timeout_add(2000, emit_signal) # Tell the remote object to emit the signal diff --git a/python/matchrules.py b/python/matchrules.py index d65e3920..3a2fbedf 100644 --- a/python/matchrules.py +++ b/python/matchrules.py @@ -70,6 +70,8 @@ class SignalMatchTree: path.add(rule.path, leaf=rule) def exec_matches(self, match_rule, message): + args = message.get_args_list() + sender_matches = self._tree.get_matches(match_rule.sender) for sender_node in sender_matches: interface_matches = sender_node.get_matches(match_rule.dbus_interface) @@ -80,7 +82,8 @@ class SignalMatchTree: for path_node in path_matches: if(path_node.rules): for rule in path_node.rules: - rule.execute(message) + if (rule.match_args_from_list(args)): + rule.execute(message, args) def remove(self, rule): try: @@ -121,9 +124,16 @@ class SignalMatchRule: self.dbus_interface = dbus_interface self.sender = sender self.path = path + self.args = None - def execute(self, message): - args = message.get_args_list() + def add_args_match(self, args): + self.args = args + + def execute(self, message, args=None): + #optimization just in case we already extarcted the args + if not args: + args = message.get_args_list() + for handler in self.handler_functions: if getattr(handler, "_dbus_pass_message", False): keywords = {"dbus_message": message} @@ -133,12 +143,48 @@ class SignalMatchRule: def add_handler(self, handler): self.handler_functions.append(handler) - + + #matches only those arguments listed by self + def match_args_from_list(self, args_list): + if not self.args: + return True + + last_index = len(args_list) - 1 + for (index, value) in self.args.iteritems(): + if index > last_index: + return False + + if not (args_list[index] == value): + return False + + return True + + #does exact matching + def match_args_from_rule(self, rule): + if self.args == rule.args: + return True + + if self.args == None or rule.args == None: + return False + + my_args_list = self.args.items() + match_args_list = rule.args.iterms() + + if len(my_args_list) != len(match_args_list): + return False + + for (key, value) in my_args_list: + if rule.args.get(key) != value: + return False + + return True + def is_match(self, rule): if (self.signal_name == rule.signal_name and self.dbus_interface == rule.dbus_interface and self.sender == rule.sender and - self.path == rule.path): + self.path == rule.path and + self.match_args_from_rule(rule)): if rule.handler_functions == []: return True @@ -167,5 +213,11 @@ class SignalMatchRule: if (self.signal_name): repr = repr + ",member='%s'" % (self.signal_name) - + + if (self.args): + my_args_list = self.args.items() + my_args_list.sort() + for (index, value) in my_args_list: + repr = repr + ",arg%i='%s'" % (index, value) + return repr |