1 """This module allows a caller to invoke methods on another process.
2 It is really part of the proxy module, but separate because it imports some GTK
3 functions which a slave must not do.
8 from __future__
import generators
9 from proxy
import Proxy
10 import tasks
# (imports rox, and thus gtk)
12 class MasterObject(object):
13 """Invoking a method on a MasterObject invokes the corresponding
14 method on the slave object. The return value is a ResponseBlocker from
15 which the response can be read."""
18 def __init__(self
, master
):
21 def __getattr__(self
, name
):
24 request
= self
._master
._add
_blocker
(self
._serial
)
25 self
._master
.write_object((self
._serial
, name
, args
))
29 def finish_proxy(self
):
30 """Calls MasterProxy.finish() for our MasterProxy"""
33 class RequestBlocker(tasks
.Blocker
):
34 """The blocker is triggered when the slave object sends a reply
35 to our method call. You can then call get() to get the result, eg:
37 blocker = master.method()
41 If the remote method raised an exception, accessing 'isresult' will raise
42 it rather than returning it.
46 if self
.error
is not None:
48 raise Exception('No result yet! Yield this blocker first.')
53 result
= property(_error
)
55 def __init__(self
, master
, serial
):
56 tasks
.Blocker
.__init
__(self
)
61 """Store the result and trigger our blocker."""
62 assert not self
.happened
63 self
.master
._remove
_blocker
(self
.serial
)
64 if isinstance(data
, Exception):
70 class LostConnection(Exception):
73 class MasterProxy(Proxy
):
74 """Invoking operations on MasterProxy.root will invoke the same
75 operation on the SlaveProxy's slave_object."""
77 def __init__(self
, to_slave
, from_slave
):
78 Proxy
.__init
__(self
, to_slave
, from_slave
)
79 self
.root
= MasterObject(self
)
80 self
._queue
= {} # Serial -> RequestBlocker
82 def _dispatch(self
, value
):
84 self
._queue
[serial
].add(data
)
86 def _add_blocker(self
, serial
):
87 assert serial
not in self
._queue
88 request
= RequestBlocker(self
, serial
)
89 self
._queue
[serial
] = request
92 def _remove_blocker(self
, serial
):
93 del self
._queue
[serial
]
95 def lost_connection(self
):
96 for x
in self
._queue
.values():
97 x
.add(LostConnection('Lost connection to su proxy'))
98 assert not self
._queue