2 import introspect_parser
4 from exceptions
import MissingReplyHandlerException
, MissingErrorHandlerException
, IntrospectionParserException
9 This is returned instead of ProxyMethod when we are defering DBus calls
10 while waiting for introspection data to be returned
12 def __init__(self
, proxy_method
):
13 self
._proxy
_method
= proxy_method
14 self
._method
_name
= proxy_method
._method
_name
16 def __call__(self
, *args
, **keywords
):
18 if keywords
.has_key('reply_handler'):
19 reply_handler
= keywords
['reply_handler']
21 #block for now even on async
22 # FIXME: put ret in async queue in future if we have a reply handler
24 self
._proxy
_method
._proxy
._pending
_introspect
.block()
25 ret
= self
._proxy
_method
(*args
, **keywords
)
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.
36 def __init__(self
, proxy
, connection
, named_service
, object_path
, method_name
, iface
):
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
44 def __call__(self
, *args
, **keywords
):
46 if keywords
.has_key('timeout'):
47 timeout
= keywords
['timeout']
50 if keywords
.has_key('reply_handler'):
51 reply_handler
= keywords
['reply_handler']
54 if keywords
.has_key('error_handler'):
55 error_handler
= keywords
['error_handler']
58 if keywords
.has_key('ignore_reply'):
59 ignore_reply
= keywords
['ignore_reply']
62 if not(reply_handler
and error_handler
):
64 raise MissingErrorHandlerException()
66 raise MissingReplyHandlerException()
68 dbus_interface
= self
._dbus
_interface
69 if keywords
.has_key('dbus_interface'):
70 dbus_interface
= keywords
['dbus_interface']
74 tmp_iface
= dbus_interface
+ '.'
76 key
= tmp_iface
+ self
._method
_name
79 if self
._proxy
._introspect
_method
_map
.has_key (key
):
80 introspect_sig
= self
._proxy
._introspect
_method
_map
[key
]
82 message
= _dbus_bindings
.MethodCall(self
._object
_path
, dbus_interface
, self
._method
_name
)
83 message
.set_destination(self
._named
_service
)
85 # Add the arguments to the function
86 iter = message
.get_iter(True)
89 for (arg
, sig
) in zip(args
, _dbus_bindings
.Signature(introspect_sig
)):
90 iter.append_strict(arg
, sig
)
96 result
= self
._connection
.send(message
)
97 args_tuple
= (result
,)
99 result
= self
._connection
.send_with_reply_handlers(message
, timeout
, reply_handler
, error_handler
)
102 reply_message
= self
._connection
.send_with_reply_and_block(message
, timeout
)
103 args_tuple
= reply_message
.get_args_list()
105 if len(args_tuple
) == 0:
107 elif len(args_tuple
) == 1:
114 """A proxy to the remote Object.
116 A ProxyObject is provided by the Bus. ProxyObjects
117 have member functions, and can be called like normal Python objects.
119 ProxyMethodClass
= ProxyMethod
120 DeferedMethodClass
= DeferedMethod
122 INTROSPECT_STATE_DONT_INTROSPECT
= 0
123 INTROSPECT_STATE_INTROSPECT_IN_PROGRESS
= 1
124 INTROSPECT_STATE_INTROSPECT_DONE
= 2
126 def __init__(self
, bus
, named_service
, object_path
, introspect
=True):
128 self
._named
_service
= named_service
129 self
._object
_path
= object_path
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
= {}
139 self
._introspect
_state
= self
.INTROSPECT_STATE_DONT_INTROSPECT
141 self
._introspect
_state
= self
.INTROSPECT_STATE_INTROSPECT_IN_PROGRESS
143 (result
, self
._pending
_introspect
) = self
._Introspect
()
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
,
154 def _Introspect(self
):
155 message
= _dbus_bindings
.MethodCall(self
._object
_path
, 'org.freedesktop.DBus.Introspectable', 'Introspect')
156 message
.set_destination(self
._named
_service
)
158 result
= self
._bus
.get_connection().send_with_reply_handlers(message
, -1,
159 self
._introspect
_reply
_handler
,
160 self
._introspect
_error
_handler
)
163 def _introspect_execute_queue(self
):
164 for call
in self
._pending
_introspect
_queue
:
165 (member
, iface
, args
, keywords
) = call
167 introspect_sig
= None
171 tmp_iface
= iface
+ '.'
173 key
= tmp_iface
+ '.' + member
174 if self
._introspect
_method
_map
.has_key (key
):
175 introspect_sig
= self
._introspect
_method
_map
[key
]
178 call_object
= self
.ProxyMethodClass(self
._bus
.get_connection(),
185 call_object(args
, keywords
)
187 def _introspect_reply_handler(self
, data
):
189 self
._introspect
_method
_map
= introspect_parser
.process_introspection_data(data
)
190 except IntrospectionParserException
, e
:
191 self
._introspect
_error
_handler
(e
)
194 self
._introspect
_state
= self
.INTROSPECT_STATE_INTROSPECT_DONE
195 #self._introspect_execute_queue()
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")
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
)
208 ret
= self
.ProxyMethodClass(self
, self
._bus
.get_connection(),
210 self
._object
_path
, member
,
213 if self
._introspect
_state
== self
.INTROSPECT_STATE_INTROSPECT_IN_PROGRESS
:
214 ret
= self
.DeferedMethodClass(ret
)
219 return '<ProxyObject wrapping %s %s %s at %#x>'%(
220 self
._bus
, self
._named
_service
, self
._object
_path
, id(self
))