Loading sjrpc/__init__.py +1 −5 Original line number Diff line number Diff line #!/usr/bin/env python #coding:utf8 ''' Loading @@ -11,14 +9,12 @@ The library is separated into four parts: * core library contains all common classes. * server library contains all the server side related stuff. * client library contains all the client side related stuff. * utils library contains some helpers used in previous libraries. ''' import sjrpc.core import sjrpc.server import sjrpc.client import sjrpc.utils __version__ = 13 __version__ = '14~dev' sjrpc/client/__init__.pydeleted 100644 → 0 +0 −6 Original line number Diff line number Diff line #!/usr/bin/env python #coding:utf8 from sjrpc.client.simple import SimpleRpcClient __all__ = ('SimpleRpcClient',) sjrpc/client/simple.pydeleted 100644 → 0 +0 −109 Original line number Diff line number Diff line #!/usr/bin/env python #coding=utf8 import select import socket import logging from sjrpc.core import RpcConnection, ConnectionManager class SimpleRpcClient(ConnectionManager): ''' Create a new simple RPC client. :param connect: the :class:`RpcConnection` object to bind the client manager :param default_handler: the default handler to bind to the client connection :param on_disconnect: method on the handler to call when the client disconnects. ''' def __init__(self, connection, default_handler=None, on_disconnect=None): super(SimpleRpcClient, self).__init__() self._on_disconnect = on_disconnect self._connection = connection self._connection.set_handler(default_handler) self.register(self._connection.get_fd(), self._handle_event) @classmethod def from_addr(cls, addr, port, enable_ssl=False, cert=None, timeout=None, conn_timeout=30.0, default_handler=None, on_disconnect=None): ''' Construct the instance of :class:`SimpleRpcClient` without providing the :class:`RpcConnection` object. The :class:`RpcConnection` is automatically created and passed to the standard constructor before to return the new instance. :param addr: the target ip address :param port: the target port :param ssl: enable SSL :param timeout: the global call timeout setting :param conn_timeout: the connection operation timeout :param cert: is SSL is enabled, profile the filename of certificate to check. If None, don't check certificate. :param default_handler: the default handler to bind to the client connection :param on_disconnect: method on the handler to call when the client disconnects. ''' connection = RpcConnection.from_addr(addr, port, None, timeout=timeout, conn_timeout=conn_timeout, enable_ssl=enable_ssl, cert=cert) client = cls(connection, default_handler=default_handler, on_disconnect=on_disconnect) connection._manager = client return client @classmethod def from_sock(cls, sock, default_handler=None, on_disconnect=None): ''' Construct the instance of :class:`SimpleRpcClient` without providing the :class:`RpcConnection` object. The :class:`RpcConnection` is automatically created and passed to the standard constructor before to return the new instance :param sock: the socket object to wrap with :class:`RpcConnection` object. :param default_handler: the default handler to bind to the client connection :param on_disconnect: method on the handler to call when the client disconnects. ''' connection = RpcConnection(sock, None) client = cls(connection, default_handler, on_disconnect) connection._manager = client return client def shutdown(self): super(SimpleRpcClient, self).shutdown() self._connection.shutdown(self._on_disconnect) def _handle_event(self, fd, events): if events & select.EPOLLIN: # Data are ready to be readed on socket try: self._connection.receive() except socket.error as err: logging.debug('Socket error while receiving from the client ' 'fd/%s: %s', fd, err) self.shutdown() if events & select.EPOLLOUT: # Data are ready to be written on socket try: self._connection.send() except socket.error as err: logging.debug('Socket error while sending to the client ' 'fd/%s: %s', fd, err) self.shutdown() if events & select.EPOLLHUP: logging.debug('Socket HUP fd/%s', fd) self.shutdown() def all_connections(self): return set((self._connection,)) def call(self, *args, **kwargs): return self._connection.call(*args, **kwargs) sjrpc/core/__init__.py +3 −4 Original line number Diff line number Diff line Loading @@ -2,10 +2,9 @@ #coding:utf8 from sjrpc.core.rpcconnection import * from sjrpc.core.connectionmanagers import * from sjrpc.core.callers import * from sjrpc.core.exceptions import * from sjrpc.core.async import * __all__ = ('ConnectionManager', 'RpcConnection', 'RpcCaller', 'RpcError', 'ThreadedRpcCaller', ) __all__ = ('RpcConnection', 'RpcCaller', 'ThreadedRpcCaller', 'RpcError', 'AsyncWatcher') sjrpc/core/callers.py +36 −21 Original line number Diff line number Diff line #!/usr/bin/env python #coding:utf8 import threading from sjrpc.core.exceptions import RpcError ERRMSG_RPCERR = ('Unable to send reply to the peer: %s (this error is usualy ' 'raised when connection is lost while handler function ' 'execution)') class RpcCaller(object): ''' A caller execute a callable (function, method, class which implement the Loading @@ -11,37 +15,47 @@ class RpcCaller(object): peer through it :class:`RpcConnection` object. ''' def __init__(self, request, connection, func): def __init__(self, request, protocol, func): self._request = request self._connection = connection self._protocol = protocol self._func = func # Apply the request decorator #request_decorator = connection.request_decorator #if request_decorator is not None: # self._func = request_decorator(self._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) if getattr(self._func, '__pass_rpc__', False): args.insert(0, self._protocol) if getattr(self._func, '__pass_connection__', False): args.insert(0, self._protocol.connection) try: returned = self._func(*args, **kwargs) except Exception as err: self._connection.error(msg_id, message=str(err), try: self._protocol.error(msg_id, message=str(err), error=err.__class__.__name__) except RpcError as err: self._protocol.connection.logger.error(ERRMSG_RPCERR, err) else: self._connection.response(msg_id, returned=returned) try: self._protocol.response(msg_id, returned=returned) except RpcError as err: self._protocol.connection.logger.error(ERRMSG_RPCERR, err) def start(self): ''' Start execution of the callable, the most of time, it just call :meth:`run` method. ''' self.run() Loading @@ -54,6 +68,7 @@ class ThreadedRpcCaller(RpcCaller): def __init__(self, *args, **kwargs): super(ThreadedRpcCaller, self).__init__(*args, **kwargs) self._thread = threading.Thread(target=self.run) self._thread.name = 'Processing of call: %s' % self._request['id'] self._thread.daemon = True def start(self): Loading Loading
sjrpc/__init__.py +1 −5 Original line number Diff line number Diff line #!/usr/bin/env python #coding:utf8 ''' Loading @@ -11,14 +9,12 @@ The library is separated into four parts: * core library contains all common classes. * server library contains all the server side related stuff. * client library contains all the client side related stuff. * utils library contains some helpers used in previous libraries. ''' import sjrpc.core import sjrpc.server import sjrpc.client import sjrpc.utils __version__ = 13 __version__ = '14~dev'
sjrpc/client/__init__.pydeleted 100644 → 0 +0 −6 Original line number Diff line number Diff line #!/usr/bin/env python #coding:utf8 from sjrpc.client.simple import SimpleRpcClient __all__ = ('SimpleRpcClient',)
sjrpc/client/simple.pydeleted 100644 → 0 +0 −109 Original line number Diff line number Diff line #!/usr/bin/env python #coding=utf8 import select import socket import logging from sjrpc.core import RpcConnection, ConnectionManager class SimpleRpcClient(ConnectionManager): ''' Create a new simple RPC client. :param connect: the :class:`RpcConnection` object to bind the client manager :param default_handler: the default handler to bind to the client connection :param on_disconnect: method on the handler to call when the client disconnects. ''' def __init__(self, connection, default_handler=None, on_disconnect=None): super(SimpleRpcClient, self).__init__() self._on_disconnect = on_disconnect self._connection = connection self._connection.set_handler(default_handler) self.register(self._connection.get_fd(), self._handle_event) @classmethod def from_addr(cls, addr, port, enable_ssl=False, cert=None, timeout=None, conn_timeout=30.0, default_handler=None, on_disconnect=None): ''' Construct the instance of :class:`SimpleRpcClient` without providing the :class:`RpcConnection` object. The :class:`RpcConnection` is automatically created and passed to the standard constructor before to return the new instance. :param addr: the target ip address :param port: the target port :param ssl: enable SSL :param timeout: the global call timeout setting :param conn_timeout: the connection operation timeout :param cert: is SSL is enabled, profile the filename of certificate to check. If None, don't check certificate. :param default_handler: the default handler to bind to the client connection :param on_disconnect: method on the handler to call when the client disconnects. ''' connection = RpcConnection.from_addr(addr, port, None, timeout=timeout, conn_timeout=conn_timeout, enable_ssl=enable_ssl, cert=cert) client = cls(connection, default_handler=default_handler, on_disconnect=on_disconnect) connection._manager = client return client @classmethod def from_sock(cls, sock, default_handler=None, on_disconnect=None): ''' Construct the instance of :class:`SimpleRpcClient` without providing the :class:`RpcConnection` object. The :class:`RpcConnection` is automatically created and passed to the standard constructor before to return the new instance :param sock: the socket object to wrap with :class:`RpcConnection` object. :param default_handler: the default handler to bind to the client connection :param on_disconnect: method on the handler to call when the client disconnects. ''' connection = RpcConnection(sock, None) client = cls(connection, default_handler, on_disconnect) connection._manager = client return client def shutdown(self): super(SimpleRpcClient, self).shutdown() self._connection.shutdown(self._on_disconnect) def _handle_event(self, fd, events): if events & select.EPOLLIN: # Data are ready to be readed on socket try: self._connection.receive() except socket.error as err: logging.debug('Socket error while receiving from the client ' 'fd/%s: %s', fd, err) self.shutdown() if events & select.EPOLLOUT: # Data are ready to be written on socket try: self._connection.send() except socket.error as err: logging.debug('Socket error while sending to the client ' 'fd/%s: %s', fd, err) self.shutdown() if events & select.EPOLLHUP: logging.debug('Socket HUP fd/%s', fd) self.shutdown() def all_connections(self): return set((self._connection,)) def call(self, *args, **kwargs): return self._connection.call(*args, **kwargs)
sjrpc/core/__init__.py +3 −4 Original line number Diff line number Diff line Loading @@ -2,10 +2,9 @@ #coding:utf8 from sjrpc.core.rpcconnection import * from sjrpc.core.connectionmanagers import * from sjrpc.core.callers import * from sjrpc.core.exceptions import * from sjrpc.core.async import * __all__ = ('ConnectionManager', 'RpcConnection', 'RpcCaller', 'RpcError', 'ThreadedRpcCaller', ) __all__ = ('RpcConnection', 'RpcCaller', 'ThreadedRpcCaller', 'RpcError', 'AsyncWatcher')
sjrpc/core/callers.py +36 −21 Original line number Diff line number Diff line #!/usr/bin/env python #coding:utf8 import threading from sjrpc.core.exceptions import RpcError ERRMSG_RPCERR = ('Unable to send reply to the peer: %s (this error is usualy ' 'raised when connection is lost while handler function ' 'execution)') class RpcCaller(object): ''' A caller execute a callable (function, method, class which implement the Loading @@ -11,37 +15,47 @@ class RpcCaller(object): peer through it :class:`RpcConnection` object. ''' def __init__(self, request, connection, func): def __init__(self, request, protocol, func): self._request = request self._connection = connection self._protocol = protocol self._func = func # Apply the request decorator #request_decorator = connection.request_decorator #if request_decorator is not None: # self._func = request_decorator(self._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) if getattr(self._func, '__pass_rpc__', False): args.insert(0, self._protocol) if getattr(self._func, '__pass_connection__', False): args.insert(0, self._protocol.connection) try: returned = self._func(*args, **kwargs) except Exception as err: self._connection.error(msg_id, message=str(err), try: self._protocol.error(msg_id, message=str(err), error=err.__class__.__name__) except RpcError as err: self._protocol.connection.logger.error(ERRMSG_RPCERR, err) else: self._connection.response(msg_id, returned=returned) try: self._protocol.response(msg_id, returned=returned) except RpcError as err: self._protocol.connection.logger.error(ERRMSG_RPCERR, err) def start(self): ''' Start execution of the callable, the most of time, it just call :meth:`run` method. ''' self.run() Loading @@ -54,6 +68,7 @@ class ThreadedRpcCaller(RpcCaller): def __init__(self, *args, **kwargs): super(ThreadedRpcCaller, self).__init__(*args, **kwargs) self._thread = threading.Thread(target=self.run) self._thread.name = 'Processing of call: %s' % self._request['id'] self._thread.daemon = True def start(self): Loading