78 lines
2.6 KiB
Python
Executable File
78 lines
2.6 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
from __future__ import print_function
|
|
import argparse
|
|
import socket
|
|
import capnp
|
|
|
|
import calculator_capnp
|
|
import rpc_capnp
|
|
|
|
class PowerFunction(calculator_capnp.Calculator.Function.Server):
|
|
'''An implementation of the Function interface wrapping pow(). Note that
|
|
we're implementing this on the client side and will pass a reference to
|
|
the server. The server will then be able to make calls back to the client.'''
|
|
|
|
def call(self, params):
|
|
return pow(params[0], params[1])
|
|
|
|
def parse_args():
|
|
parser = argparse.ArgumentParser('Connects to the Calculator server at the given address and does some RPCs')
|
|
parser.add_argument("host", help="HOST:PORT")
|
|
|
|
return parser.parse_args()
|
|
|
|
def main():
|
|
host, port = parse_args().host.split(':')
|
|
|
|
sock = socket.create_connection((host, port))
|
|
client = capnp.RpcClient(sock)
|
|
|
|
ref = rpc_capnp.SturdyRef.new_message()
|
|
ref.objectId.set_as_text('calculator')
|
|
calculator = client.restore(ref.objectId).cast_as(calculator_capnp.Calculator)
|
|
|
|
'''Make a request that just evaluates the literal value 123.
|
|
|
|
What's interesting here is that evaluate() returns a "Value", which is
|
|
another interface and therefore points back to an object living on the
|
|
server. We then have to call read() on that object to read it.
|
|
However, even though we are making two RPC's, this block executes in
|
|
*one* network round trip because of promise pipelining: we do not wait
|
|
for the first call to complete before we send the second call to the
|
|
server.'''
|
|
|
|
print('Evaluating a literal... ', end="")
|
|
|
|
request = calculator.evaluate_request()
|
|
request.expression.literal = 123
|
|
|
|
eval_promise = request.send()
|
|
read_promise = eval_promise.value.read()
|
|
response = read_promise.wait()
|
|
assert response.value == 123
|
|
|
|
print("PASS")
|
|
|
|
'''Make a request to evaluate 123 + 45 - 67.
|
|
# //
|
|
The Calculator interface requires that we first call getOperator() to
|
|
get the addition and subtraction functions, then call evaluate() to use
|
|
them. But, once again, we can get both functions, call evaluate(), and
|
|
then read() the result -- four RPCs -- in the time of *one* network
|
|
round trip, because of promise pipelining.'''
|
|
|
|
print("Using add and subtract... ", end='')
|
|
add = calculator.getOperator(op='add').func
|
|
subtract = calculator.getOperator(op='subtract').func
|
|
|
|
request = calculator.evaluate_request()
|
|
subtract_call = request.expression.init('call')
|
|
subtract_call.function = subtract
|
|
params = subtract_call.init('params', 2)
|
|
params[1] = 67.0
|
|
|
|
if __name__ == '__main__':
|
|
main()
|
|
|