From ce84a7761a567f5afaca03d0fb5c0378f293da80 Mon Sep 17 00:00:00 2001 From: "John (J5) Palmieri" Date: Tue, 16 Aug 2005 22:54:04 +0000 Subject: * python/__init__.py: Version updated (0, 43, 0) * python/dbus_bindings.pyx: - Fixed type objects to have self passed into __init__ - Added the Variant type - Add the ability to specify types or signatures for Array, Variant and Dictionary - (Connection::send_with_reply_handlers): return a PendingCall object - (_pending_call_notification): handle the case when an error is returned without an error message in the body - (MessageIter::get_boolean): return True or False instead of an integer - (MessageIter::python_value_to_dbus_sig): add direct checking of types and add checks for objects with embeded signatures or types (Array, Variant and Dictionary) - (MessageIter::append_byte): handle case when the value is a dbus.Byte - (MessageIter::append_dict): handle embeded types or signatures - (MessageIter::append_array): handle embeded types or signatures - (MessageIter::append_variant): new method * python/proxies.py: - (DeferedMethod): New. Dummy executable object used when queuing calls blocking on introspection data - (ProxyMethod::__call__): add the timeout keyword for specifying longer or shorter timeouts for method calls - (ProxyObject): Add first pass at an introspection state machine - (ProxyObject::__init__): Add introspect keyword for turing off an on introspection. - (ProxyObject::_Introspect): Internal Introspect call that bypasses the usual mechanisms for sending messages. This is to avoid a deadlock where the Intospect call would be queued waiting for the Introspect call to finish ;-) - (ProxyObject::_introspect_reply_handler): New. This method is called when introspection returns with no error - (ProxyObject::_introspect_error_handler): New. This method is called when introspection encounters an error - (ProxyObject::__getattr__): Code to handle different introspection states. Queue async calls or block blocking calls if we are introspecting. Pass through as normal if we are not or are done with introspecting. * python/service.py: Import signal and method from decorators.py * python/types.py: Add Variant type --- python/proxies.py | 97 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 86 insertions(+), 11 deletions(-) (limited to 'python/proxies.py') diff --git a/python/proxies.py b/python/proxies.py index 95c98a9c..c7dc02be 100644 --- a/python/proxies.py +++ b/python/proxies.py @@ -1,6 +1,17 @@ import dbus_bindings from exceptions import MissingReplyHandlerException, MissingErrorHandlerException +class DeferedMethod: + """A DeferedMethod + + This is returned instead of ProxyMethod when we are defering DBus calls + while waiting for introspection data to be returned + + This class can be used for debugging purposes + """ + def __call__(self, *args, **keywords): + return None + class ProxyMethod: """A proxy Method. @@ -17,15 +28,19 @@ class ProxyMethod: def __call__(self, *args, **keywords): dbus_interface = self._dbus_interface - if (keywords.has_key('dbus_interface')): + if keywords.has_key('dbus_interface'): dbus_interface = keywords['dbus_interface'] + timeout = -1 + if keywords.has_key('timeout'): + timeout = keywords['timeout'] + reply_handler = None - if (keywords.has_key('reply_handler')): + if keywords.has_key('reply_handler'): reply_handler = keywords['reply_handler'] error_handler = None - if (keywords.has_key('error_handler')): + if keywords.has_key('error_handler'): error_handler = keywords['error_handler'] if not(reply_handler and error_handler): @@ -43,10 +58,10 @@ class ProxyMethod: iter.append(arg) if reply_handler: - result = self._connection.send_with_reply_handlers(message, -1, reply_handler, error_handler) - args_tuple = (result,) + result = self._connection.send_with_reply_handlers(message, timeout, reply_handler, error_handler) + args_tuple = result else: - reply_message = self._connection.send_with_reply_and_block(message, -1) + reply_message = self._connection.send_with_reply_and_block(message, timeout) args_tuple = reply_message.get_args_list() if len(args_tuple) == 0: @@ -64,11 +79,31 @@ class ProxyObject: have member functions, and can be called like normal Python objects. """ ProxyMethodClass = ProxyMethod + DeferedMethodClass = DeferedMethod - def __init__(self, bus, named_service, object_path): - self._bus = bus + INTROSPECT_STATE_DONT_INTROSPECT = 0 + INTROSPECT_STATE_INTROSPECT_IN_PROGRESS = 1 + INTROSPECT_STATE_INTROSPECT_DONE = 2 + + #TODO: default introspect to False right now because it is not done yet + # make sure to default to True later + def __init__(self, bus, named_service, object_path, introspect=False): + self._bus = bus self._named_service = named_service - self._object_path = object_path + self._object_path = object_path + + #PendingCall object for Introspect call + self._pending_introspect = None + #queue of async calls waiting on the Introspect to return + self._pending_introspect_queue = [] + + if not introspect: + self._introspect_state = self.INTROSPECT_STATE_DONT_INTROSPECT + else: + self._introspect_state = self.INTROSPECT_STATE_INTROSPECT_IN_PROGRESS + + (result, self._pending_introspect) = self._Introspect() + def connect_to_signal(self, signal_name, handler_function, dbus_interface=None): self._bus.add_signal_receiver(handler_function, @@ -77,7 +112,28 @@ class ProxyObject: named_service=self._named_service, path=self._object_path) + def _Introspect(self): + message = dbus_bindings.MethodCall(self._object_path, 'org.freedesktop.DBus.Introspectable', 'Introspect') + message.set_destination(self._named_service) + + result = self._bus.get_connection().send_with_reply_handlers(message, -1, + self._introspect_reply_handler, + self._introspect_error_handler) + return result + + def _introspect_reply_handler(self, data): + self._introspect_state = self.INTROSPECT_STATE_INTROSPECT_DONE + + for call in self._pending_introspect_queue: + (member, iface, args, keywords) = call + call_object = self.ProxyMethodClass(self._bus.get_connection(), + self._named_service, + self._object_path, iface, member) + + call_object(args, keywords) + def _introspect_error_handler(self, error): + self._introspect_state = self.INTROSPECT_STATE_DONT_INTROSPECT def __getattr__(self, member, **keywords): if member == '__call__': @@ -86,12 +142,31 @@ class ProxyObject: raise AttributeError(member) else: iface = None - if (keywords.has_key('dbus_interface')): + if keywords.has_key('dbus_interface'): iface = keywords['dbus_interface'] - return self.ProxyMethodClass(self._bus.get_connection(), + if self._introspect_state == self.INTROSPECT_STATE_INTROSPECT_IN_PROGRESS: + reply_handler = None + if keywords.has_key('reply_handler'): + reply_handler = keywords['reply_handler'] + + error_handler = None + if keywords.has_key('error_handler'): + error_handler = keywords['error_handler'] + + if not reply_handler: + self._pending_introspect.block() + else: + call = (memeber, iface, args, keywords) + self._pending_introspect_queue.append(call) + + ret = self.DeferedMethodClass() + return ret + + ret = self.ProxyMethodClass(self._bus.get_connection(), self._named_service, self._object_path, iface, member) + return ret def __repr__(self): return ''%( -- cgit