1 from exceptions
import DBusException
9 def add(self
, key
, leaf
=None):
13 if self
.finite
.has_key(key
):
14 node
= self
.finite
[key
]
16 node
= SignalMatchNode()
17 self
.finite
[key
] = node
22 node
= SignalMatchNode()
25 node
.rules
.append(leaf
)
28 def get_matches(self
, key
):
31 result
.append(self
.wildcard
)
33 if self
.finite
.has_key(key
):
34 result
.append(self
.finite
[key
])
38 def get_match(self
, key
):
40 if self
.finite
.has_key(key
):
41 return self
.finite
[key
]
47 def has_children(self
):
48 if self
.wildcard
or len(self
.finite
.iterkeys()) > 0:
52 def remove_child(self
, child
, key
=None):
53 if self
.wildcard
== child
:
55 elif self
.finite
.has_key(key
):
58 class SignalMatchTree
:
59 """This class creates an ordered tree of SignalMatchRules
60 to speed searchs. Left branches are wildcard elements
61 and all other branches are concreet elements.
64 self
._tree
= SignalMatchNode()
67 interface
= self
._tree
.add(rule
.sender
)
68 signal
= interface
.add(rule
.dbus_interface
)
69 path
= signal
.add(rule
.signal_name
)
70 path
.add(rule
.path
, leaf
=rule
)
72 def exec_matches(self
, match_rule
, message
):
73 args
= message
.get_args_list()
75 sender_matches
= self
._tree
.get_matches(match_rule
.sender
)
76 for sender_node
in sender_matches
:
77 interface_matches
= sender_node
.get_matches(match_rule
.dbus_interface
)
78 for interface_node
in interface_matches
:
79 signal_matches
= interface_node
.get_matches(match_rule
.signal_name
)
80 for signal_node
in signal_matches
:
81 path_matches
= signal_node
.get_matches(match_rule
.path
)
82 for path_node
in path_matches
:
84 for rule
in path_node
.rules
:
85 if (rule
.match_args_from_list(args
)):
86 rule
.execute(message
, args
)
88 def remove(self
, rule
):
90 sender
= self
._tree
.get_match(rule
.sender
)
91 interface
= sender
.get_match(rule
.dbus_interface
)
92 signal
= interface
.get_match(rule
.signal_name
)
93 path
= signal
.get_match(rule
.path
)
96 for _rule
in path
.rules
:
97 if _rule
.is_match(rule
):
98 rule_matches
.append(_rule
)
100 for _rule
in rule_matches
:
101 path
.rules
.remove(_rule
)
104 if len(path
.rules
) == 0:
105 signal
.remove_child(path
, key
= rule
.path
)
106 if not signal
.has_children():
107 interface
.remove_child(signal
, key
= rule
.signal_name
)
108 if not interface
.has_children():
109 sender
.remove_child(interface
, key
= rule
.dbus_interface
)
110 if not sender
.has_children():
111 self
._tree
.remove_child(sender
, key
= rule
.sender
)
114 raise DBusException ("Trying to remove unkown rule: %s"%str
(rule
))
116 class SignalMatchRule
:
117 """This class represents a dbus rule used to filter signals.
118 When a rule matches a filter, the signal is propagated to the handler_funtions
120 def __init__(self
, signal_name
, dbus_interface
, sender
, path
):
121 self
.handler_functions
= []
123 self
.signal_name
= signal_name
124 self
.dbus_interface
= dbus_interface
129 def add_args_match(self
, args
):
132 def execute(self
, message
, args
=None):
135 if self
.sender_keyword
is not None:
136 keywords
[self
.sender_keyword
] = message
.get_sender()
137 if self
.path_keyword
is not None:
138 keywords
[self
.path_keyword
] = message
.get_path()
140 # optimization just in case we already extracted the args
142 args
= message
.get_args_list()
144 for handler
in self
.handler_functions
:
145 if getattr(handler
, "_dbus_pass_message", False):
146 keywords
["dbus_message"] = message
148 if len(keywords
) == 0:
151 handler(*args
, **keywords
)
153 def add_handler(self
, handler
):
154 self
.handler_functions
.append(handler
)
156 #matches only those arguments listed by self
157 def match_args_from_list(self
, args_list
):
161 last_index
= len(args_list
) - 1
162 for (index
, value
) in self
.args
.iteritems():
163 if index
> last_index
:
166 if not (args_list
[index
] == value
):
172 def match_args_from_rule(self
, rule
):
173 if self
.args
== rule
.args
:
176 if self
.args
== None or rule
.args
== None:
179 my_args_list
= self
.args
.items()
180 match_args_list
= rule
.args
.iterms()
182 if len(my_args_list
) != len(match_args_list
):
185 for (key
, value
) in my_args_list
:
186 if rule
.args
.get(key
) != value
:
191 def is_match(self
, rule
):
192 if (self
.signal_name
== rule
.signal_name
and
193 self
.dbus_interface
== rule
.dbus_interface
and
194 self
.sender
== rule
.sender
and
195 self
.path
== rule
.path
and
196 self
.match_args_from_rule(rule
)):
197 if rule
.handler_functions
== []:
200 _funcs_copy_a
= self
.handler_functions
[0:]
201 _funcs_copy_b
= rule
.handler_functions
[0:]
205 return _funcs_copy_a
== _funcs_copy_b
210 """Returns a custom representation of this DBusMatchRule that can
211 be used with _dbus_bindings
213 repr = "type='signal'"
214 if (self
.dbus_interface
):
215 repr = repr + ",interface='%s'" % (self
.dbus_interface
)
218 repr = repr + ",sender='%s'" % (self
.sender
)
221 repr = repr + ",path='%s'" % (self
.path
)
223 if (self
.signal_name
):
224 repr = repr + ",member='%s'" % (self
.signal_name
)
227 my_args_list
= self
.args
.items()
229 for (index
, value
) in my_args_list
:
230 repr = repr + ",arg%i='%s'" % (index
, value
)