Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 100 additions & 20 deletions export.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,122 @@
import json
import argparse
import sqlite3
import pandas as pd
from collections import Counter
from html import escape

conn = sqlite3.connect(':memory:')
c = conn.cursor()
with open("data/bugs.json") as f:
data = json.load(f)

df = pd.DataFrame(data)
df.to_sql('bugs', conn)

domain_map = {
'dbms' : 'Database Management Systems',
'datalog' : 'Datalog Engines',
'xml' : 'XML Processors',
'compiler&interpreter': 'Compilers and Interpreters'
}

common_where_clause = "(resolution IN ('confirmed', 'fixed', 'open') OR resolution IS NULL)"
domain_count_query = 'SELECT domain, COUNT(*) FROM bugs WHERE ' + common_where_clause + ' GROUP BY domain ORDER BY COUNT(*) DESC;'
def is_included(entry):
return entry.get('resolution') in ('confirmed', 'fixed', 'open', None)


included_bugs = [entry for entry in data if is_included(entry)]
domain_counts = Counter(entry.get('domain') for entry in included_bugs)
ordered_domains = sorted(domain_counts.items(), key=lambda item: item[1], reverse=True)

print('<b>Overview</b><br/>')
print('<ul>')
for domain, count in c.execute(domain_count_query).fetchall():
for domain, count in ordered_domains:
print('<a href="#%s"><li>%s: %d bugs</li></a>' % (domain, domain_map[domain], count))
print('</ul>')

print('''
<div class="bug-database-controls">
<button type="button" class="expand-bug-databases">Expand all databases</button>
<button type="button" class="collapse-bug-databases">Collapse all databases</button>
</div>
<style>
.bug-database-controls {
display: flex;
gap: 0.6rem;
margin: 1rem 0;
flex-wrap: wrap;
}

.bug-database-controls button {
padding: 0.4rem 0.8rem;
border: 1px solid #1565c0;
border-radius: 4px;
color: #1565c0;
background: transparent;
cursor: pointer;
}

.bug-database-controls button:hover {
color: #fff;
background: #1565c0;
}

.bug-database-group {
margin: 0.8rem 0;
border: 1px solid rgba(0, 0, 0, 0.12);
border-radius: 4px;
}

.bug-database-group > summary {
padding: 0.7rem 1rem;
cursor: pointer;
font-size: 1.15rem;
font-weight: 600;
}

.bug-database-group[open] > summary {
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
}

.bug-database-group > .bug-entry {
margin: 0.7rem 1rem;
}
</style>
''')

print('<br/>')
for domain, count in c.execute(domain_count_query).fetchall():
for domain, count in ordered_domains:
print('<h2 id="%s">%s (%d bugs)</h2>' % (domain, domain_map[domain], count))
for system, count in c.execute(("SELECT system, COUNT(*) FROM bugs WHERE domain = '%s' AND " + common_where_clause + " GROUP BY system ORDER BY COUNT(*) DESC") % (domain,)).fetchall():
print('<h3>%s (%d bugs)</h3>' % (system, count))
for title, url, found_by, resolution in c.execute(("SELECT title, url, reported_by, resolution FROM bugs WHERE domain='%s' AND system='%s' AND " + common_where_clause + ";") % (domain, system)).fetchall():
print('<details>')
print('<summary>%s</summary>'% (title, ))
domain_bugs = [entry for entry in included_bugs if entry.get('domain') == domain]
system_counts = Counter(entry.get('system') for entry in domain_bugs)
ordered_systems = sorted(system_counts.items(), key=lambda item: item[1], reverse=True)
for system, count in ordered_systems:
print('<details class="bug-database-group">')
print('<summary>%s (%d bugs)</summary>' % (escape(system or 'Unknown database'), count))
for entry in domain_bugs:
if entry.get('system') != system:
continue
title = entry.get('title')
url = entry.get('url')
found_by = entry.get('reported_by')
resolution = entry.get('resolution')
print('<details class="bug-entry">')
print('<summary>%s</summary>' % escape(title or 'Untitled bug'))
if resolution is None:
resolution = 'unconfirmed'
print('Status: %s<br />' % (resolution, ))
print('Link: <a href="%s">%s</a> <br />' % (url, url))
print('Found by: %s' % (found_by,))
safe_url = escape(url or '', quote=True)
print('Status: %s<br />' % escape(resolution))
print('Link: <a href="%s">%s</a> <br />' % (safe_url, escape(url or '')))
print('Found by: %s' % escape(found_by or 'Unknown'))
print('</details>')
print('</details>')

print('''
<script>
document.addEventListener('DOMContentLoaded', function() {
var groups = Array.prototype.slice.call(document.querySelectorAll('.bug-database-group'));
var expandButton = document.querySelector('.expand-bug-databases');
var collapseButton = document.querySelector('.collapse-bug-databases');
if (!groups.length) return;

expandButton.addEventListener('click', function() {
groups.forEach(function(group) { group.open = true; });
});

collapseButton.addEventListener('click', function() {
groups.forEach(function(group) { group.open = false; });
});
});
</script>''')
Loading