diff options
author | Hugo Parente Lima <hugo.pl@gmail.com> | 2010-09-08 15:08:41 -0300 |
---|---|---|
committer | Hugo Parente Lima <hugo.pl@gmail.com> | 2010-09-08 15:28:25 -0300 |
commit | 0ba776e27a8c17727fa883eed29f60bc6c0bb7be (patch) | |
tree | d489930e20e04443eafb7667979277853a586014 /tests | |
parent | f1bc92a2dd0f9a19ac8dcf9699f65d4ee2d61945 (diff) |
Fix bug#282 and bug#283.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/util/httpd.py | 84 |
1 files changed, 76 insertions, 8 deletions
diff --git a/tests/util/httpd.py b/tests/util/httpd.py index 96750f01c..4d7dde94b 100644 --- a/tests/util/httpd.py +++ b/tests/util/httpd.py @@ -1,10 +1,11 @@ import SocketServer import BaseHTTPServer +import os +import sys +import threading +import select import random -from threading import Thread - - class TestHandler(BaseHTTPServer.BaseHTTPRequestHandler): DATA = "PySide Server" @@ -42,22 +43,89 @@ class TestSecureHandler(BaseHTTPServer.BaseHTTPRequestHandler): self.send_header("Content-Length", str(len(TestHandler.DATA))) self.end_headers() +# Workaround for the missing shutdown method in python2.5 +class CompatTCPServer(SocketServer.TCPServer): + def __init__(self, server_address, RequestHandlerClass): + SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass) + + self.isPy25 = sys.version_info[0] == 2 and sys.version_info[1] == 5 + if self.isPy25: + self.__is_shut_down = threading.Event() + self.__serving = False + + def serve_forever(self, poll_interval=0.5): + """Handle one request at a time until shutdown. + + Polls for shutdown every poll_interval seconds. Ignores + self.timeout. If you need to do periodic tasks, do them in + another thread. + """ + if self.isPy25: + self.__serving = True + self.__is_shut_down.clear() + while self.__serving: + # XXX: Consider using another file descriptor or + # connecting to the socket to wake this up instead of + # polling. Polling reduces our responsiveness to a + # shutdown request and wastes cpu at all other times. + r, w, e = select.select([self], [], [], poll_interval) + if r: + self.py25_handle_request_noblock() + self.__is_shut_down.set() + else: + SocketServer.TCPServer.serve_forever(self, poll_interval) + + def py25_handle_request_noblock(self): + """Handle one request, without blocking. + + I assume that select.select has returned that the socket is + readable before this function was called, so there should be + no risk of blocking in get_request(). + """ + if self.isPy25: + try: + request, client_address = self.get_request() + except socket.error: + return + if self.verify_request(request, client_address): + try: + self.process_request(request, client_address) + except: + self.handle_error(request, client_address) + self.close_request(request) -class TestServer(Thread): + def shutdown(self): + """Stops the serve_forever loop. + + Blocks until the loop has finished. This must be called while + serve_forever() is running in another thread, or it will + deadlock. + """ + if self.isPy25: + self.__serving = False + if not self.__is_shut_down: + self.__is_shut_down.wait() + else: + SocketServer.TCPServer.shutdown(self) + + +class TestServer(threading.Thread): def __init__(self, secure=False): - Thread.__init__(self) + threading.Thread.__init__(self) - self._port = 8000 + random.randint(0, 100) + self._port = int(os.getenv("PYSIDE_TESTSERVER_PORT") or 12321) self.keep_running = True - server = SocketServer.TCPServer if secure: handle = TestSecureHandler else: handle = TestHandler - self.httpd = SocketServer.TCPServer(('' , self._port), handle) + try: + self.httpd = CompatTCPServer(('' , self._port), handle) + except: + self.httpd = CompatTCPServer(('' , self._port + random.randint(1, 100)), handle) def port(self): return self._port |