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 / proxies.py < prev    next >
Encoding:
Python Source  |  2006-07-17  |  8.2 KB  |  223 lines

  1. import dbus_bindings
  2. import introspect_parser
  3. import sys
  4. from exceptions import MissingReplyHandlerException, MissingErrorHandlerException, IntrospectionParserException
  5.  
  6. class DeferedMethod:
  7.     """A DeferedMethod
  8.     
  9.     This is returned instead of ProxyMethod when we are defering DBus calls
  10.     while waiting for introspection data to be returned
  11.     """
  12.     def __init__(self, proxy_method):
  13.         self._proxy_method = proxy_method
  14.         self._method_name  = proxy_method._method_name
  15.     
  16.     def __call__(self, *args, **keywords):
  17.         reply_handler = None
  18.         if keywords.has_key('reply_handler'):
  19.             reply_handler = keywords['reply_handler']
  20.  
  21.         #block for now even on async
  22.         # FIXME: put ret in async queue in future if we have a reply handler
  23.  
  24.         self._proxy_method._proxy._pending_introspect.block()
  25.         ret = self._proxy_method (*args, **keywords)
  26.         
  27.         return ret
  28.  
  29. class ProxyMethod:
  30.     """A proxy Method.
  31.  
  32.     Typically a member of a ProxyObject. Calls to the
  33.     method produce messages that travel over the Bus and are routed
  34.     to a specific named Service.
  35.     """
  36.     def __init__(self, proxy, connection, named_service, object_path, method_name, iface):
  37.         self._proxy          = proxy
  38.         self._connection     = connection
  39.         self._named_service  = named_service
  40.         self._object_path    = object_path
  41.         self._method_name    = method_name
  42.         self._dbus_interface = iface
  43.  
  44.     def __call__(self, *args, **keywords):
  45.         timeout = -1
  46.         if keywords.has_key('timeout'):
  47.             timeout = keywords['timeout']
  48.  
  49.         reply_handler = None
  50.         if keywords.has_key('reply_handler'):
  51.             reply_handler = keywords['reply_handler']
  52.  
  53.         error_handler = None
  54.         if keywords.has_key('error_handler'):
  55.             error_handler = keywords['error_handler']            
  56.  
  57.         ignore_reply = False
  58.         if keywords.has_key('ignore_reply'):
  59.             ignore_reply = keywords['ignore_reply']
  60.  
  61.  
  62.         if not(reply_handler and error_handler):
  63.             if reply_handler:
  64.                 raise MissingErrorHandlerException()
  65.             elif error_handler:
  66.                 raise MissingReplyHandlerException()
  67.  
  68.         dbus_interface = self._dbus_interface 
  69.         if keywords.has_key('dbus_interface'):
  70.             dbus_interface = keywords['dbus_interface']
  71.  
  72.         tmp_iface = ''
  73.         if dbus_interface:
  74.         tmp_iface = dbus_interface + '.'
  75.  
  76.         key = tmp_iface + self._method_name
  77.  
  78.         introspect_sig = None
  79.         if self._proxy._introspect_method_map.has_key (key):
  80.             introspect_sig = self._proxy._introspect_method_map[key]
  81.  
  82.         message = dbus_bindings.MethodCall(self._object_path, dbus_interface, self._method_name)
  83.         message.set_destination(self._named_service)
  84.         
  85.         # Add the arguments to the function
  86.         iter = message.get_iter(True)
  87.  
  88.         if introspect_sig:
  89.             for (arg, sig) in zip(args, dbus_bindings.Signature(introspect_sig)):
  90.                 iter.append_strict(arg, sig)
  91.         else:
  92.             for arg in args:
  93.                 iter.append(arg)
  94.  
  95.         if ignore_reply:
  96.             result = self._connection.send(message)
  97.             args_tuple = (result,)
  98.         elif reply_handler:
  99.             result = self._connection.send_with_reply_handlers(message, timeout, reply_handler, error_handler)
  100.             args_tuple = result
  101.         else:
  102.             reply_message = self._connection.send_with_reply_and_block(message, timeout)
  103.             args_tuple = reply_message.get_args_list()
  104.  
  105.         if len(args_tuple) == 0:
  106.             return
  107.         elif len(args_tuple) == 1:
  108.             return args_tuple[0]
  109.         else:
  110.             return args_tuple
  111.  
  112.  
  113. class ProxyObject:
  114.     """A proxy to the remote Object.
  115.  
  116.     A ProxyObject is provided by the Bus. ProxyObjects
  117.     have member functions, and can be called like normal Python objects.
  118.     """
  119.     ProxyMethodClass = ProxyMethod
  120.     DeferedMethodClass = DeferedMethod
  121.  
  122.     INTROSPECT_STATE_DONT_INTROSPECT = 0
  123.     INTROSPECT_STATE_INTROSPECT_IN_PROGRESS = 1
  124.     INTROSPECT_STATE_INTROSPECT_DONE = 2
  125.  
  126.     def __init__(self, bus, named_service, object_path, introspect=True):
  127.         self._bus           = bus
  128.         self._named_service = named_service
  129.         self._object_path   = object_path
  130.  
  131.         #PendingCall object for Introspect call
  132.         self._pending_introspect = None
  133.         #queue of async calls waiting on the Introspect to return 
  134.         self._pending_introspect_queue = []
  135.         #dictionary mapping method names to their input signatures
  136.         self._introspect_method_map = {}
  137.  
  138.         if not introspect:
  139.             self._introspect_state = self.INTROSPECT_STATE_DONT_INTROSPECT
  140.         else:
  141.             self._introspect_state = self.INTROSPECT_STATE_INTROSPECT_IN_PROGRESS
  142.             
  143.             (result, self._pending_introspect) = self._Introspect()
  144.             
  145.  
  146.     def connect_to_signal(self, signal_name, handler_function, dbus_interface=None, **keywords):
  147.         self._bus.add_signal_receiver(handler_function,
  148.                                       signal_name=signal_name,
  149.                                       dbus_interface=dbus_interface,
  150.                                       named_service=self._named_service,
  151.                                       path=self._object_path,
  152.                                       **keywords)
  153.  
  154.     def _Introspect(self):
  155.         message = dbus_bindings.MethodCall(self._object_path, 'org.freedesktop.DBus.Introspectable', 'Introspect')
  156.         message.set_destination(self._named_service)
  157.         
  158.         result = self._bus.get_connection().send_with_reply_handlers(message, -1, 
  159.                                                                      self._introspect_reply_handler, 
  160.                                                                      self._introspect_error_handler)
  161.         return result   
  162.     
  163.     def _introspect_execute_queue(self): 
  164.         for call in self._pending_introspect_queue:
  165.             (member, iface, args, keywords) = call
  166.  
  167.             introspect_sig = None
  168.  
  169.             tmp_iface = ''
  170.             if iface:
  171.                 tmp_iface = iface + '.'
  172.                     
  173.             key = tmp_iface + '.' + member
  174.             if self._introspect_method_map.has_key (key):
  175.                 introspect_sig = self._introspect_method_map[key]
  176.  
  177.             
  178.             call_object = self.ProxyMethodClass(self._bus.get_connection(),
  179.                                                 self._named_service,
  180.                                                 self._object_path, 
  181.                                                 iface, 
  182.                                                 member,
  183.                                                 introspect_sig)
  184.                                                                        
  185.             call_object(args, keywords)
  186.  
  187.     def _introspect_reply_handler(self, data):
  188.         try:
  189.             self._introspect_method_map = introspect_parser.process_introspection_data(data)
  190.         except IntrospectionParserException, e:
  191.             self._introspect_error_handler(e)
  192.             return
  193.         
  194.         self._introspect_state = self.INTROSPECT_STATE_INTROSPECT_DONE
  195.         #self._introspect_execute_queue()
  196.  
  197.     def _introspect_error_handler(self, error):
  198.         self._introspect_state = self.INTROSPECT_STATE_DONT_INTROSPECT
  199.         self._introspect_execute_queue()
  200.         sys.stderr.write("Introspect error: " + str(error) + "\n")
  201.  
  202.     def __getattr__(self, member, dbus_interface=None):
  203.         if member == '__call__':
  204.             return object.__call__
  205.         elif member.startswith('__') and member.endswith('__'):
  206.             raise AttributeError(member)
  207.         else:
  208.             ret = self.ProxyMethodClass(self, self._bus.get_connection(),
  209.                                         self._named_service,
  210.                                         self._object_path, member, 
  211.                                         dbus_interface)
  212.         
  213.             if self._introspect_state == self.INTROSPECT_STATE_INTROSPECT_IN_PROGRESS:
  214.                 ret = self.DeferedMethodClass(ret)
  215.                     
  216.             return ret
  217.  
  218.     def __repr__(self):
  219.         return '<ProxyObject wrapping %s %s %s at %#x>'%(
  220.             self._bus, self._named_service, self._object_path , id(self))
  221.     __str__ = __repr__
  222.  
  223.