summaryrefslogtreecommitdiffstats
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/_dbus.py55
-rw-r--r--python/examples/example-signal-recipient.py3
-rw-r--r--python/matchrules.py64
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