diff options
Diffstat (limited to 'sugargame/dbusproxy.py')
-rw-r--r-- | sugargame/dbusproxy.py | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/sugargame/dbusproxy.py b/sugargame/dbusproxy.py new file mode 100644 index 0000000..d210114 --- /dev/null +++ b/sugargame/dbusproxy.py @@ -0,0 +1,100 @@ +"""Spike test for a safer networking system for DBUS-based objects""" + +from sugargame import util +from dbus import proxies + + +def wrap(value, tube=None, path=None): + """Wrap object with any required pygame-side proxies""" + if isinstance(value, proxies._ProxyMethod): + return DBUSMethod(value, tube=tube, path=path) + elif isinstance(value, proxies._DeferredMethod): + value._proxy_method = DBUSMethod(value._proxy_method, tube=tube, + path=path) + return value + elif isinstance(value, proxies.ProxyObject): + return DBUSProxy(value, tube=tube, path=path) + else: + return value + + +class DBUSProxy(object): + """Proxy for the DBUS Proxy object""" + def __init__(self, proxy, tube=None, path=None): + self.__proxy = proxy + self.__tube = tube + self.__path = path + + def __getattr__(self, key): + """Retrieve attribute of given key""" + return wrap(getattr(self.__proxy, key)) + + def add_signal_receiver(self, callback, eventName, interface, path=None, + sender_keyword='sender'): + """ + Add a new signal handler (which will be called many times) + for given signal + """ + self.__tube.add_signal_receiver( + Callback(callback), + eventName, + interface, + path=path or self.__path, + sender_keyword=sender_keyword, + ) + + +class DBUSMethod(object): + """DBUS method which does callbacks in the Pygame (eventwrapper) thread""" + def __init__(self, proxy, tube, path): + self.__proxy = proxy + self.__tube = tube + self.__path = path + + def __call__(self, *args, **named): + """Perform the asynchronous call""" + callback, errback = named.get('reply_handler'), \ + named.get('error_handler') + if not callback: + raise TypeError("""Require a reply_handler named argument to do + any asynchronous call""") + else: + callback = Callback(callback) + if not errback: + errback = defaultErrback + else: + errback = Callback(errback) + named['reply_handler'] = callback + named['error_handler'] = errback + return self.__proxy(*args, **named) + + +def defaultErrback(error): + """Log the error to stderr/log""" + pass + + +class Callback(object): + """ + PyGTK-side callback which generates a CallbackResult to process on the + Pygame side + """ + def __init__(self, callable, callContext=None): + """Initialize the callback to process results""" + self.callable = callable + if callContext is None: + callContext = util.get_traceback(None) + self.callContext = callContext + + def __call__(self, *args, **named): + """PyGTK-side callback operation""" + from olpcgames import eventwrap + args = [wrap(a) for a in args] + named = dict([ + (k, wrap(v)) for k, v in named.items() + ]) + eventwrap.post( + eventwrap.CallbackResult( + self.callable, args, named, callContext=self.callContext + ) + ) |