blob: db607ddcbfd10fa8535abd426986e31abb889fa1 [file] [log] [blame]
# -*- coding: utf-8 -*-
# Copyright 2015 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""All django views for the build_annotations app."""
from __future__ import print_function
from django import http
from django import shortcuts
from django.core import urlresolvers
from django.views import generic
from google.appengine.api import users
from build_annotations import build_row_controller
from build_annotations import models as ba_models
from build_annotations import forms as ba_forms
from chromite.lib import constants
import urllib
_DEFAULT_USERNAME = "SomeoneGotHereWithoutLoggingIn"
def _BuildUrl(url_name, url_kwargs=None, get_kwargs=None):
"""Build a url via urlresolver, and attach GET arguments
Args:
url_name: Canonical name of the url.
url_kwargs: Arugment accepted by the url builder for the view.
get_kwargs: Url arguments for GET query. Accepts a dict or django's
QueryDict object.
"""
url = urlresolvers.reverse(url_name, kwargs=url_kwargs)
if get_kwargs is not None:
url += '?' + urllib.urlencode(get_kwargs, doseq=True)
return url
class ListBuildsView(generic.list.ListView):
"""The landing page view of the app. Lists requested builds."""
template_name = 'build_annotations/index.html'
def __init__(self, *args, **kwargs):
super(ListBuildsView, self).__init__(*args, **kwargs)
self._username = _DEFAULT_USERNAME
self._build_config = None
self._search_form = None
self._controller = None
self._builds_list = None
self._latest_build_id = None
self._num_builds = None
self._hist = None
def get_queryset(self):
self._controller = build_row_controller.BuildRowController()
build_config_q = None
if self._build_config is not None:
build_config_q = self._controller.GetQRestrictToBuildConfig(
self._build_config)
self._builds_list = self._controller.GetStructuredBuilds(
latest_build_id=self._latest_build_id,
num_builds=self._num_builds,
extra_filter_q=build_config_q)
self._hist = self._controller.GetHandlingTimeHistogram(
latest_build_id=self._latest_build_id,
num_builds=self._num_builds,
extra_filter_q=build_config_q)
return self._builds_list
def get_context_object_name(self, _):
return 'builds_list'
def get_context_data(self, **kwargs):
context = super(ListBuildsView, self).get_context_data(**kwargs)
context['username'] = self._username
context['search_form'] = self._GetSearchForm()
context['build_config'] = self._build_config
context['histogram_data'] = self._hist
return context
# pylint: disable=arguments-differ
def get(self, request, build_config=None):
# We're assured that a username exists in prod because our app sits behind
# appengine login. Not so when running from dev_appserver.
self._username = users.get_current_user()
self._build_config = build_config
self._PopulateUrlArgs(request.GET.get('latest_build_id'),
request.GET.get('num_builds'))
return super(ListBuildsView, self).get(request)
def post(self, request, build_config):
self._username = users.get_current_user()
self._build_config = build_config
self._latest_build_id = request.GET.get('latest_build_id')
self._num_builds = request.GET.get('num_builds')
form = ba_forms.SearchForm(request.POST)
self._search_form = form
if not form.is_valid():
return super(ListBuildsView, self).get(request)
self._latest_build_id = form.cleaned_data['latest_build_id']
self._num_builds = form.cleaned_data['num_builds']
return http.HttpResponseRedirect(_BuildUrl(
'build_annotations:builds_list',
url_kwargs={'build_config': build_config},
get_kwargs={'latest_build_id': self._latest_build_id,
'num_builds': self._num_builds}))
def put(self, *args, **kwargs):
return self.post(*args, **kwargs)
def _GetSearchForm(self):
if self._search_form is not None:
return self._search_form
return ba_forms.SearchForm(
{'latest_build_id': self._latest_build_id,
'num_builds': self._num_builds})
def _PopulateUrlArgs(self, latest_build_id, num_builds):
self._latest_build_id = latest_build_id
self._num_builds = num_builds
if self._latest_build_id is None or self._num_builds is None:
controller = build_row_controller.BuildRowController()
controller.GetStructuredBuilds(num_builds=1)
if self._latest_build_id is None:
self._latest_build_id = controller.latest_build_id
if self._num_builds is None:
self._num_builds = controller.DEFAULT_NUM_BUILDS
def _GetLatestBuildId(self):
controller = build_row_controller.BuildRowController()
controller.GetStructuredBuilds(num_builds=1)
return controller.latest_build_id
class EditAnnotationsView(generic.base.View):
"""View that handles annotation editing page."""
template_name = 'build_annotations/edit_annotations.html'
def __init__(self, *args, **kwargs):
self._username = _DEFAULT_USERNAME
self._annotations_formset = None
self._finalize_form = None
self._context = {}
self._build_config = None
self._build_id = None
super(EditAnnotationsView, self).__init__(*args, **kwargs)
def get(self, request, build_config, build_id):
# We're assured that a username exists in prod because our app sits behind
# appengine login. Not so when running from dev_appserver.
self._username = users.get_current_user()
self._build_config = build_config
self._build_id = build_id
self._PopulateContext()
return shortcuts.render(request, self.template_name, self._context)
def post(self, request, build_config, build_id):
# We're assured that a username exists in prod because our app sits behind
# appengine login. Not so when running from dev_appserver.
self._username = users.get_current_user()
self._build_config = build_config
self._build_id = build_id
finalize_form = ba_forms.FinalizeForm(request.POST)
if finalize_form.is_valid() and finalize_form['finalize'].value():
self._MaybeSaveFinalizeMessage()
self._annotations_formset = ba_forms.AnnotationsFormSet(request.POST)
if self._annotations_formset.is_valid():
self._SaveAnnotations()
return http.HttpResponseRedirect(_BuildUrl(
'build_annotations:edit_annotations',
url_kwargs={'build_config': build_config,
'build_id': build_id},
get_kwargs=request.GET))
else:
self._PopulateContext()
return shortcuts.render(request, self.template_name, self._context)
def _PopulateContext(self):
build_row = self._GetBuildRow()
if build_row is None:
raise http.Http404
self._context = {}
self._context['username'] = self._username
self._context['build_config'] = self._build_config
self._context['build_row'] = build_row
self._context['annotations_formset'] = self._GetAnnotationsFormSet()
self._context['finalize_form'] = self._GetFinalizeForm()
def _MaybeSaveFinalizeMessage(self):
"""Creates a finalize buildMessage for this build."""
has_finalize_message = self._GetFinalizeRow().exists()
if not has_finalize_message:
build = self._GetBuildRow().build_entry
ba_models.BuildMessageTable(
build_id=build,
message_type=
ba_models.BuildMessageTable.MESSAGE_TYPES.ANNOTATIONS_FINALIZED,
).save()
def _GetFinalizeRow(self):
"""Gets the existing finalize message for this build_id, if it exists."""
return ba_models.BuildMessageTable.objects.filter(
build_id=self._build_id,
message_type=
ba_models.BuildMessageTable.MESSAGE_TYPES.ANNOTATIONS_FINALIZED,
)
def _GetFinalizeForm(self):
"""Creates a finalize form for marking annotations as finalized.
'You FOOL! This isn't even my final form!' - Frieza
"""
has_finalize_message = self._GetFinalizeRow().exists()
return ba_forms.FinalizeForm({'finalize': has_finalize_message})
def _GetBuildRow(self):
controller = build_row_controller.BuildRowController()
build_row_list = controller.GetStructuredBuilds(
latest_build_id=self._build_id,
num_builds=1)
if not build_row_list:
return None
return build_row_list[0]
def _GetAnnotationsFormSet(self):
if self._annotations_formset is None:
build_row = self._GetBuildRow()
if build_row is not None:
queryset = build_row.GetAnnotationsQS()
else:
queryset = ba_models.AnnotationsTable.objects.none()
self._annotations_formset = ba_forms.AnnotationsFormSet(queryset=queryset)
return self._annotations_formset
def _SaveAnnotations(self):
models_to_save = self._annotations_formset.save(commit=False)
build_row = self._GetBuildRow()
for model in models_to_save:
if not hasattr(model, 'build_id') or model.build_id is None:
model.build_id = build_row.build_entry
model.last_annotator = self._username
model.save()