1"""Basic http server for tests to simulate PyPI or custom indexes
2"""
3
4import os
5import time
6import threading
7import http.server
8import urllib.parse
9import urllib.request
10
11
12class IndexServer(http.server.HTTPServer):
13    """Basic single-threaded http server simulating a package index
14
15    You can use this server in unittest like this::
16        s = IndexServer()
17        s.start()
18        index_url = s.base_url() + 'mytestindex'
19        # do some test requests to the index
20        # The index files should be located in setuptools/tests/indexes
21        s.stop()
22    """
23
24    def __init__(
25            self, server_address=('', 0),
26            RequestHandlerClass=http.server.SimpleHTTPRequestHandler):
27        http.server.HTTPServer.__init__(
28            self, server_address, RequestHandlerClass)
29        self._run = True
30
31    def start(self):
32        self.thread = threading.Thread(target=self.serve_forever)
33        self.thread.start()
34
35    def stop(self):
36        "Stop the server"
37
38        # Let the server finish the last request and wait for a new one.
39        time.sleep(0.1)
40
41        self.shutdown()
42        self.thread.join()
43        self.socket.close()
44
45    def base_url(self):
46        port = self.server_port
47        return 'http://127.0.0.1:%s/setuptools/tests/indexes/' % port
48
49
50class RequestRecorder(http.server.BaseHTTPRequestHandler):
51    def do_GET(self):
52        requests = vars(self.server).setdefault('requests', [])
53        requests.append(self)
54        self.send_response(200, 'OK')
55
56
57class MockServer(http.server.HTTPServer, threading.Thread):
58    """
59    A simple HTTP Server that records the requests made to it.
60    """
61
62    def __init__(
63            self, server_address=('', 0),
64            RequestHandlerClass=RequestRecorder):
65        http.server.HTTPServer.__init__(
66            self, server_address, RequestHandlerClass)
67        threading.Thread.__init__(self)
68        self.daemon = True
69        self.requests = []
70
71    def run(self):
72        self.serve_forever()
73
74    @property
75    def netloc(self):
76        return 'localhost:%s' % self.server_port
77
78    @property
79    def url(self):
80        return 'http://%s/' % self.netloc
81
82
83def path_to_url(path, authority=None):
84    """ Convert a path to a file: URL. """
85    path = os.path.normpath(os.path.abspath(path))
86    base = 'file:'
87    if authority is not None:
88        base += '//' + authority
89    url = urllib.parse.urljoin(base, urllib.request.pathname2url(path))
90    return url
91