Merge lp:~mwhudson/lava-dashboard/use-tables-code into lp:lava-dashboard

Proposed by Michael Hudson-Doyle
Status: Merged
Merged at revision: 307
Proposed branch: lp:~mwhudson/lava-dashboard/use-tables-code
Merge into: lp:lava-dashboard
Diff against target: 549 lines (+237/-143)
6 files modified
dashboard_app/templates/dashboard_app/bundle_list.html (+6/-41)
dashboard_app/templates/dashboard_app/bundle_stream_list.html (+5/-29)
dashboard_app/templates/dashboard_app/test_run_detail.html (+5/-34)
dashboard_app/templates/dashboard_app/test_run_list.html (+3/-1)
dashboard_app/urls.py (+4/-0)
dashboard_app/views.py (+214/-38)
To merge this branch: bzr merge lp:~mwhudson/lava-dashboard/use-tables-code
Reviewer Review Type Date Requested Status
Zygmunt Krynicki (community) Approve
Review via email: mp+97795@code.launchpad.net

Description of the change

This branch converts a pretty arbitrary selection of the tables in the dispatcher over to ajax tables.

To post a comment you must log in.
Revision history for this message
Zygmunt Krynicki (zyga) wrote :

529 + print test_run

Stray debug?

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

+1

review: Approve
312. By Michael Hudson-Doyle

remove print

313. By Michael Hudson-Doyle

merge trunk

314. By Michael Hudson-Doyle

changes

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'dashboard_app/templates/dashboard_app/bundle_list.html'
2--- dashboard_app/templates/dashboard_app/bundle_list.html 2011-12-15 16:13:43 +0000
3+++ dashboard_app/templates/dashboard_app/bundle_list.html 2012-03-20 21:23:20 +0000
4@@ -1,4 +1,6 @@
5 {% extends "dashboard_app/_content_with_sidebar.html" %}
6+
7+{% load django_tables2 %}
8 {% load i18n %}
9 {% load humanize %}
10
11@@ -32,14 +34,6 @@
12 </div>
13 <script type="text/javascript" charset="utf-8">
14 $(document).ready(function() {
15- oTable = $('#bundles').dataTable({
16- bJQueryUI: true,
17- sPaginationType: "full_numbers",
18- aaSorting: [[4, "desc"]],
19- iDisplayLength: 25,
20- aLengthMenu: [[10, 25, 50, -1], [10, 25, 50, "All"]],
21- sDom: 'lfr<"#master-toolbar">t<"F"ip>'
22- });
23 // Try hard to make our radio boxes behave as links
24 $("#master-toolbar-splice span.view-as").buttonset();
25 $("#master-toolbar-splice span.view-as input").change(function(event) {
26@@ -56,39 +50,10 @@
27 $("#master-toolbar").addClass("ui-widget-header ui-corner-tl ui-corner-tr").css(
28 "padding", "5pt").css("text-align", "center");
29 });
30-</script>
31-<table class="demo_jui display" id="bundles">
32- <thead>
33- <tr>
34- <th>{% trans "Bundle Name" %}</th>
35- <th>{% trans "Passes" %}</th>
36- <th>{% trans "Fails " %}</th>
37- <th>{% trans "Total Results" %}</th>
38- <th>{% trans "Uploaded On" %}</th>
39- <th>{% trans "Uploaded By" %}</th>
40- <th>{% trans "Deserialized?" %}</th>
41- </tr>
42- </thead>
43- <tbody>
44- {% for bundle in bundle_list %}
45- <tr>
46- <td><a href="{{ bundle.get_absolute_url }}"><code>{{ bundle.content_filename }}</code></a></td>
47- <td>{{ bundle.get_summary_results.pass }}</td>
48- <td>{{ bundle.get_summary_results.fail }}</td>
49- <td>{{ bundle.get_summary_results.total }}</td>
50- <td>{{ bundle.uploaded_on|date:"Y-m-d H:i:s"}}</td>
51- <td>
52- {% if bundle.uploaded_by %}
53- {{ bundle.uploaded_by }}
54- {% else %}
55- <em>{% trans "anonymous user" %}</em>
56- {% endif %}
57- </td>
58- <td>{{ bundle.is_deserialized|yesno }}</td>
59- </tr>
60- {% endfor %}
61- </tbody>
62-</table>
63+</script>
64+
65+{% render_table bundle_table %}
66+
67 {% endblock %}
68
69
70
71=== modified file 'dashboard_app/templates/dashboard_app/bundle_stream_list.html'
72--- dashboard_app/templates/dashboard_app/bundle_stream_list.html 2011-07-12 02:34:12 +0000
73+++ dashboard_app/templates/dashboard_app/bundle_stream_list.html 2012-03-20 21:23:20 +0000
74@@ -1,38 +1,14 @@
75 {% extends "dashboard_app/_content_with_sidebar.html" %}
76+
77+{% load django_tables2 %}
78 {% load i18n %}
79 {% load pagination_tags %}
80
81
82 {% block content %}
83-<script type="text/javascript" charset="utf-8">
84- $(document).ready(function() {
85- oTable = $('#bundle_streams').dataTable({
86- bJQueryUI: true,
87- sPaginationType: "full_numbers",
88- iDisplayLength: 25,
89- });
90- });
91-</script>
92-<table class="demo_jui display" id="bundle_streams">
93- <thead>
94- <tr>
95- <th width="50%">Pathname</th>
96- <th>Name</th>
97- <th>Number of test runs</th>
98- <th>Number of bundles</th>
99- </tr>
100- </thead>
101- <tbody>
102- {% for bundle_stream in bundle_stream_list %}
103- <tr>
104- <td style="vertical-align: top;"><a href="{% url dashboard_app.views.bundle_list bundle_stream.pathname %}"><code>{{ bundle_stream.pathname }}</code></a></td>
105- <td>{{ bundle_stream.name|default:"<i>not set</i>" }}</td>
106- <td style="vertical-align: top;"><a href="{% url dashboard_app.views.test_run_list bundle_stream.pathname %}">{{ bundle_stream.get_test_run_count }}</a></td>
107- <td style="vertical-align: top;"><a href="{% url dashboard_app.views.bundle_list bundle_stream.pathname %}">{{ bundle_stream.bundles.count}}</a></td>
108- </tr>
109- {% endfor %}
110- </tbody>
111-</table>
112+
113+{% render_table bundle_stream_table %}
114+
115 {% endblock %}
116
117
118
119=== modified file 'dashboard_app/templates/dashboard_app/test_run_detail.html'
120--- dashboard_app/templates/dashboard_app/test_run_detail.html 2011-09-27 20:58:16 +0000
121+++ dashboard_app/templates/dashboard_app/test_run_detail.html 2012-03-20 21:23:20 +0000
122@@ -1,43 +1,14 @@
123 {% extends "dashboard_app/_content_with_sidebar.html" %}
124+
125+{% load django_tables2 %}
126 {% load i18n %}
127 {% load humanize %}
128
129
130 {% block content %}
131-<script type="text/javascript" charset="utf-8">
132- $(document).ready(function() {
133- oTable = $('#test_results').dataTable({
134- "bJQueryUI": true,
135- "sPaginationType": "full_numbers",
136- "aaSorting": [[0, "asc"]],
137- });
138- });
139-</script>
140-<table class="demo_jui display" id="test_results">
141- <thead>
142- <tr>
143- <th>#</th>
144- <th>{% trans "Test case" %}</th>
145- <th>{% trans "Result" %}</th>
146- <th>{% trans "Measurement" %}</th>
147- </tr>
148- </thead>
149- <tbody>
150- {% for test_result in test_run.get_results %}
151- <tr>
152- <td width="1%">{{ test_result.relative_index }}</td>
153- <td>{{ test_result.test_case|default_if_none:"<em>Not specified</em>" }}</td>
154- <td>
155- <a href ="{{test_result.get_absolute_url}}">
156- <img src="{{ STATIC_URL }}dashboard_app/images/icon-{{ test_result.result_code }}.png"
157- alt="{{ test_result.get_result_display }}" width="16" height="16" border="0"/></a>
158- <a href ="{{test_result.get_absolute_url}}">{{ test_result.get_result_display }}</a>
159- </td>
160- <td>{{ test_result.measurement|default_if_none:"Not specified" }} {{ test_result.units }}</td>
161- </tr>
162- {% endfor %}
163- </tbody>
164-</table>
165+
166+{% render_table test_table %}
167+
168 {% endblock %}
169
170
171
172=== modified file 'dashboard_app/templates/dashboard_app/test_run_list.html'
173--- dashboard_app/templates/dashboard_app/test_run_list.html 2011-09-27 21:26:42 +0000
174+++ dashboard_app/templates/dashboard_app/test_run_list.html 2012-03-20 21:23:20 +0000
175@@ -1,4 +1,6 @@
176 {% extends "dashboard_app/_content_with_sidebar.html" %}
177+
178+{% load django_tables2 %}
179 {% load i18n %}
180 {% load humanize %}
181
182@@ -55,7 +57,7 @@
183 "padding", "5pt").css("text-align", "center");
184 });
185 </script>
186-{% include "dashboard_app/_test_run_list_table.html" %}
187+{% render_table test_run_table %}
188 {% endblock %}
189
190
191
192=== modified file 'dashboard_app/urls.py'
193--- dashboard_app/urls.py 2011-10-06 12:03:00 +0000
194+++ dashboard_app/urls.py 2012-03-20 21:23:20 +0000
195@@ -46,16 +46,20 @@
196 'mapper': legacy_mapper,
197 'template_name': 'dashboard_app/api.html'}),
198 url(r'^streams/$', 'bundle_stream_list'),
199+ url(r'^streams/json$', 'bundle_stream_list_json'),
200 url(r'^streams(?P<pathname>/[a-zA-Z0-9/._-]+)bundles/$', 'bundle_list'),
201+ url(r'^streams(?P<pathname>/[a-zA-Z0-9/._-]+)bundles/json$', 'bundle_list_table_json'),
202 url(r'^streams(?P<pathname>/[a-zA-Z0-9/._-]+)bundles/(?P<content_sha1>[0-9a-z]+)/$', 'bundle_detail'),
203 url(r'^streams(?P<pathname>/[a-zA-Z0-9/._-]+)bundles/(?P<content_sha1>[0-9a-z]+)/json$', 'bundle_json'),
204 url(r'^streams(?P<pathname>/[a-zA-Z0-9/._-]+)bundles/(?P<content_sha1>[0-9a-z]+)/(?P<analyzer_assigned_uuid>[a-zA-Z0-9-]+)/$', 'test_run_detail'),
205+ url(r'^streams(?P<pathname>/[a-zA-Z0-9/._-]+)bundles/(?P<content_sha1>[0-9a-z]+)/(?P<analyzer_assigned_uuid>[a-zA-Z0-9-]+)/json$', 'test_run_detail_test_json'),
206 url(r'^streams(?P<pathname>/[a-zA-Z0-9/._-]+)bundles/(?P<content_sha1>[0-9a-z]+)/(?P<analyzer_assigned_uuid>[a-zA-Z0-9-]+)/attachments$', 'attachment_list'),
207 url(r'^streams(?P<pathname>/[a-zA-Z0-9/._-]+)bundles/(?P<content_sha1>[0-9a-z]+)/(?P<analyzer_assigned_uuid>[a-zA-Z0-9-]+)/attachments/(?P<pk>[0-9]+)/$', 'attachment_detail'),
208 url(r'^streams(?P<pathname>/[a-zA-Z0-9/._-]+)bundles/(?P<content_sha1>[0-9a-z]+)/(?P<analyzer_assigned_uuid>[a-zA-Z0-9-]+)/result/(?P<relative_index>[0-9]+)/$', 'test_result_detail'),
209 url(r'^streams(?P<pathname>/[a-zA-Z0-9/._-]+)bundles/(?P<content_sha1>[0-9a-z]+)/(?P<analyzer_assigned_uuid>[a-zA-Z0-9-]+)/hardware-context/$', 'test_run_hardware_context'),
210 url(r'^streams(?P<pathname>/[a-zA-Z0-9/._-]+)bundles/(?P<content_sha1>[0-9a-z]+)/(?P<analyzer_assigned_uuid>[a-zA-Z0-9-]+)/software-context/$', 'test_run_software_context'),
211 url(r'^streams(?P<pathname>/[a-zA-Z0-9/._-]+)test-runs/$', 'test_run_list'),
212+ url(r'^streams(?P<pathname>/[a-zA-Z0-9/._-]+)test-runs/json$', 'test_run_list_json'),
213 url(r'^permalink/test-run/(?P<analyzer_assigned_uuid>[a-zA-Z0-9-]+)/$', 'redirect_to_test_run'),
214 url(r'^permalink/test-run/(?P<analyzer_assigned_uuid>[a-zA-Z0-9-]+)/(?P<trailing>.*)$', 'redirect_to_test_run'),
215 url(r'^permalink/test-result/(?P<analyzer_assigned_uuid>[a-zA-Z0-9-]+)/(?P<relative_index>[0-9]+)/$', 'redirect_to_test_result'),
216
217=== modified file 'dashboard_app/views.py'
218--- dashboard_app/views.py 2011-12-15 16:13:43 +0000
219+++ dashboard_app/views.py 2012-03-20 21:23:20 +0000
220@@ -25,14 +25,24 @@
221
222 from django.contrib.auth.decorators import login_required
223 from django.contrib.sites.models import Site
224+from django.core.urlresolvers import reverse
225 from django.db.models.manager import Manager
226 from django.db.models.query import QuerySet
227 from django.http import Http404, HttpResponse, HttpResponseRedirect
228 from django.shortcuts import render_to_response, redirect, get_object_or_404
229 from django.template import RequestContext, loader
230-from django.views.generic.create_update import create_object
231+from django.utils.safestring import mark_safe
232 from django.views.generic.list_detail import object_list, object_detail
233
234+from django_tables2 import Attrs, Column, TemplateColumn
235+
236+from lava.utils.data_tables.tables import DataTablesTable
237+from lava_server.views import index as lava_index
238+from lava_server.bread_crumbs import (
239+ BreadCrumb,
240+ BreadCrumbTrail,
241+)
242+
243 from dashboard_app.models import (
244 Attachment,
245 Bundle,
246@@ -46,11 +56,6 @@
247 TestRun,
248 TestingEffort,
249 )
250-from lava_server.views import index as lava_index
251-from lava_server.bread_crumbs import (
252- BreadCrumb,
253- BreadCrumbTrail,
254-)
255
256
257 def _get_queryset(klass):
258@@ -99,6 +104,37 @@
259 }, RequestContext(request))
260
261
262+
263+
264+class BundleStreamTable(DataTablesTable):
265+
266+ pathname = TemplateColumn(
267+ '<a href="{% url dashboard_app.views.bundle_list record.pathname %}">'
268+ '<code>{{ record.pathname }}</code></a>')
269+ name = TemplateColumn(
270+ '{{ record.name|default:"<i>not set</i>" }}')
271+ number_of_test_runs = TemplateColumn(
272+ '<a href="{% url dashboard_app.views.test_run_list record.pathname %}">'
273+ '{{ record.get_test_run_count }}')
274+ number_of_bundles = TemplateColumn(
275+ '<a href="{% url dashboard_app.views.bundle_list record.pathname %}">'
276+ '{{ record.bundles.count}}</a>')
277+
278+ def get_queryset(self, user):
279+ return BundleStream.objects.accessible_by_principal(user)
280+
281+ datatable_opts = {
282+ 'iDisplayLength': 25,
283+ 'sPaginationType': "full_numbers",
284+ }
285+
286+ searchable_columns = ['pathname', 'name']
287+
288+
289+def bundle_stream_list_json(request):
290+ return BundleStreamTable.json(request, params=(request.user,))
291+
292+
293 @BreadCrumb("Bundle Streams", parent=index)
294 def bundle_stream_list(request):
295 """
296@@ -108,7 +144,9 @@
297 'dashboard_app/bundle_stream_list.html', {
298 'bread_crumb_trail': BreadCrumbTrail.leading_to(
299 bundle_stream_list),
300- "bundle_stream_list": BundleStream.objects.accessible_by_principal(request.user).order_by('pathname'),
301+ "bundle_stream_table": BundleStreamTable(
302+ 'bundle-stream-table', reverse(bundle_stream_list_json),
303+ params=(request.user,)),
304 'has_personal_streams': (
305 request.user.is_authenticated() and
306 BundleStream.objects.filter(user=request.user).count() > 0),
307@@ -120,6 +158,52 @@
308 )
309
310
311+class BundleTable(DataTablesTable):
312+
313+ content_filename = TemplateColumn(
314+ '<a href="{{ record.get_absolute_url }}">'
315+ '<code>{{ record.content_filename }}</code></a>',
316+ verbose_name="bundle name")
317+
318+ passes = TemplateColumn('{{ record.get_summary_results.pass }}')
319+ fails = TemplateColumn('{{ record.get_summary_results.pass }}')
320+ total_results = TemplateColumn('{{ record.get_summary_results.total }}')
321+
322+ uploaded_on = TemplateColumn('{{ record.uploaded_on|date:"Y-m-d H:i:s"}}')
323+ uploaded_by = TemplateColumn('''
324+ {% load i18n %}
325+ {% if record.uploaded_by %}
326+ {{ record.uploaded_by }}
327+ {% else %}
328+ <em>{% trans "anonymous user" %}</em>
329+ {% endif %}''')
330+ deserializaled = TemplateColumn('{{ record.is_deserialized|yesno }}')
331+
332+ def get_queryset(self, bundle_stream):
333+ return bundle_stream.bundles.select_related(
334+ 'bundle_stream', 'deserialization_error')
335+
336+ datatable_opts = {
337+ 'aaSorting': [[4, 'desc']],
338+ 'sPaginationType': 'full_numbers',
339+ 'iDisplayLength': 25,
340+# 'aLengthMenu': [[10, 25, 50, -1], [10, 25, 50, "All"]],
341+ 'sDom': 'lfr<"#master-toolbar">t<"F"ip>',
342+ }
343+
344+ searchable_columns = ['content_filename']
345+
346+
347+def bundle_list_table_json(request, pathname):
348+ bundle_stream = get_restricted_object_or_404(
349+ BundleStream,
350+ lambda bundle_stream: bundle_stream,
351+ request.user,
352+ pathname=pathname
353+ )
354+ return BundleTable.json(request, params=(bundle_stream,))
355+
356+
357 @BreadCrumb(
358 "Bundles in {pathname}",
359 parent=bundle_stream_list,
360@@ -134,18 +218,20 @@
361 request.user,
362 pathname=pathname
363 )
364- return object_list(
365- request,
366- queryset=bundle_stream.bundles.select_related(
367- 'bundle_stream', 'deserialization_error'),
368- template_name="dashboard_app/bundle_list.html",
369- template_object_name="bundle",
370- extra_context={
371+ return render_to_response(
372+ "dashboard_app/bundle_list.html",
373+ {
374+ 'bundle_table': BundleTable(
375+ 'bundle-table',
376+ reverse(
377+ bundle_list_table_json, kwargs=dict(pathname=pathname)),
378+ params=(bundle_stream,)),
379 'bread_crumb_trail': BreadCrumbTrail.leading_to(
380 bundle_list,
381 pathname=pathname),
382 "bundle_stream": bundle_stream
383- })
384+ },
385+ RequestContext(request))
386
387
388 @BreadCrumb(
389@@ -229,28 +315,28 @@
390 RequestContext(request))
391
392
393-@BreadCrumb(
394- "Test runs in {pathname}",
395- parent=bundle_stream_list,
396- needs=['pathname'])
397-def test_run_list(request, pathname):
398- """
399- List of test runs in a specified bundle stream.
400- """
401- bundle_stream = get_restricted_object_or_404(
402- BundleStream,
403- lambda bundle_stream: bundle_stream,
404- request.user,
405- pathname=pathname
406- )
407- return render_to_response(
408- 'dashboard_app/test_run_list.html', {
409- 'bread_crumb_trail': BreadCrumbTrail.leading_to(
410- test_run_list,
411- pathname=pathname),
412- "test_run_list": TestRun.objects.filter(
413+class TestRunTable(DataTablesTable):
414+
415+ record = TemplateColumn(
416+ '<a href="{{ record.get_absolute_url }}">'
417+ '<code>{{ record.test }} results<code/></a>',
418+ accessor="test__test_id",
419+ )
420+
421+ test = TemplateColumn(
422+ '<a href="{{ record.test.get_absolute_url }}">{{ record.test }}</a>',
423+ accessor="test__test_id",
424+ )
425+
426+ uploaded_on = TemplateColumn(
427+ '{{ record.bundle.uploaded_on|date:"Y-m-d H:i:s" }}')
428+
429+ analyzed_on = TemplateColumn(
430+ '{{ record.analyzer_assigned_date|date:"Y-m-d H:i:s" }}')
431+
432+ def get_queryset(self, bundle_stream):
433+ return TestRun.objects.filter(
434 bundle__bundle_stream=bundle_stream
435- ).order_by( # clean any implicit ordering
436 ).select_related(
437 "test",
438 "bundle",
439@@ -264,12 +350,94 @@
440 "bundle__bundle_stream__pathname", # Needed by TestRun.get_absolute_url
441 "test__name", # needed by Test.__unicode__
442 "test__test_id", # needed by Test.__unicode__
443- ),
444+ )
445+
446+ datatable_opts = {
447+ "sPaginationType": "full_numbers",
448+ "aaSorting": [[1, "desc"]],
449+ "iDisplayLength": 25,
450+ "sDom": 'lfr<"#master-toolbar">t<"F"ip>'
451+ }
452+
453+ searchable_columns = ['test__test_id']
454+
455+
456+def test_run_list_json(request, pathname):
457+ bundle_stream = get_restricted_object_or_404(
458+ BundleStream,
459+ lambda bundle_stream: bundle_stream,
460+ request.user,
461+ pathname=pathname
462+ )
463+ return TestRunTable.json(request, params=(bundle_stream,))
464+
465+
466+@BreadCrumb(
467+ "Test runs in {pathname}",
468+ parent=bundle_stream_list,
469+ needs=['pathname'])
470+def test_run_list(request, pathname):
471+ """
472+ List of test runs in a specified bundle stream.
473+ """
474+ bundle_stream = get_restricted_object_or_404(
475+ BundleStream,
476+ lambda bundle_stream: bundle_stream,
477+ request.user,
478+ pathname=pathname
479+ )
480+ return render_to_response(
481+ 'dashboard_app/test_run_list.html', {
482+ 'bread_crumb_trail': BreadCrumbTrail.leading_to(
483+ test_run_list,
484+ pathname=pathname),
485+ "test_run_table": TestRunTable(
486+ 'test-runs',
487+ reverse(test_run_list_json, kwargs=dict(pathname=pathname)),
488+ params=(bundle_stream,)),
489 "bundle_stream": bundle_stream,
490 }, RequestContext(request)
491 )
492
493
494+class TestTable(DataTablesTable):
495+
496+ relative_index = Column(
497+ verbose_name="#", attrs=Attrs(th=dict(style="width: 1%")),
498+ default=mark_safe("<em>Not specified</em>"))
499+
500+ test_case = Column()
501+
502+ result = TemplateColumn('''
503+ <a href="{{record.get_absolute_url}}">
504+ <img src="{{ STATIC_URL }}dashboard_app/images/icon-{{ record.result_code }}.png"
505+ alt="{{ record.get_result_display }}" width="16" height="16" border="0"/></a>
506+ <a href ="{{record.get_absolute_url}}">{{ record.get_result_display }}</a>
507+ ''')
508+
509+ units = TemplateColumn(
510+ '{{ record.measurement|default_if_none:"Not specified" }} {{ record.units }}',
511+ verbose_name="measurement")
512+
513+ def get_queryset(self, test_run):
514+ return test_run.get_results()
515+
516+ datatable_opts = {
517+ 'sPaginationType': "full_numbers",
518+ }
519+
520+ searchable_columns = ['test_case__test_case_id']
521+
522+
523+def test_run_detail_test_json(request, pathname, content_sha1, analyzer_assigned_uuid):
524+ test_run = get_restricted_object_or_404(
525+ TestRun, lambda test_run: test_run.bundle.bundle_stream,
526+ request.user,
527+ analyzer_assigned_uuid=analyzer_assigned_uuid
528+ )
529+ return TestTable.json(request, params=(test_run,))
530+
531+
532 @BreadCrumb(
533 "Run {analyzer_assigned_uuid}",
534 parent=bundle_detail,
535@@ -288,7 +456,15 @@
536 pathname=pathname,
537 content_sha1=content_sha1,
538 analyzer_assigned_uuid=analyzer_assigned_uuid),
539- "test_run": test_run
540+ "test_run": test_run,
541+ "test_table": TestTable(
542+ 'test-table',
543+ reverse(test_run_detail_test_json, kwargs=dict(
544+ pathname=pathname,
545+ content_sha1=content_sha1,
546+ analyzer_assigned_uuid=analyzer_assigned_uuid)),
547+ params=(test_run,))
548+
549 }, RequestContext(request))
550
551

Subscribers

People subscribed via source and target branches

to all changes: