Fix examples formatting issues and make them pep8 compliant

This commit is contained in:
Jason Paryani
2013-12-11 01:59:52 -08:00
parent 5811213321
commit 03bac73120
2 changed files with 122 additions and 91 deletions

View File

@@ -7,25 +7,38 @@ import capnp
import calculator_capnp import calculator_capnp
class PowerFunction(calculator_capnp.Calculator.Function.Server): class PowerFunction(calculator_capnp.Calculator.Function.Server):
'''An implementation of the Function interface wrapping pow(). Note that '''An implementation of the Function interface wrapping pow(). Note that
we're implementing this on the client side and will pass a reference to 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.''' the server. The server will then be able to make calls back to the client.'''
def call(self, params, **kwargs): def call(self, params, **kwargs):
'''Note the **kwargs. This is very necessary to include, since protocols can add parameters over time. Also, by default, a _context variable is passed to all server methods. Read the docs for further explanation.''' '''Note the **kwargs. This is very necessary to include, since
protocols can add parameters over time. Also, by default, a _context
variable is passed to all server methods, but you can also return
results directly as python objects, and they'll be added to the
results struct in the correct order'''
return pow(params[0], params[1]) return pow(params[0], params[1])
def parse_args(): def parse_args():
parser = argparse.ArgumentParser(usage='Connects to the Calculator server at the given address and does some RPCs') parser = argparse.ArgumentParser(usage='Connects to the Calculator server \
at the given address and does some RPCs')
parser.add_argument("host", help="HOST:PORT") parser.add_argument("host", help="HOST:PORT")
return parser.parse_args() return parser.parse_args()
def main(sock): def main(sock):
client = capnp.TwoPartyClient(sock) client = capnp.TwoPartyClient(sock)
# Pass "calculator" to ez_restore (there's also a `restore` function that takes a struct or AnyPointer as an argument), and then cast the returned capability to it's proper type. This casting is due to capabilities not having a reference to their schema # Pass "calculator" to ez_restore (there's also a `restore` function that
# takes a struct or AnyPointer as an argument), and then cast the returned
# capability to it's proper type. This casting is due to capabilities not
# having a reference to their schema
calculator = client.ez_restore('calculator').cast_as(calculator_capnp.Calculator) calculator = client.ez_restore('calculator').cast_as(calculator_capnp.Calculator)
'''Make a request that just evaluates the literal value 123. '''Make a request that just evaluates the literal value 123.
@@ -40,14 +53,17 @@ def main(sock):
print('Evaluating a literal... ', end="") print('Evaluating a literal... ', end="")
# Set up the request. Note the form is 'evaluate' + '_request', where 'evaluate' is the name of the method we want to call # Set up the request. Note the form is 'evaluate' + '_request', where
# 'evaluate' is the name of the method we want to call
request = calculator.evaluate_request() request = calculator.evaluate_request()
request.expression.literal = 123 request.expression.literal = 123
# Send it, which returns a promise for the result (without blocking). # Send it, which returns a promise for the result (without blocking).
eval_promise = request.send() eval_promise = request.send()
# Using the promise, create a pipelined request to call read() on the returned object. Note that here we are using the shortened method call syntax read(), which is mostly just sugar for read_request().send() # Using the promise, create a pipelined request to call read() on the
# returned object. Note that here we are using the shortened method call
# syntax read(), which is mostly just sugar for read_request().send()
read_promise = eval_promise.value.read() read_promise = eval_promise.value.read()
# Now that we've sent all the requests, wait for the response. Until this # Now that we've sent all the requests, wait for the response. Until this
@@ -94,7 +110,6 @@ def main(sock):
print("PASS") print("PASS")
'''Make a request to evaluate 4 * 6, then use the result in two more '''Make a request to evaluate 4 * 6, then use the result in two more
requests that add 3 and 5. requests that add 3 and 5.
@@ -110,13 +125,12 @@ def main(sock):
# Get the "multiply" function from the server. # Get the "multiply" function from the server.
multiply = calculator.getOperator(op='multiply').func multiply = calculator.getOperator(op='multiply').func
# Build the request to evaluate 4 * 6 # Build the request to evaluate 4 * 6
request = calculator.evaluate_request() request = calculator.evaluate_request()
multiply_call = request.expression.init("call") multiply_call = request.expression.init("call")
multiply_call.function = multiply multiply_call.function = multiply
multiply_params = multiply_call.init("params", 2); multiply_params = multiply_call.init("params", 2)
multiply_params[0].literal = 4 multiply_params[0].literal = 4
multiply_params[1].literal = 6 multiply_params[1].literal = 6
@@ -124,25 +138,25 @@ def main(sock):
# Use the result in two calls that add 3 and add 5. # Use the result in two calls that add 3 and add 5.
add3Request = calculator.evaluate_request() add_3_request = calculator.evaluate_request()
add3Call = add3Request.expression.init("call") add_3_call = add_3_request.expression.init("call")
add3Call.function = add add_3_call.function = add
add3Params = add3Call.init("params", 2) add_3_params = add_3_call.init("params", 2)
add3Params[0].previousResult = multiply_result add_3_params[0].previousResult = multiply_result
add3Params[1].literal = 3 add_3_params[1].literal = 3
add3Promise = add3Request.send().value.read() add_3_promise = add_3_request.send().value.read()
add5Request = calculator.evaluate_request() add_5_request = calculator.evaluate_request()
add5Call = add5Request.expression.init("call") add_5_call = add_5_request.expression.init("call")
add5Call.function = add add_5_call.function = add
add5Params = add5Call.init("params", 2) add_5_params = add_5_call.init("params", 2)
add5Params[0].previousResult = multiply_result add_5_params[0].previousResult = multiply_result
add5Params[1].literal = 5 add_5_params[1].literal = 5
add5Promise = add5Request.send().value.read() add_5_promise = add_5_request.send().value.read()
# Now wait for the results. # Now wait for the results.
assert add3Promise.wait().value == 27 assert add_3_promise.wait().value == 27
assert add5Promise.wait().value == 29 assert add_5_promise.wait().value == 29
print("PASS") print("PASS")
@@ -168,16 +182,16 @@ def main(sock):
request.paramCount = 2 request.paramCount = 2
# Build the function body. # Build the function body.
addCall = request.body.init("call") add_call = request.body.init("call")
addCall.function = add add_call.function = add
addParams = addCall.init("params", 2) add_params = add_call.init("params", 2)
addParams[1].parameter = 1 # y add_params[1].parameter = 1 # y
multiplyCall = addParams[0].init("call") multiply_call = add_params[0].init("call")
multiplyCall.function = multiply multiply_call.function = multiply
multiplyParams = multiplyCall.init("params", 2) multiply_params = multiply_call.init("params", 2)
multiplyParams[0].parameter = 0 # x multiply_params[0].parameter = 0 # x
multiplyParams[1].literal = 100 multiply_params[1].literal = 100
f = request.send().func f = request.send().func
@@ -186,45 +200,45 @@ def main(sock):
request.paramCount = 1 request.paramCount = 1
# Build the function body. # Build the function body.
multiplyCall = request.body.init("call") multiply_call = request.body.init("call")
multiplyCall.function = multiply multiply_call.function = multiply
multiplyParams = multiplyCall.init("params", 2) multiply_params = multiply_call.init("params", 2)
multiplyParams[1].literal = 2 multiply_params[1].literal = 2
fCall = multiplyParams[0].init("call") f_call = multiply_params[0].init("call")
fCall.function = f f_call.function = f
fParams = fCall.init("params", 2) f_params = f_call.init("params", 2)
fParams[0].parameter = 0 f_params[0].parameter = 0
addCall = fParams[1].init("call") add_call = f_params[1].init("call")
addCall.function = add add_call.function = add
addParams = addCall.init("params", 2) add_params = add_call.init("params", 2)
addParams[0].parameter = 0 add_params[0].parameter = 0
addParams[1].literal = 1 add_params[1].literal = 1
g = request.send().func g = request.send().func
# OK, we've defined all our functions. Now create our eval requests. # OK, we've defined all our functions. Now create our eval requests.
# f(12, 34) # f(12, 34)
fEvalRequest = calculator.evaluate_request() f_eval_request = calculator.evaluate_request()
fCall = fEvalRequest.expression.init("call") f_call = f_eval_request.expression.init("call")
fCall.function = f f_call.function = f
fParams = fCall.init("params", 2) f_params = f_call.init("params", 2)
fParams[0].literal = 12 f_params[0].literal = 12
fParams[1].literal = 34 f_params[1].literal = 34
fEvalPromise = fEvalRequest.send().value.read() f_eval_promise = f_eval_request.send().value.read()
# g(21) # g(21)
gEvalRequest = calculator.evaluate_request() g_eval_request = calculator.evaluate_request()
gCall = gEvalRequest.expression.init("call") g_call = g_eval_request.expression.init("call")
gCall.function = g g_call.function = g
gCall.init('params', 1)[0].literal = 21 g_call.init('params', 1)[0].literal = 21
gEvalPromise = gEvalRequest.send().value.read() g_eval_promise = g_eval_request.send().value.read()
# Wait for the results. # Wait for the results.
assert fEvalPromise.wait().value == 1234 assert f_eval_promise.wait().value == 1234
assert gEvalPromise.wait().value == 4244 assert g_eval_promise.wait().value == 4244
print("PASS") print("PASS")
@@ -250,16 +264,16 @@ def main(sock):
# Build the eval request for 2^(4+5). # Build the eval request for 2^(4+5).
request = calculator.evaluate_request() request = calculator.evaluate_request()
powCall = request.expression.init("call") pow_call = request.expression.init("call")
powCall.function = PowerFunction() pow_call.function = PowerFunction()
powParams = powCall.init("params", 2) pow_params = pow_call.init("params", 2)
powParams[0].literal = 2 pow_params[0].literal = 2
addCall = powParams[1].init("call") add_call = pow_params[1].init("call")
addCall.function = add add_call.function = add
addParams = addCall.init("params", 2) add_params = add_call.init("params", 2)
addParams[0].literal = 4 add_params[0].literal = 4
addParams[1].literal = 5 add_params[1].literal = 5
# Send the request and wait. # Send the request and wait.
response = request.send().value.read().wait() response = request.send().value.read().wait()

View File

@@ -8,6 +8,7 @@ import capnp
import calculator_capnp import calculator_capnp
def readValue(value): def readValue(value):
'''Helper function to asynchronously call read() on a Calculator::Value and '''Helper function to asynchronously call read() on a Calculator::Value and
return a promise for the result. (In the future, the generated code might return a promise for the result. (In the future, the generated code might
@@ -15,6 +16,7 @@ def readValue(value):
return value.read().then(lambda result: result.value) return value.read().then(lambda result: result.value)
def evaluateImpl(expression, params=None): def evaluateImpl(expression, params=None):
'''Implementation of CalculatorImpl::evaluate(), also shared by '''Implementation of CalculatorImpl::evaluate(), also shared by
FunctionImpl::call(). In the latter case, `params` are the parameter FunctionImpl::call(). In the latter case, `params` are the parameter
@@ -22,17 +24,15 @@ def evaluateImpl(expression, params=None):
empty list.''' empty list.'''
which = expression.which() which = expression.which()
if which == 'literal': if which == 'literal':
return capnp.Promise(expression.literal) return capnp.Promise(expression.literal)
elif which == 'previousResult': elif which == 'previousResult':
return readValue(expression.previousResult) return readValue(expression.previousResult)
elif which == 'parameter': elif which == 'parameter':
assert expression.parameter < len(params) assert expression.parameter < len(params)
return capnp.Promise(params[expression.parameter]) return capnp.Promise(params[expression.parameter])
elif which == 'call': elif which == 'call':
def then(vals):
ret = func.call(vals).then(lambda result: result.value)
return ret
call = expression.call call = expression.call
func = call.function func = call.function
@@ -41,14 +41,15 @@ def evaluateImpl(expression, params=None):
joinedParams = capnp.join_promises(paramPromises) joinedParams = capnp.join_promises(paramPromises)
# When the parameters are complete, call the function. # When the parameters are complete, call the function.
ret = joinedParams.then(then) ret = joinedParams.then(lambda vals: func.call(vals).then(lambda result: result.value))
return ret return ret
else: else:
raise ValueError("Unknown expression type: " + which) raise ValueError("Unknown expression type: " + which)
class ValueImpl(calculator_capnp.Calculator.Value.Server): class ValueImpl(calculator_capnp.Calculator.Value.Server):
"Simple implementation of the Calculator.Value Cap'n Proto interface." "Simple implementation of the Calculator.Value Cap'n Proto interface."
def __init__(self, value): def __init__(self, value):
@@ -57,21 +58,29 @@ class ValueImpl(calculator_capnp.Calculator.Value.Server):
def read(self, **kwargs): def read(self, **kwargs):
return self.value return self.value
class FunctionImpl(calculator_capnp.Calculator.Function.Server): class FunctionImpl(calculator_capnp.Calculator.Function.Server):
'''Implementation of the Calculator.Function Cap'n Proto interface, where the '''Implementation of the Calculator.Function Cap'n Proto interface, where the
function is defined by a Calculator.Expression.''' function is defined by a Calculator.Expression.'''
def __init__(self, paramCount, body, obj): def __init__(self, paramCount, body):
self.paramCount = paramCount self.paramCount = paramCount
self.body = body.as_builder() self.body = body.as_builder()
self.obj = obj
def call(self, params, _context, **kwargs): def call(self, params, _context, **kwargs):
'''Note that we're returning a Promise object here, and bypassing the
helper functionality that normally sets the results struct from the
returned object. Instead, we set _context.results directly inside of
another promise'''
assert len(params) == self.paramCount assert len(params) == self.paramCount
return evaluateImpl(self.body, params).then(lambda value: setattr(_context.results, 'value', value)) # using setattr because '=' is not allowed inside of lambdas # using setattr because '=' is not allowed inside of lambdas
return evaluateImpl(self.body, params).then(lambda value: setattr(_context.results, 'value', value))
class OperatorImpl(calculator_capnp.Calculator.Function.Server): class OperatorImpl(calculator_capnp.Calculator.Function.Server):
'''Implementation of the Calculator.Function Cap'n Proto interface, wrapping '''Implementation of the Calculator.Function Cap'n Proto interface, wrapping
basic binary arithmetic operators.''' basic binary arithmetic operators.'''
@@ -82,6 +91,7 @@ class OperatorImpl(calculator_capnp.Calculator.Function.Server):
assert len(params) == 2 assert len(params) == 2
op = self.op op = self.op
if op == 'add': if op == 'add':
return params[0] + params[1] return params[0] + params[1]
elif op == 'subtract': elif op == 'subtract':
@@ -93,23 +103,25 @@ class OperatorImpl(calculator_capnp.Calculator.Function.Server):
else: else:
raise ValueError('Unknown operator') raise ValueError('Unknown operator')
class CalculatorImpl(calculator_capnp.Calculator.Server): class CalculatorImpl(calculator_capnp.Calculator.Server):
"Implementation of the Calculator Cap'n Proto interface." "Implementation of the Calculator Cap'n Proto interface."
def evaluate(self, expression, _context, **kwargs): def evaluate(self, expression, _context, **kwargs):
return evaluateImpl(expression).then(lambda value: setattr(_context.results, 'value', ValueImpl(value))) return evaluateImpl(expression).then(lambda value: setattr(_context.results, 'value', ValueImpl(value)))
def defFunction(self, paramCount, body, _context, **kwargs): def defFunction(self, paramCount, body, _context, **kwargs):
return FunctionImpl(paramCount, body, _context) return FunctionImpl(paramCount, body)
def getOperator(self, op, **kwargs): def getOperator(self, op, **kwargs):
return OperatorImpl(op) return OperatorImpl(op)
def parse_args(): def parse_args():
parser = argparse.ArgumentParser(usage='''Runs the server bound to the given address/port parser = argparse.ArgumentParser(usage='''Runs the server bound to the\
ADDRESS may be '*' to bind to all local addresses. given address/port ADDRESS may be '*' to bind to all local addresses.\
:PORT may be omitted to choose a port automatically. :PORT may be omitted to choose a port automatically. ''')
''')
parser.add_argument("address", help="ADDRESS[:PORT]") parser.add_argument("address", help="ADDRESS[:PORT]")
@@ -117,6 +129,10 @@ ADDRESS may be '*' to bind to all local addresses.
class CalcRestorer: class CalcRestorer:
'''A RPC Restorer. This requires a `restore` function to be defined, and
will be passed in a SturdyRef by your client'''
def __init__(self): def __init__(self):
self.calc = CalculatorImpl() self.calc = CalculatorImpl()
@@ -124,6 +140,7 @@ class CalcRestorer:
assert ref.as_text() == 'calculator' assert ref.as_text() == 'calculator'
return CalculatorImpl() return CalculatorImpl()
def main(): def main():
address = parse_args().address address = parse_args().address
@@ -131,16 +148,16 @@ def main():
address, port = address.split(':') address, port = address.split(':')
port = int(port) port = int(port)
else: else:
port = random.randint(60000,61000) port = random.randint(60000, 61000)
if address == '*': if address == '*':
address = '' address = ''
print("Listening on port: {}".format(port)) print("Listening on port: {}".format(port))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((address,port)) s.bind((address, port))
s.listen(1) # service only 1 client at a time s.listen(1) # service only 1 client at a time
while True: while True:
try: try: