#!/usr/bin/env python # Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. # # Use of this source code is governed by a BSD-style license # that can be found in the LICENSE file in the root of the source # tree. An additional intellectual property rights grant can be found # in the file PATENTS. All contributing project authors may # be found in the AUTHORS file in the root of the source tree. """Implements the coverage tracker dashboard and reporting facilities.""" __author__ = 'phoglund@webrtc.org (Patrik Hoglund)' import datetime from google.appengine.api import oauth from google.appengine.api import users from google.appengine.ext import db import webapp2 import gviz_api class UserNotAuthenticatedException(Exception): """Gets thrown if a user is not permitted to store coverage data.""" pass class CoverageData(db.Model): """This represents one coverage report from the build bot.""" date = db.DateTimeProperty(required=True) line_coverage = db.FloatProperty(required=True) function_coverage = db.FloatProperty(required=True) class ShowDashboard(webapp2.RequestHandler): """Shows the dashboard page. The page is shown by grabbing data we have stored previously in the App Engine database using the AddCoverageData handler. """ def get(self): page_template_filename = 'templates/dashboard_template.html' # Load the page HTML template. try: template_file = open(page_template_filename) page_template = template_file.read() template_file.close() except IOError as exception: self._show_error_page('Cannot open page template file: %s
Details: %s' % (page_template_filename, exception)) return coverage_entries = db.GqlQuery('SELECT * ' 'FROM CoverageData ' 'ORDER BY date ASC') data = [] for coverage_entry in coverage_entries: data.append({'date': coverage_entry.date, 'line_coverage': coverage_entry.line_coverage, 'function_coverage': coverage_entry.function_coverage, }) description = { 'date': ('datetime', 'Date'), 'line_coverage': ('number', 'Line Coverage'), 'function_coverage': ('number', 'Function Coverage') } coverage_data = gviz_api.DataTable(description, data) coverage_json_data = coverage_data.ToJSon(order_by='date') # Fill in the template with the data and respond: self.response.write(page_template % vars()) def _show_error_page(self, error_message): self.response.write('%s' % error_message) class AddCoverageData(webapp2.RequestHandler): """Used to report coverage data. The user is required to have obtained an OAuth access token from an administrator for this application earlier. """ def post(self): try: self._authenticate_user() except UserNotAuthenticatedException as exception: self._show_error_page('Failed to authenticate user: %s' % exception) return try: posix_time = int(self.request.get('date')) parsed_date = datetime.datetime.fromtimestamp(posix_time) line_coverage = float(self.request.get('line_coverage')) function_coverage = float(self.request.get('function_coverage')) except ValueError as exception: self._show_error_page('Invalid parameter in request. Details: %s' % exception) return item = CoverageData(date=parsed_date, line_coverage=line_coverage, function_coverage=function_coverage) item.put() def _authenticate_user(self): try: if oauth.is_current_user_admin(): # The user on whose behalf we are acting is indeed an administrator # of this application, so we're good to go. return else: raise UserNotAuthenticatedException('We are acting on behalf of ' 'user %s, but that user is not ' 'an administrator.' % oauth.get_current_user()) except oauth.OAuthRequestError as exception: raise UserNotAuthenticatedException('Invalid OAuth request: %s' % exception) def _show_error_page(self, error_message): self.response.write('%s' % error_message) app = webapp2.WSGIApplication([('/', ShowDashboard), ('/add_coverage_data', AddCoverageData)], debug=True)