1  """ 
 2  Simple HTTP request dumper for tests in Python 2.5+. 
 3  """ 
 4   
 5  import sys 
 6  from contextlib import contextmanager 
 7   
 8  try: 
 9      import urlparse 
10  except ImportError: 
11       
12      import urllib.parse as urlparse 
13   
14   
15  @contextmanager 
16 -def webserver(app, port=0, host=None): 
 17      """Context manager entry point for the 'with' statement. 
18   
19      Pass 0 as port number to dynamically allocate a free port. 
20   
21      Usage: 
22   
23      with webserver(wsgi_app_function, 8080) as host_url: 
24          do_ws_calls(host_url) 
25      """ 
26      server = build_web_server(app, port, host or '127.0.0.1') 
27      host, port = server.socket.getsockname() 
28   
29      import threading 
30      thread = threading.Thread(target=server.serve_forever, 
31                                kwargs={'poll_interval': 0.5}) 
32      thread.setDaemon(True) 
33      thread.start() 
34      try: 
35          yield 'http://%s:%s/' % (host, port)   
36      finally: 
37          server.shutdown() 
38          server.server_close() 
 39   
40   
41  try: 
42      from SocketServer import ThreadingMixIn 
43  except ImportError: 
44       
45      from socketserver import ThreadingMixIn 
46   
47  import wsgiref.simple_server as wsgiserver 
48 -class WebServer(wsgiserver.WSGIServer, ThreadingMixIn): 
 49      """A web server that starts a new thread for each request. 
50      """ 
 51   
61   
64      server = wsgiserver.make_server( 
65          host or '', port, app, 
66          server_class=WebServer, 
67          handler_class=_RequestHandler) 
68      return server 
 69   
72 -    def __init__(self, response_data, response_code=200, headers=()): 
 73          self.requests = [] 
74          self.response_code = response_code 
75          self.response_data = response_data 
76          self.headers = list(headers or ()) 
 77   
78 -    def __call__(self, environ, start_response): 
 79          self.requests.append(( 
80              environ.get('PATH_INFO'), 
81              urlparse.parse_qsl(environ.get('QUERY_STRING')))) 
82          start_response('%s OK' % self.response_code, self.headers) 
83          return [self.response_data]