2 from exceptions import MissingReplyHandlerException, MissingErrorHandlerException
7 This is returned instead of ProxyMethod when we are defering DBus calls
8 while waiting for introspection data to be returned
10 This class can be used for debugging purposes
12 def __call__(self, *args, **keywords):
18 Typically a member of a ProxyObject. Calls to the
19 method produce messages that travel over the Bus and are routed
20 to a specific named Service.
22 def __init__(self, connection, named_service, object_path, dbus_interface, method_name):
23 self._connection = connection
24 self._named_service = named_service
25 self._object_path = object_path
26 self._method_name = method_name
27 self._dbus_interface = dbus_interface
29 def __call__(self, *args, **keywords):
30 dbus_interface = self._dbus_interface
31 if keywords.has_key('dbus_interface'):
32 dbus_interface = keywords['dbus_interface']
35 if keywords.has_key('timeout'):
36 timeout = keywords['timeout']
39 if keywords.has_key('reply_handler'):
40 reply_handler = keywords['reply_handler']
43 if keywords.has_key('error_handler'):
44 error_handler = keywords['error_handler']
46 if not(reply_handler and error_handler):
48 raise MissingErrorHandlerException()
50 raise MissingReplyHandlerException()
52 message = dbus_bindings.MethodCall(self._object_path, dbus_interface, self._method_name)
53 message.set_destination(self._named_service)
55 # Add the arguments to the function
56 iter = message.get_iter(True)
61 result = self._connection.send_with_reply_handlers(message, timeout, reply_handler, error_handler)
64 reply_message = self._connection.send_with_reply_and_block(message, timeout)
65 args_tuple = reply_message.get_args_list()
67 if len(args_tuple) == 0:
69 elif len(args_tuple) == 1:
76 """A proxy to the remote Object.
78 A ProxyObject is provided by the Bus. ProxyObjects
79 have member functions, and can be called like normal Python objects.
81 ProxyMethodClass = ProxyMethod
82 DeferedMethodClass = DeferedMethod
84 INTROSPECT_STATE_DONT_INTROSPECT = 0
85 INTROSPECT_STATE_INTROSPECT_IN_PROGRESS = 1
86 INTROSPECT_STATE_INTROSPECT_DONE = 2
88 #TODO: default introspect to False right now because it is not done yet
89 # make sure to default to True later
90 def __init__(self, bus, named_service, object_path, introspect=False):
92 self._named_service = named_service
93 self._object_path = object_path
95 #PendingCall object for Introspect call
96 self._pending_introspect = None
97 #queue of async calls waiting on the Introspect to return
98 self._pending_introspect_queue = []
101 self._introspect_state = self.INTROSPECT_STATE_DONT_INTROSPECT
103 self._introspect_state = self.INTROSPECT_STATE_INTROSPECT_IN_PROGRESS
105 (result, self._pending_introspect) = self._Introspect()
108 def connect_to_signal(self, signal_name, handler_function, dbus_interface=None, **keywords):
109 self._bus.add_signal_receiver(handler_function,
110 signal_name=signal_name,
111 dbus_interface=dbus_interface,
112 named_service=self._named_service,
113 path=self._object_path,
116 def _Introspect(self):
117 message = dbus_bindings.MethodCall(self._object_path, 'org.freedesktop.DBus.Introspectable', 'Introspect')
118 message.set_destination(self._named_service)
120 result = self._bus.get_connection().send_with_reply_handlers(message, -1,
121 self._introspect_reply_handler,
122 self._introspect_error_handler)
125 def _introspect_reply_handler(self, data):
126 self._introspect_state = self.INTROSPECT_STATE_INTROSPECT_DONE
128 for call in self._pending_introspect_queue:
129 (member, iface, args, keywords) = call
130 call_object = self.ProxyMethodClass(self._bus.get_connection(),
132 self._object_path, iface, member)
134 call_object(args, keywords)
136 def _introspect_error_handler(self, error):
137 self._introspect_state = self.INTROSPECT_STATE_DONT_INTROSPECT
139 def __getattr__(self, member, **keywords):
140 if member == '__call__':
141 return object.__call__
142 elif member.startswith('__') and member.endswith('__'):
143 raise AttributeError(member)
146 if keywords.has_key('dbus_interface'):
147 iface = keywords['dbus_interface']
149 if self._introspect_state == self.INTROSPECT_STATE_INTROSPECT_IN_PROGRESS:
151 if keywords.has_key('reply_handler'):
152 reply_handler = keywords['reply_handler']
155 if keywords.has_key('error_handler'):
156 error_handler = keywords['error_handler']
158 if not reply_handler:
159 self._pending_introspect.block()
161 call = (memeber, iface, args, keywords)
162 self._pending_introspect_queue.append(call)
164 ret = self.DeferedMethodClass()
167 ret = self.ProxyMethodClass(self._bus.get_connection(),
169 self._object_path, iface, member)
173 return '<ProxyObject wrapping %s %s %s at %x>'%(
174 self._bus, self._named_service, self._object_path , id(self))