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