run_dev_server.py revision 66a37686207944273ced825e0e8b6b6375f8c3de
188448d9ae4dfff1805045790ef5f32495d62abccJeff Brown#!/usr/bin/env python 288448d9ae4dfff1805045790ef5f32495d62abccJeff Brown# Copyright (c) 2012 The Chromium Authors. All rights reserved. 388448d9ae4dfff1805045790ef5f32495d62abccJeff Brown# Use of this source code is governed by a BSD-style license that can be 488448d9ae4dfff1805045790ef5f32495d62abccJeff Brown# found in the LICENSE file. 566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisimport json 688448d9ae4dfff1805045790ef5f32495d62abccJeff Brownimport optparse 788448d9ae4dfff1805045790ef5f32495d62abccJeff Brownimport os 888448d9ae4dfff1805045790ef5f32495d62abccJeff Brownimport sys 94849cead45edf85cf2a61526c0b716eb637f74baJeff Brownimport time 1066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisimport traceback 1166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisfrom build import generate_deps_js_contents as deps_generator 1266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisfrom build import generate_template_contents as template_generator 1388448d9ae4dfff1805045790ef5f32495d62abccJeff Brown 1466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisimport SocketServer 1588448d9ae4dfff1805045790ef5f32495d62abccJeff Brownimport SimpleHTTPServer 1688448d9ae4dfff1805045790ef5f32495d62abccJeff Brownimport BaseHTTPServer 1788448d9ae4dfff1805045790ef5f32495d62abccJeff Brown 1888448d9ae4dfff1805045790ef5f32495d62abccJeff BrownDEFAULT_PORT = 8003 1966a37686207944273ced825e0e8b6b6375f8c3deJamie GennisDEPS_CHECK_DELAY = 30 2066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 2166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennistoplevel_dir = os.path.abspath(os.path.dirname(__file__)) 2266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennissrc_dir = os.path.join(toplevel_dir, 'src') 2366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennistest_data_dir = os.path.join(toplevel_dir, 'test_data') 2488448d9ae4dfff1805045790ef5f32495d62abccJeff Brown 2588448d9ae4dfff1805045790ef5f32495d62abccJeff Brownclass Handler(SimpleHTTPServer.SimpleHTTPRequestHandler): 2666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis def __init__(self, *args, **kwargs): 2766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, *args, **kwargs) 2866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 2966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis def send_response(self, code, message=None): 3066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis SimpleHTTPServer.SimpleHTTPRequestHandler.send_response(self, code, message) 3166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if code == 200: 3266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.send_header('Cache-Control', 'no-cache') 3366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 3466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis def do_GET_json_tests(self): 3566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis def is_test(x): 3666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis basename = os.path.basename(x) 3766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if basename.startswith('.'): 3866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return False 3966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 4066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if basename.endswith('_test.js'): 4166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return True 4266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return False 4366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 4466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis test_filenames = [] 4566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis for dirpath, dirnames, filenames in os.walk(src_dir): 4666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis for f in filenames: 4766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis x = os.path.join(dirpath, f) 4866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis y = '/' + os.path.relpath(x, toplevel_dir) 4966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if is_test(y): 5066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis test_filenames.append(y) 5166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 5266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis test_filenames.sort() 5366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 5466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis tests_as_json = json.dumps(test_filenames) 5566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 5666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.send_response(200) 5766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.send_header('Content-Type', 'application/json') 5866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.send_header('Content-Length', len(tests_as_json)) 5966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.end_headers() 6066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.wfile.write(tests_as_json) 6166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 6266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis def do_GET_example_files(self): 6366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis data_files = [] 6466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis for dirpath, dirnames, filenames in os.walk(test_data_dir): 6566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis for f in filenames: 6666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis data_files.append(f) 6766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 6866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis data_files.sort() 6966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis files_as_json = json.dumps(data_files) 7066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 7166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.send_response(200) 7266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.send_header('Content-Type', 'application/json') 7366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.send_header('Content-Length', len(files_as_json)) 7466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.end_headers() 7566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.wfile.write(files_as_json) 7666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 7766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis def do_GET_deps(self): 7866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis current_time = time.time() 7966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if self.server.next_deps_check < current_time: 8066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.log_message('Regenerating ' + self.path) 8166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis try: 8266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.server.deps = deps_generator.generate_deps_js() 8366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis except Exception, ex: 8466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis msg = json.dumps({"details": traceback.format_exc(), 8566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis "message": ex.message}); 8666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.log_error('While parsing deps: %s', ex.message) 8766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.send_response(500) 8866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.send_header('Content-Type', 'application/json') 8966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.send_header('Cache-Control', 'no-cache') 9066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.send_header('Content-Length', len(msg)) 9166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.end_headers() 9266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.wfile.write(msg) 9366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return 9466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 9566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.server.next_deps_check = current_time + DEPS_CHECK_DELAY 9666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 9766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.send_response(200) 9866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.send_header('Content-Type', 'application/javascript') 9966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.send_header('Content-Length', len(self.server.deps)) 10066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.end_headers() 10166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.wfile.write(self.server.deps) 10266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 10366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis def do_GET_templates(self): 10466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis templates = template_generator.generate_templates() 10566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 10666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.send_response(200) 10766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.send_header('Content-Type', 'text/html') 10866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.send_header('Content-Length', len(templates)) 10966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.end_headers() 11066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.wfile.write(templates) 11166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 11288448d9ae4dfff1805045790ef5f32495d62abccJeff Brown def do_GET(self): 11366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if self.path == '/json/examples': 11466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.do_GET_example_files() 11566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return 11666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 11766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if self.path == '/json/tests': 11866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.do_GET_json_tests() 11966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return 12066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 12166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if self.path == '/templates': 12266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.do_GET_templates() 12366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return 12466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 12566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if self.path == '/deps.js': 12666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.do_GET_deps() 12766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return 12866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 12988448d9ae4dfff1805045790ef5f32495d62abccJeff Brown return SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self) 13088448d9ae4dfff1805045790ef5f32495d62abccJeff Brown 13166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis def log_error(self, format, *args): 13266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if self.path == '/favicon.ico': 13366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return 13466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.log_message("While processing %s: ", self.path) 13566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis SimpleHTTPServer.SimpleHTTPRequestHandler.log_error(self, format, *args) 13666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 13766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis def log_request(self, code='-', size='-'): 13866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis # Dont spam the console unless it is important. 13966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis pass 14066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 14166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 14266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisclass Server(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer): 1434849cead45edf85cf2a61526c0b716eb637f74baJeff Brown def __init__(self, *args, **kwargs): 1444849cead45edf85cf2a61526c0b716eb637f74baJeff Brown BaseHTTPServer.HTTPServer.__init__(self, *args, **kwargs) 1454849cead45edf85cf2a61526c0b716eb637f74baJeff Brown self.next_deps_check = -1 14666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis self.deps = None 14788448d9ae4dfff1805045790ef5f32495d62abccJeff Brown 14888448d9ae4dfff1805045790ef5f32495d62abccJeff Browndef Main(args): 14988448d9ae4dfff1805045790ef5f32495d62abccJeff Brown parser = optparse.OptionParser() 15088448d9ae4dfff1805045790ef5f32495d62abccJeff Brown parser.add_option('--port', 15188448d9ae4dfff1805045790ef5f32495d62abccJeff Brown action='store', 15288448d9ae4dfff1805045790ef5f32495d62abccJeff Brown type='int', 15388448d9ae4dfff1805045790ef5f32495d62abccJeff Brown default=DEFAULT_PORT, 15488448d9ae4dfff1805045790ef5f32495d62abccJeff Brown help='Port to serve from') 15588448d9ae4dfff1805045790ef5f32495d62abccJeff Brown options, args = parser.parse_args() 15688448d9ae4dfff1805045790ef5f32495d62abccJeff Brown server = Server(('', options.port), Handler) 15788448d9ae4dfff1805045790ef5f32495d62abccJeff Brown sys.stderr.write("Now running on http://localhost:%i\n" % options.port) 15888448d9ae4dfff1805045790ef5f32495d62abccJeff Brown server.serve_forever() 15988448d9ae4dfff1805045790ef5f32495d62abccJeff Brown 16088448d9ae4dfff1805045790ef5f32495d62abccJeff Brownif __name__ == '__main__': 16166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis os.chdir(toplevel_dir) 16288448d9ae4dfff1805045790ef5f32495d62abccJeff Brown sys.exit(Main(sys.argv[1:])) 163