Skip to content
callers.py 1.7 KiB
Newer Older
Antoine Millet's avatar
Antoine Millet committed
#!/usr/bin/env python
#coding:utf8

import threading

class RpcCaller(object):
    '''
    A caller execute a callable (function, method, class which implement the
    :meth:`__call__` method...) in a particular context (threaded or 
    "timeouted" for example), and return the result (or the exception) to the 
    peer through it :class:`RpcConnection` object.
    '''
    
    def __init__(self, request, connection, func):
        self._request = request
        self._connection = connection
        self._func = func

    def run(self):
        '''
        Run the callable and return the result (or the exception) to the peer.
        '''
        
        msg_id = self._request['id']
        args = self._request['args']
        kwargs = self._request['kwargs']
        
        if not getattr(self._func, '__pure__', False):
            args.insert(0, self._connection)

        try:
            returned = self._func(*args, **kwargs)
        except Exception as err:
            self._connection.error(msg_id, message=str(err),
                                   error=err.__class__.__name__)
        else:
            self._connection.response(msg_id, returned=returned)
    
    def start(self):
        '''
        Start execution of the callable, the most of time, it just call 
        :meth:`run` method.
        '''
        
        self.run()


class ThreadedRpcCaller(RpcCaller):
    
    '''
    A caller which make the call into a separated thread.
    '''
    
    def __init__(self, *args, **kwargs):
        super(ThreadedRpcCaller, self).__init__(*args, **kwargs)
        self._thread = threading.Thread(target=self.run)
        self._thread.daemon = True
    
    def start(self):
        self._thread.start()