-
Notifications
You must be signed in to change notification settings - Fork 27
Open
Description
In the Python version, when called using complex Python object with __str__ method the rpc fails as the object converted to its string representation.
The fix is relatively simple:
- Modify the FunctionCall object:
1.1. Change the__init__function
1.2. Created a function callcallthat first get the function attrbutenameof the object and then pass theargsandkwargs
class FunctionCall(dict):
"""Encapsulates a function call as a Python dictionary."""
@staticmethod
def from_dict(dictionary):
"""Return a new FunctionCall from a Python dictionary."""
name = dictionary.get('name')
args = dictionary.get('args')
kwargs = dictionary.get('kwargs')
return FunctionCall(name, args, kwargs)
def __init__(self, name, args=None, kwargs=None):
"""Create a new FunctionCall from a method name, an optional argument tuple, and an optional keyword argument
dictionary."""
self['name'] = name
if not args:
self['args'] = []
else:
self['args'] = args
if not kwargs:
self['kwargs'] = [{}]
else:
self['kwargs'] = kwargs
def call(self, local_object):
func = getattr(local_object, self['name'])
return func(*self['args'], **self['kwargs'])
def as_python_code(self):
"""Return a string representation of this object that can be evaled to execute the function call."""
argstring = '' if 'args' not in self else \
','.join(str(arg) for arg in self['args'])
kwargstring = '' if 'kwargs' not in self else \
','.join('%s=%s' % (key,val) for (key,val) in list(self['kwargs'].items()))
if len(argstring) == 0:
params = kwargstring
elif len(kwargstring) == 0:
params = argstring
else:
params = ','.join([argstring,kwargstring])
return '%s(%s)' % (self['name'], params)
- The Server class also needs to be modified to replace the
execstatement withfunction_call.call(self.local_object)
class Server(object):
"""Executes function calls received from a Redis queue."""
def __init__(self, redis_server, message_queue, local_object):
self.redis_server = redis_server
self.message_queue = message_queue
self.local_object = local_object
def run(self):
# Flush the message queue.
self.redis_server.delete(self.message_queue)
while True:
message_queue, message = self.redis_server.blpop(self.message_queue)
message_queue = message_queue.decode()
assert message_queue == self.message_queue
logging.debug('RPC Request: %s' % message)
transport, rpc_request = decode_message(message)
response_queue = rpc_request['response_queue']
function_call = FunctionCall.from_dict(rpc_request['function_call'])
self.value = function_call.call(self.local_object)
rpc_response = dict(return_value=self.value)
message = transport.dumps(rpc_response)
logging.debug('RPC Response: %s' % message)
self.redis_server.rpush(response_queue, message)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels