diff options
-rw-r--r-- | jsonrpclib/SimpleJSONRPCServer.py | 13 | ||||
-rw-r--r-- | jsonrpclib/jsonrpc.py | 45 | ||||
-rw-r--r-- | tests.py | 69 |
3 files changed, 99 insertions, 28 deletions
diff --git a/jsonrpclib/SimpleJSONRPCServer.py b/jsonrpclib/SimpleJSONRPCServer.py index 854697b..d76da73 100644 --- a/jsonrpclib/SimpleJSONRPCServer.py +++ b/jsonrpclib/SimpleJSONRPCServer.py @@ -1,8 +1,10 @@ import jsonrpclib from jsonrpclib import Fault +from jsonrpclib.jsonrpc import USE_UNIX_SOCKETS import SimpleXMLRPCServer import SocketServer import socket +import logging import os import types import traceback @@ -192,14 +194,15 @@ class SimpleJSONRPCServer(SocketServer.TCPServer, SimpleJSONRPCDispatcher): # check Python version and decide on how to call it vi = sys.version_info self.address_family = address_family - if address_family == socket.AF_UNIX: + if USE_UNIX_SOCKETS and address_family == socket.AF_UNIX: # Unix sockets can't be bound if they already exist in the # filesystem. The convention of e.g. X11 is to unlink # before binding again. - try: - os.unlink(addr) - except OSError: - pass + if os.path.exists(addr): + try: + os.unlink(addr) + except OSError: + logging.warning("Could not unlink socket %s", addr) # if python 2.5 and lower if vi[0] < 3 and vi[1] < 6: SocketServer.TCPServer.__init__(self, addr, requestHandler) diff --git a/jsonrpclib/jsonrpc.py b/jsonrpclib/jsonrpc.py index ae5c75f..0655e38 100644 --- a/jsonrpclib/jsonrpc.py +++ b/jsonrpclib/jsonrpc.py @@ -81,6 +81,12 @@ except ImportError: IDCHARS = string.ascii_lowercase+string.digits +class UnixSocketMissing(Exception): + """ + Just a properly named Exception if Unix Sockets usage is + attempted on a platform that doesn't support them (Windows) + """ + pass #JSON Abstractions @@ -147,22 +153,32 @@ class Transport(TransportMixIn, XMLTransport): class SafeTransport(TransportMixIn, XMLSafeTransport): pass - from httplib import HTTP, HTTPConnection -from socket import socket, AF_UNIX, SOCK_STREAM -class UnixHTTPConnection(HTTPConnection): - def connect(self): - self.sock = socket(AF_UNIX, SOCK_STREAM) - self.sock.connect(self.host) +from socket import socket + +USE_UNIX_SOCKETS = False + +try: + from socket import AF_UNIX, SOCK_STREAM + USE_UNIX_SOCKETS = True +except ImportError: + pass + +if (USE_UNIX_SOCKETS): + + class UnixHTTPConnection(HTTPConnection): + def connect(self): + self.sock = socket(AF_UNIX, SOCK_STREAM) + self.sock.connect(self.host) -class UnixHTTP(HTTP): - _connection_class = UnixHTTPConnection + class UnixHTTP(HTTP): + _connection_class = UnixHTTPConnection -class UnixTransport(TransportMixIn, XMLTransport): - def make_connection(self, host): - import httplib - host, extra_headers, x509 = self.get_host_info(host) - return UnixHTTP(host) + class UnixTransport(TransportMixIn, XMLTransport): + def make_connection(self, host): + import httplib + host, extra_headers, x509 = self.get_host_info(host) + return UnixHTTP(host) class ServerProxy(XMLServerProxy): @@ -181,6 +197,9 @@ class ServerProxy(XMLServerProxy): if schema not in ('http', 'https', 'unix'): raise IOError('Unsupported JSON-RPC protocol.') if schema == 'unix': + if not USE_UNIX_SOCKETS: + # Don't like the "generic" Exception... + raise UnixSocketMissing("Unix sockets not available.") self.__host = uri self.__handler = '/' else: @@ -20,11 +20,14 @@ TODO: """ from jsonrpclib import Server, MultiCall, history, config, ProtocolError +from jsonrpclib import jsonrpc from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCRequestHandler import socket +import tempfile import unittest import os +import time try: import json except ImportError: @@ -345,17 +348,60 @@ class InternalTests(unittest.TestCase): self.assertRaises(raises[i], func) -class UnixSocketInternalTests(InternalTests): - """ - These tests run the same internal communication tests, but over a - Unix socket instead of a TCP socket. +if jsonrpc.USE_UNIX_SOCKETS: + # We won't do these tests unless Unix Sockets are supported + + class UnixSocketInternalTests(InternalTests): + """ + These tests run the same internal communication tests, + but over a Unix socket instead of a TCP socket. + """ + def setUp(self): + suffix = "%d.sock" % PORTS.pop() + + # Open to safer, alternative processes + # for getting a temp file name... + temp = tempfile.NamedTemporaryFile( + suffix=suffix + ) + self.port = temp.name + temp.close() + + self.server = server_set_up( + addr=self.port, + address_family=socket.AF_UNIX + ) + + def get_client(self): + return Server('unix:/%s' % self.port) + + def tearDown(self): + """ Removes the tempory socket file """ + os.unlink(self.port) + +class UnixSocketErrorTests(unittest.TestCase): + """ + Simply tests that the proper exceptions fire if + Unix sockets are attempted to be used on a platform + that doesn't support them. """ + def setUp(self): - self.port = "/tmp/jsonrpc%d.sock" % (PORTS.pop()) - self.server = server_set_up(addr=self.port, address_family=socket.AF_UNIX) - - def get_client(self): - return Server('unix:%s' % self.port) + self.original_value = jsonrpc.USE_UNIX_SOCKETS + if (jsonrpc.USE_UNIX_SOCKETS): + jsonrpc.USE_UNIX_SOCKETS = False + + def test_client(self): + address = "unix://shouldnt/work.sock" + self.assertRaises( + jsonrpc.UnixSocketMissing, + Server, + address + ) + + def tearDown(self): + jsonrpc.USE_UNIX_SOCKETS = self.original_value + """ Test Methods """ def subtract(minuend, subtrahend): @@ -403,5 +449,8 @@ def server_set_up(addr, address_family=socket.AF_INET): return server_proc if __name__ == '__main__': + print "===============================================================" + print " NOTE: There may be threading exceptions after tests finish. " + print "===============================================================" + time.sleep(2) unittest.main() - |