home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / share / pycentral / python-dbus / site-packages / dbus / matchrules.py < prev    next >
Encoding:
Python Source  |  2006-07-17  |  7.5 KB  |  233 lines

  1. from exceptions import DBusException
  2.  
  3. class SignalMatchNode:
  4.     def __init__(self):
  5.         self.wildcard = None
  6.         self.finite = {}
  7.         self.rules = []
  8.         
  9.     def add(self, key, leaf=None):
  10.         node = None
  11.         
  12.         if key:
  13.             if self.finite.has_key(key):
  14.                 node = self.finite[key]
  15.             else:
  16.                 node = SignalMatchNode()
  17.                 self.finite[key]  = node
  18.         else:
  19.             if self.wildcard:
  20.                 node = self.wildcard
  21.             else:
  22.                 node = SignalMatchNode()
  23.                 self.wildcard = node
  24.          
  25.         node.rules.append(leaf)
  26.         return node
  27.     
  28.     def get_matches(self, key):
  29.         result = []
  30.         if self.wildcard:
  31.             result.append(self.wildcard)
  32.         
  33.         if self.finite.has_key(key):
  34.             result.append(self.finite[key])
  35.             
  36.         return result
  37.         
  38.     def get_match(self, key):
  39.         if key:
  40.            if self.finite.has_key(key):
  41.                return self.finite[key]
  42.            else:
  43.                return None
  44.         
  45.         return self.wildcard
  46.         
  47.     def has_children(self):
  48.         if self.wildcard or len(self.finite.iterkeys()) > 0:
  49.             return True
  50.         return False
  51.  
  52.     def remove_child(self, child, key=None):
  53.         if self.wildcard == child:
  54.             self.wildcard = None
  55.         elif self.finite.has_key(key):
  56.             del self.finite[key]
  57.  
  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.
  62.     """
  63.     def __init__(self):
  64.         self._tree = SignalMatchNode()
  65.     
  66.     def add(self, rule):
  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)
  71.        
  72.     def exec_matches(self, match_rule, message):
  73.         args = message.get_args_list()
  74.     
  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:
  83.                         if(path_node.rules):
  84.                             for rule in path_node.rules:
  85.                                 if (rule.match_args_from_list(args)):
  86.                                     rule.execute(message, args)
  87.             
  88.     def remove(self, rule):
  89.         try:
  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)
  94.             
  95.             rule_matches = []
  96.             for _rule in path.rules:
  97.                 if _rule.is_match(rule):
  98.                     rule_matches.append(_rule)
  99.                     
  100.             for _rule in rule_matches:
  101.                 path.rules.remove(_rule)
  102.                 
  103.             #clean up tree
  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)
  112.             
  113.         except:
  114.             raise DBusException ("Trying to remove unkown rule: %s"%str(rule))
  115.  
  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
  119.     """
  120.     def __init__(self, signal_name, dbus_interface, sender, path):
  121.         self.handler_functions = []
  122.  
  123.         self.signal_name = signal_name
  124.         self.dbus_interface = dbus_interface
  125.         self.sender = sender
  126.         self.path = path
  127.         self.args = None
  128.  
  129.     def add_args_match(self, args):
  130.         self.args = args
  131.  
  132.     def execute(self, message, args=None):
  133.         keywords = {}
  134.  
  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()
  139.  
  140.         # optimization just in case we already extracted the args
  141.         if not args:
  142.            args = message.get_args_list()
  143.            
  144.         for handler in self.handler_functions:
  145.             if getattr(handler, "_dbus_pass_message", False):
  146.                 keywords["dbus_message"] = message
  147.  
  148.             if len(keywords) == 0:
  149.                 handler(*args)
  150.             else:
  151.                 handler(*args, **keywords)
  152.  
  153.     def add_handler(self, handler):
  154.         self.handler_functions.append(handler)
  155.     
  156.     #matches only those arguments listed by self
  157.     def match_args_from_list(self, args_list):
  158.         if not self.args:
  159.             return True
  160.  
  161.         last_index = len(args_list) - 1
  162.         for (index, value) in self.args.iteritems():
  163.             if index > last_index:
  164.                 return False
  165.                 
  166.             if not (args_list[index] == value):
  167.                 return False
  168.  
  169.         return True
  170.     
  171.     #does exact matching
  172.     def match_args_from_rule(self, rule):
  173.         if self.args == rule.args:
  174.             return True
  175.  
  176.         if self.args == None or rule.args == None:
  177.             return False
  178.  
  179.         my_args_list = self.args.items()
  180.         match_args_list = rule.args.iterms()
  181.  
  182.         if len(my_args_list) != len(match_args_list):
  183.             return False
  184.  
  185.         for (key, value) in my_args_list:
  186.             if rule.args.get(key) != value:
  187.                 return False
  188.  
  189.         return True
  190.  
  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 == []:
  198.                     return True
  199.             
  200.                 _funcs_copy_a = self.handler_functions[0:]
  201.                 _funcs_copy_b = rule.handler_functions[0:]
  202.                 _funcs_copy_a.sort()
  203.                 _funcs_copy_b.sort()
  204.  
  205.                 return _funcs_copy_a == _funcs_copy_b
  206.  
  207.         return False
  208.  
  209.     def __repr__(self):
  210.         """Returns a custom representation of this DBusMatchRule that can
  211.             be used with dbus_bindings
  212.         """
  213.         repr = "type='signal'"
  214.         if (self.dbus_interface):
  215.             repr = repr + ",interface='%s'" % (self.dbus_interface)
  216.  
  217.         if (self.sender):     
  218.             repr = repr + ",sender='%s'" % (self.sender)
  219.     
  220.         if (self.path):
  221.             repr = repr + ",path='%s'" % (self.path)
  222.             
  223.         if (self.signal_name):
  224.             repr = repr + ",member='%s'" % (self.signal_name)
  225.    
  226.         if (self.args):
  227.             my_args_list = self.args.items()
  228.             my_args_list.sort()
  229.             for (index, value) in my_args_list:
  230.                 repr = repr + ",arg%i='%s'" % (index, value)
  231.  
  232.         return repr
  233.