Skip to content

Commit e85114c

Browse files
committed
Merge pull request tobami#172 from nomeata/submit
Two more changes
2 parents 0f16149 + 8eda931 commit e85114c

10 files changed

Lines changed: 204 additions & 93 deletions

File tree

codespeed/feeds.py

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,45 @@
11
from django.contrib.syndication.views import Feed
22
from codespeed.models import Report
33
from django.conf import settings
4+
from django.db.models import Q
45

5-
6-
class LatestEntries(Feed):
6+
class ResultFeed(Feed):
77
title = settings.WEBSITE_NAME
88
link = "/changes/"
9-
description = "Last benchmark runs"
109

1110
def items(self):
12-
return Report.objects.filter(
13-
revision__branch__name=settings.DEF_BRANCH
14-
).order_by('-revision__date')[:10]
11+
return Report.objects\
12+
.filter(self.result_filter())\
13+
.order_by('-revision__date')[:10]
14+
15+
def item_title(self, item):
16+
return "%s: %s" % (item.revision.get_short_commitid(), item.item_description())
17+
18+
description_template = "codespeed/changes_table.html"
19+
20+
def get_context_data(self, **kwargs):
21+
report = kwargs['item']
22+
trendconfig = settings.TREND
23+
24+
tablelist = report.get_changes_table(trendconfig)
25+
26+
return {
27+
'tablelist': tablelist,
28+
'trendconfig': trendconfig,
29+
'rev': report.revision,
30+
'exe': report.executable,
31+
'env': report.environment,
32+
}
33+
34+
class LatestEntries(ResultFeed):
35+
description = "Last benchmark runs"
36+
37+
def result_filter(self):
38+
return Q(revision__branch__name=settings.DEF_BRANCH)
39+
40+
class LatestSignificantEntries(ResultFeed):
41+
description = "Last benchmark runs with significant changes"
42+
43+
def result_filter(self):
44+
return Q(revision__branch__name=settings.DEF_BRANCH,
45+
colorcode__in = ('red','green'))

codespeed/models.py

Lines changed: 57 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -265,43 +265,55 @@ def save(self, *args, **kwargs):
265265
self.colorcode = "none"
266266

267267
# Save summary in order of priority
268+
# (changes results before trends, averages before individual results)
269+
268270
# Average change
269271
if average_change_color != "none":
270-
#Substitute plus/minus with up/down
271-
direction = average_change >= 0 and "+" or "-"
272-
self.summary = "Average %s %s%.1f%%" % (
272+
self.summary = "Average %s %s" % (
273273
average_change_units.lower(),
274-
direction,
275-
round(abs(average_change), 1))
274+
self.updown(average_change))
276275
self.colorcode = average_change_color
276+
277277
# Single benchmark change
278-
if max_change_color != "none" and self.colorcode != "red":
279-
#Substitute plus/minus with up/down
280-
direction = max_change >= 0 and "+" or "-"
281-
self.summary = "%s %s%.1f%%" % (
282-
max_change_ben, direction, round(abs(max_change), 1))
278+
elif max_change_color != "none":
279+
self.summary = "%s %s" % (
280+
max_change_ben,
281+
self.updown(max_change))
283282
self.colorcode = max_change_color
284283

285284
# Average trend
286-
if average_trend_color != "none" and self.colorcode == "none":
287-
#Substitute plus/minus with up/down
288-
direction = average_trend >= 0 and "+" or ""
289-
self.summary = "Average %s trend %s%.1f%%" % (
290-
average_trend_units.lower(), direction, round(average_trend, 1))
291-
self.colorcode = average_trend_color == "red"\
292-
and "yellow" or average_trend_color
285+
elif average_trend_color != "none":
286+
self.summary = "Average %s trend %s" % (
287+
average_trend_units.lower(),
288+
self.updown(average_trend))
289+
# use lighter colors for trend results:
290+
if average_trend_color == "red":
291+
self.colorcode = "yellow"
292+
elif average_trend_color == "green":
293+
self.colorcode = "lightgreen"
294+
293295
# Single benchmark trend
294-
if max_trend_color != "none" and self.colorcode != "red":
295-
if (self.colorcode == "none" or
296-
(self.colorcode == "green" and "trend" not in self.summary)):
297-
direction = max_trend >= 0 and "+" or ""
298-
self.summary = "%s trend %s%.1f%%" % (
299-
max_trend_ben, direction, round(max_trend, 1))
300-
self.colorcode = max_trend_color == "red"\
301-
and "yellow" or max_trend_color
296+
elif max_trend_color != "none":
297+
self.summary = "%s trend %s" % (
298+
max_trend_ben,
299+
self.updown(max_trend))
300+
# use lighter colors for trend results:
301+
if max_trend_color == "red":
302+
self.colorcode = "yellow"
303+
elif max_trend_color == "green":
304+
self.colorcode = "lightgreen"
302305

303306
super(Report, self).save(*args, **kwargs)
304307

308+
def updown(self,val):
309+
#Substitute plus/minus with up/down
310+
direction = val >= 0 and "up" or "down"
311+
aval = abs(val)
312+
if aval == float("inf"):
313+
return u"%s ∞%%" % direction
314+
else:
315+
return "%s %.1f%%" % (direction, aval)
316+
305317
def is_big_change(self, val, color, current_val, current_color):
306318
if color == "red" and current_color != "red":
307319
return True
@@ -316,12 +328,12 @@ def is_big_change(self, val, color, current_val, current_color):
316328
def getcolorcode(self, val, lessisbetter, threshold):
317329
if lessisbetter:
318330
val = -val
319-
colorcode = "none"
320331
if val < -threshold:
321-
colorcode = "red"
332+
return "red"
322333
elif val > threshold:
323-
colorcode = "green"
324-
return colorcode
334+
return "green"
335+
else:
336+
return "none"
325337

326338
def get_changes_table(self, trend_depth=10, force_save=False):
327339
# Determine whether required trend value is the default one
@@ -406,9 +418,22 @@ def get_changes_table(self, trend_depth=10, force_save=False):
406418
change = "-"
407419
if len(change_list):
408420
c = change_list.filter(benchmark=bench)
409-
if c.count() and c[0].value and result:
410-
change = (result - c[0].value) * 100 / c[0].value
411-
totals['change'].append(result / c[0].value)
421+
if c.count() and result is not None:
422+
if c[0].value != 0:
423+
change = (result - c[0].value) * 100 / c[0].value
424+
totals['change'].append(result / c[0].value)
425+
elif c[0].value == 0:
426+
if result == 0:
427+
# 0/0 = 1, in our world
428+
change = 0
429+
totals['change'].append(1)
430+
else:
431+
# n/0 = ∞
432+
change = float("inf")
433+
totals['change'].append(float("inf"))
434+
else:
435+
# no previous result, no change available
436+
pass
412437

413438
# Calculate trend:
414439
# percentage change relative to average of 3 previous results

codespeed/static/css/main.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,10 @@ table.tablesorter, table.info, table.revision, table.reports {
285285
background-color: #fafafa;
286286
}
287287

288+
table.reports {
289+
margin-bottom: 2em
290+
}
291+
288292
/*table.reports {
289293
border-width: 2px;
290294
}*/
@@ -354,6 +358,8 @@ table.tablesorter tbody tr td.status-green, td.status-green { background-color:
354358
tr.status-green td.summary { color: #9FD54D; font-weight: bold; }
355359
table.tablesorter tbody tr td.status-yellow, td.status-yellow { background-color: #FFD843; }
356360
tr.status-yellow td.summary { color: #FFD843; font-weight: bold; }
361+
table.tablesorter tbody tr td.status-lightgreen, td.status-lightgreen { background-color: #c2e927; }
362+
tr.status-lightgreen td.summary { color: #c2e927; font-weight: bold; }
357363

358364
table.tablesorter tbody tr.highlight td, tr.highlight td {
359365
background-color: #9DADC6 !important;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<div class="leftcolumn">
2+
{% include 'codespeed/changes_table.html' %}
3+
</div>
4+
5+
<div class="rightcolumn">
6+
<table class="revision">
7+
<col/>
8+
<col/>
9+
<thead>
10+
<tr>
11+
<th colspan="2">Revision</th>
12+
</tr>
13+
</thead>
14+
<tbody>
15+
<tr class="commit-id">
16+
<th class="infofirst">Commit</th>
17+
<td>{% if rev.get_browsing_url %}<a href="{{ rev.get_browsing_url }}">{{ rev.commitid }}</a>{% else %}{{ rev.commitid }}{% endif %}</td>
18+
</tr>
19+
<tr class="date"><th class="infofirst">Date</td><td>{{ rev.date }}</td></tr>
20+
{% ifnotequal rev.branch.project.repo_type "N" %}
21+
<tr class="repo-path"><th class="infofirst">Repo</th><td>{{ rev.branch.project.repo_path }}</td></tr>
22+
{% endifnotequal %}
23+
</tbody>
24+
</table>
25+
26+
{% ifnotequal exe.project.repo_type 'N' %}
27+
<table class="revision">
28+
<col/>
29+
<col/>
30+
<thead class="commits">
31+
<tr>
32+
<th colspan="2">Commit logs</th>
33+
</tr>
34+
</thead>
35+
<tbody class="commits" data-commitid="{{ rev.id }}">
36+
<tr><td colspan="2" style="text-align:center;">Loading... <img src="{{ STATIC_URL}}images/ajax-loader.gif" align="bottom"></td></tr>
37+
</tbody>
38+
<script type="text/javascript">
39+
var el = $("tbody.commits");
40+
el.load("logs/", "revisionid=" + el.data("commitid"));
41+
</script>
42+
</table>
43+
{% endifnotequal %}
44+
</div>
Lines changed: 6 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
<div class="leftcolumn">
1+
{% load percentages %}
2+
23
{% for units in tablelist %}
34
<table class="tablesorter" data-lessisbetter="{{ units.lessisbetter }}">
45
<thead>
@@ -13,25 +14,25 @@
1314
</tr>
1415
</thead>
1516
<tfoot>
16-
<tr data-change="{{ units.totals.change }}" data-trend="{{ units.totals.trend }}">
17+
<tr data-change="{{ units.totals.change|fix_infinity }}" data-trend="{{ units.totals.trend|fix_infinity }}">
1718
<td title="Arithmetic mean">Average</td>
1819
<td></td>
1920
{% if units.hasmin %}<td></td>
2021
{% endif%}{% if units.has_stddev %}<td>{{ units.totals.min }}</td>
2122
{% endif%}{% if units.hasmax %}<td>{{ units.totals.max }}</td>
22-
{% endif%}<td>{% ifnotequal units.totals.change "-" %}{{ units.totals.change|floatformat:2 }}%{% else %}{{ units.totals.change }}{% endifnotequal %}</td>
23+
{% endif%}<td>{{ units.totals.change|percentage }}</td>
2324
<td>{% ifnotequal units.totals.trend "-" %}{{ units.totals.trend|floatformat:2 }}%{% else %}{{ units.totals.trend }}{% endifnotequal %}</td>
2425
</tr>
2526
</tfoot>
2627
<tbody>
2728
{% for row in units.rows|dictsort:"bench_name" %}
28-
<tr data-change="{{ row.change }}" data-trend="{{ row.trend }}">
29+
<tr data-change="{{ row.change|fix_infinity }}" data-trend="{{ row.trend|fix_infinity }}">
2930
<td title="{{ row.bench_description }}">{{ row.bench_name }}</td>
3031
<td>{{ row.result|floatformat:units.precission }}</td>
3132
{% if units.has_stddev %}<td>{{ row.std_dev|floatformat:units.precission }}</td>
3233
{% endif%}{% if units.hasmin %}<td>{{ row.val_min|floatformat:units.precission }}</td>
3334
{% endif%}{% if units.hasmax %}<td>{{ row.val_max|floatformat:units.precission }}</td>
34-
{% endif%}<td>{% ifequal row.change "-" %}-{% else %}{{ row.change|floatformat:2 }}%{% endifequal %}</td>
35+
{% endif%}<td>{{ row.change|percentage }}</td>
3536
<td>{% ifequal row.trend "-" %}-{% else %}{{ row.trend|floatformat:2 }}%{% endifequal %}</td>
3637
</tr>{% endfor %}
3738
</tbody>
@@ -62,45 +63,3 @@
6263
<tr><td class="infofirst">Kernel</td><td>{{ env.kernel }}</td></tr>
6364
</tbody>
6465
</table>
65-
</div>
66-
67-
<div class="rightcolumn">
68-
<table class="revision">
69-
<col/>
70-
<col/>
71-
<thead>
72-
<tr>
73-
<th colspan="2">Revision</th>
74-
</tr>
75-
</thead>
76-
<tbody>
77-
<tr class="commit-id">
78-
<th class="infofirst">Commit</th>
79-
<td>{% if rev.get_browsing_url %}<a href="{{ rev.get_browsing_url }}">{{ rev.commitid }}</a>{% else %}{{ rev.commitid }}{% endif %}</td>
80-
</tr>
81-
<tr class="date"><th class="infofirst">Date</td><td>{{ rev.date }}</td></tr>
82-
{% ifnotequal rev.branch.project.repo_type "N" %}
83-
<tr class="repo-path"><th class="infofirst">Repo</th><td>{{ rev.branch.project.repo_path }}</td></tr>
84-
{% endifnotequal %}
85-
</tbody>
86-
</table>
87-
88-
{% ifnotequal exe.project.repo_type 'N' %}
89-
<table class="revision">
90-
<col/>
91-
<col/>
92-
<thead class="commits">
93-
<tr>
94-
<th colspan="2">Commit logs</th>
95-
</tr>
96-
</thead>
97-
<tbody class="commits" data-commitid="{{ rev.id }}">
98-
<tr><td colspan="2" style="text-align:center;">Loading... <img src="{{ STATIC_URL}}images/ajax-loader.gif" align="bottom"></td></tr>
99-
</tbody>
100-
<script type="text/javascript">
101-
var el = $("tbody.commits");
102-
el.load("logs/", "revisionid=" + el.data("commitid"));
103-
</script>
104-
</table>
105-
{% endifnotequal %}
106-
</div>

codespeed/templates/codespeed/reports.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,15 @@
99
</tbody>
1010
</table>
1111
{% endif %}
12+
13+
{% if significant_reports|length %}
14+
<table class="reports">
15+
<caption>Latest Significant Results <a href="feeds/latest_significant/"><img src="{{ STATIC_URL }}images/rss.png" alt="RSS feed" title="Subscribe to the significant results RSS feed" /></a></caption>
16+
<tbody>
17+
{% for report in significant_reports %} <tr class="status-{{ report.colorcode }}">
18+
<td><label title="lessisbetter" style="display:none;">{{ report.get_absolute_url }}</label>{{ report.revision }}</td><td>{{ report.executable }}@{{ report.environment}}</td>
19+
<td class="summary">{{ report.item_description }}</td>
20+
</tr>{% endfor %}
21+
</tbody>
22+
</table>
23+
{% endif %}

codespeed/templatetags/__init__.py

Whitespace-only changes.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from django import template
4+
5+
register = template.Library()
6+
7+
@register.filter
8+
def percentage(value):
9+
if value == "-":
10+
return "-"
11+
elif value == float("inf"):
12+
return "+∞%"
13+
else:
14+
return "%.2f" % value
15+
16+
@register.filter
17+
def fix_infinity(value):
18+
'''Python’s ∞ prints "inf", but JavaScript wants "Infinity"'''
19+
if value == float("inf"):
20+
return "Infinity"
21+
elif value == float("-inf"):
22+
return "-Infinity"
23+
else:
24+
return value

codespeed/urls.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
from django.core.urlresolvers import reverse
44
from django.views.generic import TemplateView
55

6-
from codespeed.feeds import LatestEntries
6+
from codespeed.feeds import LatestEntries, LatestSignificantEntries
77

8-
feeds = {'latest': LatestEntries}
98

109
urlpatterns = patterns('',
1110
(r'^$', TemplateView.as_view(template_name='home.html')),
1211
(r'^about/$', TemplateView.as_view(template_name='about.html')),
1312
# RSS for reports
14-
(r'^feeds/(?P<url>.*)/$', LatestEntries()),
13+
url(r'^feeds/latest/$', LatestEntries(), name='latest_feeds'),
14+
url(r'^feeds/latest_significant/$', LatestSignificantEntries(), name='latest_significant_feeds'),
1515
)
1616

1717
urlpatterns += patterns('codespeed.views',

0 commit comments

Comments
 (0)