summaryrefslogtreecommitdiffstats
path: root/python/proxies.py
diff options
context:
space:
mode:
authorJohn (J5) Palmieri <johnp@redhat.com>2005-08-16 22:54:04 +0000
committerJohn (J5) Palmieri <johnp@redhat.com>2005-08-16 22:54:04 +0000
commitce84a7761a567f5afaca03d0fb5c0378f293da80 (patch)
tree7f00e7193fb6e6f07df88fa70650174916231820 /python/proxies.py
parent9746c7a97871508c7298a8cad88dc7daff1c2bb3 (diff)
* 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
Diffstat (limited to 'python/proxies.py')
-rw-r--r--python/proxies.py97
1 files changed, 86 insertions, 11 deletions
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 '<ProxyObject wrapping %s %s %s at %x>'%(