From cdd42f3b47a20e988a54c664c954b99370c2b3b9 Mon Sep 17 00:00:00 2001 From: Daniel D'Avella Date: Wed, 14 Feb 2018 15:45:17 -0500 Subject: [PATCH] Factor server code out of conftest to avoid circular dependency... This was causing problems when testing Astropy when ASDF is installed. --- asdf/conftest.py | 70 +------------------------------------ asdf/tests/helpers.py | 2 +- asdf/tests/httpserver.py | 75 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 70 deletions(-) create mode 100644 asdf/tests/httpserver.py diff --git a/asdf/conftest.py b/asdf/conftest.py index 745a06df9..f3406fbd8 100644 --- a/asdf/conftest.py +++ b/asdf/conftest.py @@ -1,7 +1,5 @@ # Licensed under a 3-clause BSD style license - see LICENSE.rst # -*- coding: utf-8 -*- - - # this contains imports plugins that configure py.test for asdf tests. # by importing them here in conftest.py they are discoverable by py.test # no matter how it is invoked within the source tree. @@ -9,12 +7,6 @@ from astropy.tests.plugins.display import PYTEST_HEADER_MODULES, TESTED_VERSIONS import os -import queue -import shutil -import tempfile -import threading -import http.server -import socketserver import pytest @@ -23,6 +15,7 @@ # This is to figure out the affiliated package version, rather than # using Astropy's from . import version +from .tests.httpserver import HTTPServer, RangeHTTPServer packagename = os.path.basename(os.path.dirname(__file__)) TESTED_VERSIONS[packagename] = version.version @@ -45,67 +38,6 @@ pass - - -def run_server(tmpdir, handler_class, stop_event, queue): # pragma: no cover - """ - Runs an HTTP server serving files from given tmpdir in a separate - process. When it's ready, it sends a URL to the server over a - queue so the main process (the HTTP client) can start making - requests of it. - """ - class HTTPRequestHandler(handler_class): - def translate_path(self, path): - path = handler_class.translate_path(self, path) - path = os.path.join( - tmpdir, - os.path.relpath(path, os.getcwd())) - return path - - server = socketserver.TCPServer(("127.0.0.1", 0), HTTPRequestHandler) - domain, port = server.server_address - url = "http://{0}:{1}/".format(domain, port) - - # Set a reasonable timeout so that invalid requests (which may occur during - # testing) do not cause the entire test suite to hang indefinitely - server.timeout = 0.1 - - queue.put(url) - - # Using server.serve_forever does not work here since it ignores the - # timeout value set above. Having an explicit loop also allows us to kill - # the server from the parent thread. - while not stop_event.isSet(): - server.handle_request() - - server.server_close() - - -class HTTPServer(object): - handler_class = http.server.SimpleHTTPRequestHandler - - def __init__(self): - self.tmpdir = tempfile.mkdtemp() - - q = queue.Queue() - self.stop_event = threading.Event() - - args = (self.tmpdir, self.handler_class, self.stop_event, q) - self.thread = threading.Thread(target=run_server, args=args) - self.thread.start() - - self.url = q.get() - - def finalize(self): - self.stop_event.set() - self.thread.join() - shutil.rmtree(self.tmpdir) - - -class RangeHTTPServer(HTTPServer): - handler_class = RangeHTTPRequestHandler - - @pytest.fixture() def httpserver(request): """ diff --git a/asdf/tests/helpers.py b/asdf/tests/helpers.py index be820e8b4..f7d7cf63b 100644 --- a/asdf/tests/helpers.py +++ b/asdf/tests/helpers.py @@ -20,7 +20,7 @@ CartesianDifferential = None from ..asdf import AsdfFile, get_asdf_library_info -from ..conftest import RangeHTTPServer +from .httpserver import RangeHTTPServer from ..extension import default_extensions from .. import util from .. import versioning diff --git a/asdf/tests/httpserver.py b/asdf/tests/httpserver.py new file mode 100644 index 000000000..8697fa057 --- /dev/null +++ b/asdf/tests/httpserver.py @@ -0,0 +1,75 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst +# -*- coding: utf-8 -*- + +import os +import queue +import shutil +import tempfile +import threading +import http.server +import socketserver + + +from ..extern.RangeHTTPServer import RangeHTTPRequestHandler + + +__all__ = ['HTTPServer', 'RangeHTTPServer'] + + +def run_server(tmpdir, handler_class, stop_event, queue): # pragma: no cover + """ + Runs an HTTP server serving files from given tmpdir in a separate + process. When it's ready, it sends a URL to the server over a + queue so the main process (the HTTP client) can start making + requests of it. + """ + class HTTPRequestHandler(handler_class): + def translate_path(self, path): + path = handler_class.translate_path(self, path) + path = os.path.join( + tmpdir, + os.path.relpath(path, os.getcwd())) + return path + + server = socketserver.TCPServer(("127.0.0.1", 0), HTTPRequestHandler) + domain, port = server.server_address + url = "http://{0}:{1}/".format(domain, port) + + # Set a reasonable timeout so that invalid requests (which may occur during + # testing) do not cause the entire test suite to hang indefinitely + server.timeout = 0.1 + + queue.put(url) + + # Using server.serve_forever does not work here since it ignores the + # timeout value set above. Having an explicit loop also allows us to kill + # the server from the parent thread. + while not stop_event.isSet(): + server.handle_request() + + server.server_close() + + +class HTTPServer(object): + handler_class = http.server.SimpleHTTPRequestHandler + + def __init__(self): + self.tmpdir = tempfile.mkdtemp() + + q = queue.Queue() + self.stop_event = threading.Event() + + args = (self.tmpdir, self.handler_class, self.stop_event, q) + self.thread = threading.Thread(target=run_server, args=args) + self.thread.start() + + self.url = q.get() + + def finalize(self): + self.stop_event.set() + self.thread.join() + shutil.rmtree(self.tmpdir) + + +class RangeHTTPServer(HTTPServer): + handler_class = RangeHTTPRequestHandler