add static site exporter, and adjust urls to be friendlier to a flat filesystem directory
This commit is contained in:
parent
f8f7676952
commit
cd1e75fb21
98
export_static.py
Normal file
98
export_static.py
Normal file
@ -0,0 +1,98 @@
|
||||
import os
|
||||
import shutil
|
||||
import django
|
||||
|
||||
from argparse import ArgumentParser
|
||||
|
||||
from django.test import RequestFactory
|
||||
from django.core.urlresolvers import resolve
|
||||
|
||||
from stackviz.parser import tempest_subunit
|
||||
|
||||
|
||||
EXPORT_PATHS = [
|
||||
'/index.html',
|
||||
'/tempest_summary.html',
|
||||
'/tempest_aggregate.html'
|
||||
]
|
||||
|
||||
|
||||
def fake_render_view(path):
|
||||
factory = RequestFactory()
|
||||
request = factory.get(path)
|
||||
|
||||
match = resolve(path)
|
||||
response = match.func(request, *match.args, **match.kwargs)
|
||||
|
||||
if hasattr(response, "render"):
|
||||
response.render()
|
||||
|
||||
return response
|
||||
|
||||
|
||||
def export_single_page(path, dest_dir):
|
||||
dest_file = path
|
||||
if dest_file.startswith('/'):
|
||||
dest_file = dest_file[1:]
|
||||
|
||||
with open(os.path.join(dest_dir, dest_file), 'w') as f:
|
||||
content = fake_render_view(path).content
|
||||
|
||||
f.write(content)
|
||||
|
||||
|
||||
def main():
|
||||
parser = ArgumentParser(description="Generates a self-contained, static "
|
||||
"StackViz site at the given path.")
|
||||
parser.add_argument("path",
|
||||
help="The output directory. Will be created if it "
|
||||
"doesn't already exist.")
|
||||
parser.add_argument("--ignore-bower",
|
||||
help="Ignore missing Bower components.")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.ignore_bower:
|
||||
if not os.listdir(os.path.join('stackviz', 'static', 'components')):
|
||||
print "Bower components have not been installed, please run " \
|
||||
"`bower install`"
|
||||
return 1
|
||||
|
||||
if os.path.exists(args.path):
|
||||
if os.listdir(args.path):
|
||||
print "Destination exists and is not empty, cannot continue"
|
||||
return 1
|
||||
|
||||
os.mkdir(args.path)
|
||||
|
||||
print "Copying static files ..."
|
||||
shutil.copytree(os.path.join('stackviz', 'static'),
|
||||
os.path.join(args.path, 'static'))
|
||||
|
||||
for path in EXPORT_PATHS:
|
||||
print "Rendering:", path
|
||||
export_single_page(path, args.path)
|
||||
|
||||
for run_id in range(tempest_subunit.get_repositories()[0].count()):
|
||||
print "Rendering views for tempest run #%d" % run_id
|
||||
export_single_page('/tempest_timeline_%d.html' % run_id, args.path)
|
||||
export_single_page('/tempest_results_%d.html' % run_id, args.path)
|
||||
|
||||
print "Exporting data for tempest run #%d" % run_id
|
||||
export_single_page('/tempest_api_tree_%d.json' % run_id, args.path)
|
||||
export_single_page('/tempest_api_raw_%d.json' % run_id, args.path)
|
||||
|
||||
# TODO
|
||||
# export_single_page('tempest_api_details_%d.json' % run_id, args.path)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# remove leading / from static URL to give them correct filesystem paths
|
||||
import stackviz.settings as settings
|
||||
settings.STATIC_URL = settings.STATIC_URL[1:]
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "stackviz.settings")
|
||||
|
||||
django.setup()
|
||||
|
||||
main()
|
@ -71,7 +71,7 @@ function createTable(data, run) {
|
||||
tbl.setAttribute("id","table-run-" + run);
|
||||
tbl.setAttribute("class","table table-bordered table-hover table-striped");
|
||||
var header = tbl.createTHead();
|
||||
header.innerHTML = '<tr><th><a href="/tempest/timeline/' + run + '"> Run #' + run + '</a></th></tr>';
|
||||
header.innerHTML = '<tr><th><a href="tempest_timeline_' + run + '.html"> Run #' + run + '</a></th></tr>';
|
||||
for (var key in data_dict) {
|
||||
var row = tbl.insertRow();
|
||||
var c1 = row.insertCell();
|
||||
@ -92,7 +92,7 @@ function createTables(run_id) {
|
||||
//outer function so callback can use i "synchronously"
|
||||
//TODO: Sort tables when inserting so they appear in correct order
|
||||
!function(ii) {
|
||||
d3.json("/tempest/api/tree/" + i + "/", function(error, data) {
|
||||
d3.json("tempest_api_tree_" + i + ".json", function(error, data) {
|
||||
if (error) throw error;
|
||||
//create a table for the info
|
||||
createTable(data, ii);
|
||||
|
@ -77,7 +77,7 @@
|
||||
.innerRadius(function(d) { return Math.max(0, y(d.y)); })
|
||||
.outerRadius(function(d) { return Math.max(0, y(d.y + d.dy)); });
|
||||
|
||||
d3.json("/tempest/api/tree/" + run_id + "/", function(error, root) {
|
||||
d3.json("tempest_api_tree_" + run_id + ".json", function(error, root) {
|
||||
if (error) throw error;
|
||||
|
||||
displayFailingTests(root);
|
||||
|
@ -22,19 +22,19 @@
|
||||
<a href="#"><i class="fa fa-bar-chart-o fa-fw"></i> Tempest<span class="fa arrow"></span></a>
|
||||
<ul class="nav nav-second-level">
|
||||
<li>
|
||||
<a href="/tempest/summary"><i class="fa fa-bar-chart-o fa-fw"></i> Summary</a>
|
||||
<a href="tempest_summary.html"><i class="fa fa-bar-chart-o fa-fw"></i> Summary</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/tempest/results"><i class="fa fa-clock-o fa-fw"></i> Results</a>
|
||||
<a href="tempest_results_{{ tempest_latest_run }}.html"><i class="fa fa-clock-o fa-fw"></i> Results</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/tempest/timeline"><i class="fa fa-calendar fa-fw"></i> Timeline</a>
|
||||
<a href="tempest_timeline_{{ tempest_latest_run }}.html"><i class="fa fa-calendar fa-fw"></i> Timeline</a>
|
||||
</li>
|
||||
<li>
|
||||
<!--<li>
|
||||
<a href="/tempest/"><i class="fa fa-database fa-fw"></i> Compare</a>
|
||||
</li>
|
||||
</li>-->
|
||||
<li>
|
||||
<a href="/tempest/aggregate"><i class="fa fa-bar-chart-o fa-fw"></i> Aggregate Results</a>
|
||||
<a href="tempest_aggregate.html"><i class="fa fa-bar-chart-o fa-fw"></i> Aggregate Results</a>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- /.nav-second-level -->
|
||||
|
@ -123,7 +123,7 @@ var showDetails = function(item) {
|
||||
|
||||
showInfo(item);
|
||||
|
||||
d3.json("/tempest/api/details/{{run_id}}/" + item.name, function(error, data) {
|
||||
d3.json("tempest_api_details_{{run_id}}_" + item.name + ".json", function(error, data) {
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
@ -149,7 +149,7 @@ window.addEventListener('load', function() {
|
||||
var selectedItem = null;
|
||||
var selectedValue = null;
|
||||
|
||||
loadTimeline("/tempest/api/raw/{{run_id}}/", {
|
||||
loadTimeline("tempest_api_raw_{{run_id}}.json", {
|
||||
container: $("#timeline-container")[0],
|
||||
onClick: function(d) {
|
||||
var self = d3.select(this);
|
||||
|
@ -9,6 +9,7 @@ urlpatterns = patterns('',
|
||||
# url(r'^blog/', include('blog.urls')),
|
||||
|
||||
url(r'^$', IndexView.as_view()),
|
||||
url(r'^tempest/', include('stackviz.views.tempest.urls')),
|
||||
url(r'^devstack/', include('stackviz.views.devstack.urls')),
|
||||
url(r'^index.html$', IndexView.as_view(), name="index"),
|
||||
url(r'^tempest_', include('stackviz.views.tempest.urls')),
|
||||
url(r'^devstack_', include('stackviz.views.devstack.urls')),
|
||||
)
|
||||
|
@ -11,35 +11,32 @@ from .api import (TempestRunTreeEndpoint,
|
||||
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^results/(?P<run_id>\d+)/$',
|
||||
url(r'^results_(?P<run_id>\d+).html$',
|
||||
ResultsView.as_view(),
|
||||
name='tempest_results'),
|
||||
url(r'^results/$',
|
||||
url(r'^results.html$',
|
||||
LatestResultsView.as_view(),
|
||||
name='tempest_results_latest'),
|
||||
|
||||
url(r'^timeline/(?P<run_id>\d+)/$',
|
||||
url(r'^timeline_(?P<run_id>\d+).html$',
|
||||
TimelineView.as_view(),
|
||||
name='tempest_timeline'),
|
||||
url(r'^timeline/$',
|
||||
TimelineLatestView.as_view(),
|
||||
name='tempest_timeline_latest'),
|
||||
|
||||
url(r'^api/tree/(?P<run_id>\d+)/$',
|
||||
url(r'^api_tree_(?P<run_id>\d+).json$',
|
||||
TempestRunTreeEndpoint.as_view(),
|
||||
name='tempest_api_tree'),
|
||||
url(r'^api/raw/(?P<run_id>\d+)/$',
|
||||
url(r'^api_raw_(?P<run_id>\d+).json$',
|
||||
TempestRunRawEndpoint.as_view(),
|
||||
name='tempest_api_raw'),
|
||||
url(r'^api/details/(\d+)/([^/]+)/$',
|
||||
url(r'^api_details_(\d+)_([^/]+).json$',
|
||||
TempestRunDetailsEndpoint.as_view(),
|
||||
name='tempest_api_details'),
|
||||
|
||||
url(r'^aggregate/$',
|
||||
url(r'^aggregate.html$',
|
||||
AggregateResultsView.as_view(),
|
||||
name='aggregate_results'),
|
||||
name='tempest_aggregate_results'),
|
||||
|
||||
url(r'^summary/$',
|
||||
url(r'^summary.html$',
|
||||
SummaryView.as_view(),
|
||||
name='summary_results')
|
||||
name='tempest_summary_results')
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user