summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Wood <michael.g.wood@intel.com>2016-09-26 13:59:29 +0300
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-09-28 10:45:10 +0100
commit05428514e64ec896faae4055619e149e98bc8f57 (patch)
tree152ffce1b89869408c2f00225835b40026cbf353
parent8b01767d6e787cdb09789116ebf57dfb70f521bc (diff)
downloadbitbake-05428514e64ec896faae4055619e149e98bc8f57.tar.gz
toaster: move MostRecentBuildsView to its own widget
This view is specific to the builds dashboard rather than gernic api so like ToasterTable and ToasterTypeAhead we class it as a widget as it has a single purpose. Also clean up some flake8 identified issues. Original author of the code moved in this commit is Elliot Smith. Signed-off-by: Michael Wood <michael.g.wood@intel.com> Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--lib/toaster/toastergui/api.py108
-rw-r--r--lib/toaster/toastergui/urls.py3
-rw-r--r--lib/toaster/toastergui/widgets.py141
3 files changed, 127 insertions, 125 deletions
diff --git a/lib/toaster/toastergui/api.py b/lib/toaster/toastergui/api.py
index 887640996..558911802 100644
--- a/lib/toaster/toastergui/api.py
+++ b/lib/toaster/toastergui/api.py
@@ -33,10 +33,8 @@ from bldcontrol import bbcontroller
from django.http import HttpResponse, JsonResponse
from django.views.generic import View
from django.core.urlresolvers import reverse
-from django.utils import timezone
from django.db.models import Q, F
from django.db import Error
-from toastergui.templatetags.projecttags import json, sectohms, get_tasks
from toastergui.templatetags.projecttags import filtered_filesizeformat
logger = logging.getLogger("toaster")
@@ -227,112 +225,6 @@ class XhrLayer(View):
})
-class MostRecentBuildsView(View):
- def _was_yesterday_or_earlier(self, completed_on):
- now = timezone.now()
- delta = now - completed_on
-
- if delta.days >= 1:
- return True
-
- return False
-
- def get(self, request, *args, **kwargs):
- """
- Returns a list of builds in JSON format.
- """
- project = None
-
- project_id = request.GET.get('project_id', None)
- if project_id:
- try:
- project = Project.objects.get(pk=project_id)
- except:
- # if project lookup fails, assume no project
- pass
-
- recent_build_objs = Build.get_recent(project)
- recent_builds = []
-
- for build_obj in recent_build_objs:
- dashboard_url = reverse('builddashboard', args=(build_obj.pk,))
- buildtime_url = reverse('buildtime', args=(build_obj.pk,))
- rebuild_url = \
- reverse('xhr_buildrequest', args=(build_obj.project.pk,))
- cancel_url = \
- reverse('xhr_buildrequest', args=(build_obj.project.pk,))
-
- build = {}
- build['id'] = build_obj.pk
- build['dashboard_url'] = dashboard_url
-
- buildrequest_id = None
- if hasattr(build_obj, 'buildrequest'):
- buildrequest_id = build_obj.buildrequest.pk
- build['buildrequest_id'] = buildrequest_id
-
- build['recipes_parsed_percentage'] = \
- int((build_obj.recipes_parsed /
- build_obj.recipes_to_parse) * 100)
-
- tasks_complete_percentage = 0
- if build_obj.outcome in (Build.SUCCEEDED, Build.FAILED):
- tasks_complete_percentage = 100
- elif build_obj.outcome == Build.IN_PROGRESS:
- tasks_complete_percentage = build_obj.completeper()
- build['tasks_complete_percentage'] = tasks_complete_percentage
-
- build['state'] = build_obj.get_state()
-
- build['errors'] = build_obj.errors.count()
- build['dashboard_errors_url'] = dashboard_url + '#errors'
-
- build['warnings'] = build_obj.warnings.count()
- build['dashboard_warnings_url'] = dashboard_url + '#warnings'
-
- build['buildtime'] = sectohms(build_obj.timespent_seconds)
- build['buildtime_url'] = buildtime_url
-
- build['rebuild_url'] = rebuild_url
- build['cancel_url'] = cancel_url
-
- build['is_default_project_build'] = build_obj.project.is_default
-
- build['build_targets_json'] = \
- json(get_tasks(build_obj.target_set.all()))
-
- # convert completed_on time to user's timezone
- completed_on = timezone.localtime(build_obj.completed_on)
-
- completed_on_template = '%H:%M'
- if self._was_yesterday_or_earlier(completed_on):
- completed_on_template = '%d/%m/%Y ' + completed_on_template
- build['completed_on'] = completed_on.strftime(
- completed_on_template)
-
- targets = []
- target_objs = build_obj.get_sorted_target_list()
- for target_obj in target_objs:
- if target_obj.task:
- targets.append(target_obj.target + ':' + target_obj.task)
- else:
- targets.append(target_obj.target)
- build['targets'] = ' '.join(targets)
-
- # abbreviated form of the full target list
- abbreviated_targets = ''
- num_targets = len(targets)
- if num_targets > 0:
- abbreviated_targets = targets[0]
- if num_targets > 1:
- abbreviated_targets += (' +%s' % (num_targets - 1))
- build['targets_abbreviated'] = abbreviated_targets
-
- recent_builds.append(build)
-
- return JsonResponse(recent_builds, safe=False)
-
-
class XhrCustomRecipe(View):
""" Create a custom image recipe """
diff --git a/lib/toaster/toastergui/urls.py b/lib/toaster/toastergui/urls.py
index 1232611e2..0002a5a2e 100644
--- a/lib/toaster/toastergui/urls.py
+++ b/lib/toaster/toastergui/urls.py
@@ -24,6 +24,7 @@ from toastergui import tables
from toastergui import buildtables
from toastergui import typeaheads
from toastergui import api
+from toastergui import widgets
urlpatterns = patterns('toastergui.views',
# landing page
@@ -224,7 +225,7 @@ urlpatterns = patterns('toastergui.views',
api.XhrProject.as_view(),
name='xhr_project'),
- url(r'^mostrecentbuilds$', api.MostRecentBuildsView.as_view(),
+ url(r'^mostrecentbuilds$', widgets.MostRecentBuildsView.as_view(),
name='most_recent_builds'),
# default redirection
diff --git a/lib/toaster/toastergui/widgets.py b/lib/toaster/toastergui/widgets.py
index 005a5620d..026903d35 100644
--- a/lib/toaster/toastergui/widgets.py
+++ b/lib/toaster/toastergui/widgets.py
@@ -22,23 +22,24 @@
from django.views.generic import View, TemplateView
from django.views.decorators.cache import cache_control
from django.shortcuts import HttpResponse
-from django.http import HttpResponseBadRequest
-from django.core import serializers
from django.core.cache import cache
from django.core.paginator import Paginator, EmptyPage
from django.db.models import Q
-from orm.models import Project, ProjectLayer, Layer_Version
+from orm.models import Project, Build
from django.template import Context, Template
from django.template import VariableDoesNotExist
from django.template import TemplateSyntaxError
from django.core.serializers.json import DjangoJSONEncoder
from django.core.exceptions import FieldError
-from django.conf.urls import url, patterns
+from django.utils import timezone
+from toastergui.templatetags.projecttags import sectohms, get_tasks
+from toastergui.templatetags.projecttags import json as template_json
+from django.http import JsonResponse
+from django.core.urlresolvers import reverse
import types
import json
import collections
-import operator
import re
try:
@@ -55,6 +56,7 @@ from toastergui.tablefilter import TableFilterMap
class NoFieldOrDataName(Exception):
pass
+
class ToasterTable(TemplateView):
def __init__(self, *args, **kwargs):
super(ToasterTable, self).__init__()
@@ -81,7 +83,7 @@ class ToasterTable(TemplateView):
def get_context_data(self, **kwargs):
context = super(ToasterTable, self).get_context_data(**kwargs)
context['title'] = self.title
- context['table_name'] = type(self).__name__.lower()
+ context['table_name'] = type(self).__name__.lower()
context['empty_state'] = self.empty_state
return context
@@ -406,7 +408,6 @@ class ToasterTable(TemplateView):
return data
-
class ToasterTypeAhead(View):
""" A typeahead mechanism to support the front end typeahead widgets """
MAX_RESULTS = 6
@@ -427,34 +428,142 @@ class ToasterTypeAhead(View):
error = "ok"
search_term = request.GET.get("search", None)
- if search_term == None:
+ if search_term is None:
# We got no search value so return empty reponse
- return response({'error' : error , 'results': []})
+ return response({'error': error, 'results': []})
try:
prj = Project.objects.get(pk=kwargs['pid'])
except KeyError:
prj = None
- results = self.apply_search(search_term, prj, request)[:ToasterTypeAhead.MAX_RESULTS]
+ results = self.apply_search(search_term,
+ prj,
+ request)[:ToasterTypeAhead.MAX_RESULTS]
if len(results) > 0:
try:
self.validate_fields(results[0])
- except MissingFieldsException as e:
+ except self.MissingFieldsException as e:
error = e
- data = { 'results' : results,
- 'error' : error,
- }
+ data = {'results': results,
+ 'error': error}
return response(data)
def validate_fields(self, result):
- if 'name' in result == False or 'detail' in result == False:
- raise MissingFieldsException("name and detail are required fields")
+ if 'name' in result is False or 'detail' in result is False:
+ raise self.MissingFieldsException(
+ "name and detail are required fields")
def apply_search(self, search_term, prj):
""" Override this function to implement search. Return an array of
dictionaries with a minium of a name and detail field"""
pass
+
+
+class MostRecentBuildsView(View):
+ def _was_yesterday_or_earlier(self, completed_on):
+ now = timezone.now()
+ delta = now - completed_on
+
+ if delta.days >= 1:
+ return True
+
+ return False
+
+ def get(self, request, *args, **kwargs):
+ """
+ Returns a list of builds in JSON format.
+ """
+ project = None
+
+ project_id = request.GET.get('project_id', None)
+ if project_id:
+ try:
+ project = Project.objects.get(pk=project_id)
+ except:
+ # if project lookup fails, assume no project
+ pass
+
+ recent_build_objs = Build.get_recent(project)
+ recent_builds = []
+
+ for build_obj in recent_build_objs:
+ dashboard_url = reverse('builddashboard', args=(build_obj.pk,))
+ buildtime_url = reverse('buildtime', args=(build_obj.pk,))
+ rebuild_url = \
+ reverse('xhr_buildrequest', args=(build_obj.project.pk,))
+ cancel_url = \
+ reverse('xhr_buildrequest', args=(build_obj.project.pk,))
+
+ build = {}
+ build['id'] = build_obj.pk
+ build['dashboard_url'] = dashboard_url
+
+ buildrequest_id = None
+ if hasattr(build_obj, 'buildrequest'):
+ buildrequest_id = build_obj.buildrequest.pk
+ build['buildrequest_id'] = buildrequest_id
+
+ build['recipes_parsed_percentage'] = \
+ int((build_obj.recipes_parsed /
+ build_obj.recipes_to_parse) * 100)
+
+ tasks_complete_percentage = 0
+ if build_obj.outcome in (Build.SUCCEEDED, Build.FAILED):
+ tasks_complete_percentage = 100
+ elif build_obj.outcome == Build.IN_PROGRESS:
+ tasks_complete_percentage = build_obj.completeper()
+ build['tasks_complete_percentage'] = tasks_complete_percentage
+
+ build['state'] = build_obj.get_state()
+
+ build['errors'] = build_obj.errors.count()
+ build['dashboard_errors_url'] = dashboard_url + '#errors'
+
+ build['warnings'] = build_obj.warnings.count()
+ build['dashboard_warnings_url'] = dashboard_url + '#warnings'
+
+ build['buildtime'] = sectohms(build_obj.timespent_seconds)
+ build['buildtime_url'] = buildtime_url
+
+ build['rebuild_url'] = rebuild_url
+ build['cancel_url'] = cancel_url
+
+ build['is_default_project_build'] = build_obj.project.is_default
+
+ build['build_targets_json'] = \
+ template_json(get_tasks(build_obj.target_set.all()))
+
+ # convert completed_on time to user's timezone
+ completed_on = timezone.localtime(build_obj.completed_on)
+
+ completed_on_template = '%H:%M'
+ if self._was_yesterday_or_earlier(completed_on):
+ completed_on_template = '%d/%m/%Y ' + completed_on_template
+ build['completed_on'] = completed_on.strftime(
+ completed_on_template)
+
+ targets = []
+ target_objs = build_obj.get_sorted_target_list()
+ for target_obj in target_objs:
+ if target_obj.task:
+ targets.append(target_obj.target + ':' + target_obj.task)
+ else:
+ targets.append(target_obj.target)
+ build['targets'] = ' '.join(targets)
+
+ # abbreviated form of the full target list
+ abbreviated_targets = ''
+ num_targets = len(targets)
+ if num_targets > 0:
+ abbreviated_targets = targets[0]
+ if num_targets > 1:
+ abbreviated_targets += (' +%s' % (num_targets - 1))
+ build['targets_abbreviated'] = abbreviated_targets
+
+ recent_builds.append(build)
+
+ return JsonResponse(recent_builds, safe=False)