#!/usr/bin/env python # Copyright (c) 2012 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """Server for viewing the compiled C++ code from tools/json_schema_compiler. """ import cc_generator import code import cpp_type_generator import cpp_util import h_generator import idl_schema import json_schema import model import optparse import os import shlex import urlparse from highlighters import ( pygments_highlighter, none_highlighter, hilite_me_highlighter) from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer from cpp_namespace_environment import CppNamespaceEnvironment from schema_loader import SchemaLoader class CompilerHandler(BaseHTTPRequestHandler): """A HTTPRequestHandler that outputs the result of tools/json_schema_compiler. """ def do_GET(self): parsed_url = urlparse.urlparse(self.path) request_path = self._GetRequestPath(parsed_url) chromium_favicon = 'http://codereview.chromium.org/static/favicon.ico' head = code.Code() head.Append('' % chromium_favicon) head.Append('' % chromium_favicon) body = code.Code() try: if os.path.isdir(request_path): self._ShowPanels(parsed_url, head, body) else: self._ShowCompiledFile(parsed_url, head, body) finally: self.wfile.write('
') self.wfile.write(head.Render()) self.wfile.write('') self.wfile.write(body.Render()) self.wfile.write('') def _GetRequestPath(self, parsed_url, strip_nav=False): """Get the relative path from the current directory to the requested file. """ path = parsed_url.path if strip_nav: path = parsed_url.path.replace('/nav', '') return os.path.normpath(os.curdir + path) def _ShowPanels(self, parsed_url, head, body): """Show the previewer frame structure. Code panes are populated via XHR after links in the nav pane are clicked. """ (head.Append('') ) body.Append( ' ' '' '' % self._RenderNavPane(parsed_url.path[1:]) ) # The Javascript that interacts with the nav pane and panes to show the # compiled files as the URL or highlighting options change. body.Append('''''') def _ShowCompiledFile(self, parsed_url, head, body): """Show the compiled version of a json or idl file given the path to the compiled file. """ api_model = model.Model() request_path = self._GetRequestPath(parsed_url) (file_root, file_ext) = os.path.splitext(request_path) (filedir, filename) = os.path.split(file_root) schema_loader = SchemaLoader("./", filedir, self.server.include_rules, self.server.cpp_namespace_pattern) try: # Get main file. namespace = schema_loader.ResolveNamespace(filename) type_generator = cpp_type_generator.CppTypeGenerator( api_model, schema_loader, namespace) # Generate code if file_ext == '.h': cpp_code = (h_generator.HGenerator(type_generator) .Generate(namespace).Render()) elif file_ext == '.cc': cpp_code = (cc_generator.CCGenerator(type_generator) .Generate(namespace).Render()) else: self.send_error(404, "File not found: %s" % request_path) return # Do highlighting on the generated code (highlighter_param, style_param) = self._GetHighlighterParams(parsed_url) head.Append('') body.Append(self.server.highlighters[highlighter_param] .GetCodeElement(cpp_code, style_param)) except IOError: self.send_error(404, "File not found: %s" % request_path) return except (TypeError, KeyError, AttributeError, AssertionError, NotImplementedError) as error: body.Append('') body.Append('compiler error: %s' % error) body.Append('Check server log for more details') body.Append('') raise def _GetHighlighterParams(self, parsed_url): """Get the highlighting parameters from a parsed url. """ query_dict = urlparse.parse_qs(parsed_url.query) return (query_dict.get('highlighter', ['pygments'])[0], query_dict.get('style', ['colorful'])[0]) def _RenderNavPane(self, path): """Renders an HTML nav pane. This consists of a select element to set highlight style, and a list of all files at |path| with the appropriate onclick handlers to open either subdirectories or JSON files. """ html = code.Code() # Highlighter chooser. html.Append('') html.Append('