#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
# Copyright (C) 2012-2013 Bastian Kleineidam
from __future__ import print_function
import sys
import os
import time
import cgi
import codecs
import json
sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
from dosagelib.scraper import get_scraperclasses
from dosagelib.util import getLangName
class Status:
"""Status of a comic strip."""
ok = u"ok"
error = u"error"
comicdata_template = u"""
/* generated on %(date)s */
$(document).ready(function() {
$('#comics').html('
');
$('#comictable').dataTable( {
"aaData": [
%(content)s
],
"aoColumns": [
{ "sTitle": "Name" },
{ "sTitle": "Genre" },
{ "sTitle": "Language" },
{ "sTitle": "Status" },
{ "sTitle": "Votes" }
]
} );
} );
"""
comic_template = u"""\
title: %(name)s
url: "/comics/%(pageurl)s"
---
Dosage comic %(name)s
-----------------------------------------
Description | %(description)s |
Website | %(url)s |
Genre | %(genre)s |
Language | %(language)s |
Adult content | %(adult)s |
Status | %(status)s on %(date)s |
Votes | %(vote)s |
[Edit this info](%(editurl)s) or go back to the [comic list](../comic-index.html).
"""
comic_edit_template = u"""\
title: Edit %(name)s
url: "/comics/%(editurl)s"
---
Edit info for comic %(name)s
Back to the [comic](%(pageurl)s).
"""
def get_mtime (filename):
"""Return modification time of filename."""
return os.path.getmtime(filename)
def strdate(t):
"""Get formatted date string."""
return time.strftime("%d.%m.%Y", time.localtime(t))
def get_testscraper(line):
"""Get scraper from test output line."""
classname = line.split('::')[1][4:]
for scraperclass in get_scraperclasses():
if scraperclass.__name__ == classname:
return scraperclass
raise ValueError("Scraper %r not found" % classname)
def get_testinfo(filename, modified):
"""Maintains a static list of comics which users can vote on.
@return: {name -> {
"status": Status.*,
"url": string,
"description": string,
"error": string or None,
"genre": string,
"language": string,
"adult": bool,
}
}
"""
testinfo = {}
with open(filename, "r") as f:
print("Tests parsed: 0", end=" ", file=sys.stderr)
num_tests = 0
add_error = False
keys = []
for line in f:
try:
if line.startswith((". ", "F ")) and "test_comics" in line:
add_error = line.startswith("F ")
num_tests += 1
key, entry = get_testentry(line)
keys.append(key)
update_testentry(key, entry, testinfo)
if num_tests % 5 == 0:
print(num_tests, end=" ", file=sys.stderr)
elif add_error and line.startswith(" E "):
entry["error"] = line[3:].strip()
except ValueError as msg:
print(msg)
return testinfo
def get_testentry(line):
"""Get one test entry."""
scraper = get_testscraper(line)
key = scraper.__name__
name = scraper.getName()
if len(name) > 40:
name = name[:37] + u"..."
genres = u",".join(sorted(scraper.genres))
if isinstance(scraper.description, unicode):
desc = scraper.description
else:
desc = scraper.description.decode("utf-8", "ignore")
entry = {
"status": Status.ok if line.startswith(u". ") else Status.error,
"name": name,
"url": scraper.url,
"description": desc,
"genre": genres,
"language": getLangName(scraper.lang),
"error": None,
"adult": scraper.adult,
"vote": get_vote(name),
}
return key, entry
def update_testentry(key, entry, testinfo):
"""Update one entry with testinfo information."""
testinfo[key] = entry
_votes = None
def get_vote(name):
global _votes
if _votes is None:
fname = os.path.join('data', 'votes.json')
with open(fname, 'rb') as f:
_votes = json.load(f)
key = name.replace('/', '_')
return _votes.get(key, 0)
def get_comicdata(testinfo):
"""Get comic data for table listing."""
rows = []
for key in sorted(testinfo.keys()):
entry = testinfo[key]
url = "comics/%s.html" % key
args = {
"url": quote(url),
"status": quote(entry["status"]),
"name": quote(entry["name"]),
"language": quote(entry["language"]),
"genre": quote(entry["genre"]),
"vote": entry["vote"],
}
row = u'["%(name)s", "%(genre)s", "%(language)s", "%(status)s", "%(vote)d"]' % args
rows.append(row)
return u",\n".join(rows)
def write_html(testinfo, outputdir, modified):
"""Write index page and all comic pages."""
content = get_comicdata(testinfo)
date = unicode(strdate(modified))
args = {"date": quote(date), "content": content}
fname = os.path.join("media", "js", "comicdata.js")
with codecs.open(fname, 'w', 'utf-8') as fp:
fp.write(comicdata_template % args)
comicdir = os.path.join(outputdir, "comics")
if not os.path.isdir(comicdir):
os.mkdir(comicdir)
for key, entry in testinfo.items():
write_html_comic(key, entry, comicdir, date)
def write_html_comic(key, entry, outputdir, date):
"""Write a comic page."""
args = {
"url": quote(entry["url"]),
"pageurl": quote("%s.html" % key),
"editurl": quote("%s_edit.html" % key),
"name": quote(entry["name"]),
"comic": quote(key),
"adult": quote(u"yes" if entry["adult"] else u"no"),
"adultchecked": 'checked="checked"' if entry["adult"] else '',
"genre": quote(entry["genre"]),
"language": quote(entry["language"]),
"description": quote(entry["description"]),
"status": quote(entry["status"]),
"date": quote(date),
"vote": entry["vote"],
}
fname = os.path.join(outputdir, key+".md")
with codecs.open(fname, 'w', 'utf-8') as fp:
fp.write(comic_template % args)
fname = os.path.join(outputdir, key+"_edit.md")
with codecs.open(fname, 'w', 'utf-8') as fp:
fp.write(comic_edit_template % args)
def quote(arg):
"""CGI-escape and jinja-escape the argument."""
return cgi.escape(arg.replace(u'{', u'').replace(u'}', u''), quote=True)
def main(args):
"""Generate HTML output for test result."""
filename = args[0]
outputdir = args[1]
modified = get_mtime(filename)
testinfo = get_testinfo(filename, modified)
write_html(testinfo, outputdir, modified)
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))