Note that it is almost impossible to get a 100%% OK test run
-due to temporary site failures.
-
+
Dosage comic list
+
%(content)s
+
+
{%% endblock content %%}
"""
+comic_template = """
+---
+extends: base.j2
+title: Dosage comic %(name)s
+---
+{%% block content %%}
+
+
+Dosage comic %(name)s
+
+
+Description | %(description)s |
+
+
+Website | %(url)s |
+
+
+Adult content | %(adult)s |
+
+
+Available since | Dosage v%(since)s |
+
+
+Status | %(status)s on %(date)s |
+
+
+
+
+
+{%% endblock content %%}
+"""
+
+entrytemplate_url = """
+
%(name)s
+
+"""
+
+entrytemplate_nourl = """
+
%(name)s
+"""
+
def get_mtime (filename):
"""Return modification time of filename."""
@@ -49,75 +110,164 @@ def strdate(t):
return time.strftime("%d.%m.%Y", time.localtime(t))
-def get_test_name(line):
- """Get scraper name from test output line."""
+def get_testscraper(line):
+ """Get scraper from test output line."""
classname = line.split('::')[1][4:]
for scraper in get_scrapers():
if scraper.__name__ == classname:
- try:
- url = scraper.starter()
- except Exception:
- url = None
- return scraper.get_name(), url
+ return scraper
raise ValueError("Scraper %r not found" % classname)
-def get_test(line):
- """Get test name from test output line."""
- name, url = get_test_name(line)
- result = "OK" if line.startswith(". ") else "FAILED"
- return [name, url, result, ""]
-
-
-def get_content(filename):
- """Get HTML content for test output."""
- tests = []
+def get_testinfo(filename, modified):
+ """Maintains a static list of comics which users can vote on.
+ The original set of comic strips is stored in a JSON file which gets
+ updated from the test results.
+ If a comic strip stored in JSON is not found in the test results, it is
+ orphaned.
+ @return: {name -> {
+ "status": Status.*,
+ "url": string or None,
+ "description": string or None,
+ "error": string or None,
+ }
+ }
+ """
+ if os.path.isfile(json_file):
+ testinfo = load_result(json_file)
+ else:
+ testinfo = {}
with open(filename, "r") as f:
print("Tests parsed: 0", end=" ", file=sys.stderr)
num_tests = 0
- add_reason = False
+ add_error = False
+ keys = []
for line in f:
if line.startswith((". ", "F ")) and "test_comics" in line:
- add_reason = line.startswith("F ")
+ add_error = line.startswith("F ")
num_tests += 1
- try:
- tests.append(get_test(line))
- except Exception as msg:
- print("WARNING:", msg, file=sys.stderr)
- continue
- elif add_reason and line.startswith(" E "):
- reason = line[3:].strip()
- tests[-1][-1] = reason
+ key, entry = get_testentry(line)
+ keys.append(key)
+ update_testentry(key, entry, testinfo)
+ elif add_error and line.startswith(" E "):
+ entry["error"] = line[3:].strip()
if num_tests % 5 == 0:
print(num_tests, end=" ", file=sys.stderr)
- tests.sort()
- res = []
- for name, url, result, reason in tests:
- css = result.lower()
- if len(name) > 40:
- name = name[:37] + "..."
- if url:
- args = quote_all(url, reason, css, name)
- inner = '
%s' % args
+ orphan_entries(keys, testinfo)
+ save_result(testinfo, json_file)
+ return testinfo
+
+
+def get_testentry(line):
+ """Get one test entry."""
+ scraper = get_testscraper(line)
+ key = scraper.__name__
+ name = scraper.get_name()
+ if len(name) > 40:
+ name = name[:37] + "..."
+ entry = {
+ "status": Status.ok if line.startswith(". ") else Status.error,
+ "name": name,
+ "url": None,
+ "description": scraper.description,
+ "error": None,
+ "adult": scraper.adult,
+ }
+ try:
+ entry["url"] = scraper.starter()
+ except Exception as msg:
+ print("WARNING:", msg, file=sys.stderr)
+ return key, entry
+
+
+def orphan_entries(keys, testinfo):
+ """Mark all entries that are in testinfo but not in keys as orphaned."""
+ for key, entry in testinfo.items():
+ if key not in keys:
+ entry["status"] = Status.orphan
+
+
+def update_testentry(key, entry, testinfo):
+ if key not in testinfo:
+ # add dosage version for this comic
+ # XXX replace this after next release
+ if key.startswith("Arcamax") or key in ("AmazingSuperPowers", "PandyLand"):
+ entry["since"] = DosageVersion
else:
- args = quote_all(reason, css, name)
- inner = '
%s' % args
- res.append('
%s
' % inner)
+ entry["since"] = "1.8"
+ else:
+ entry["since"] = testinfo[key]["since"]
+ testinfo[key] = entry
+
+
+def get_html_index(testinfo):
+ """Get HTML content for test output index."""
+ res = []
+ for key in sorted(testinfo.keys()):
+ entry = testinfo[key]
+ css = entry["status"]
+ url = "comics/%s.html" % key
+ if entry["error"]:
+ title = entry["error"]
+ elif entry["description"]:
+ title = entry["description"]
+ else:
+ title = entry["name"]
+ args = {
+ "url": quote(url),
+ "title": quote(title),
+ "css": quote(css),
+ "name": quote(entry["name"]),
+ }
+ template = entrytemplate_url if url else entrytemplate_nourl
+ entryhtml = template % args
+ res.append('
%s
' % entryhtml)
return os.linesep.join(res)
-def quote_all(*args):
- """CGI-escape all arguments for."""
- return tuple(cgi.escape(x, quote=True) for x in args)
+def write_html(testinfo, outputdir, modified):
+ """Write index page and all comic pages."""
+ content = get_html_index(testinfo)
+ date = strdate(modified)
+ args = {"date": quote(date), "content": content}
+ fname = os.path.join(outputdir, "comic_index.html")
+ with open(fname, 'w') as fp:
+ fp.write(indextemplate % 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"]),
+ "name": quote(entry["name"]),
+ "adult": quote("yes" if entry["adult"] else "no"),
+ "since": quote(entry["since"]),
+ "description": quote(entry["description"]),
+ "status": quote(entry["status"]),
+ "date": quote(date),
+ }
+ fname = os.path.join(outputdir, key+".html")
+ with open(fname, 'w') as fp:
+ fp.write(comic_template % args)
+
+
+def quote(arg):
+ """CGI-escape argument."""
+ return cgi.escape(arg, quote=True)
def main(args):
"""Generate HTML output for test result."""
filename = args[0]
+ outputdir = args[1]
modified = get_mtime(filename)
- content = get_content(filename)
- attrs = {"date": strdate(modified), "content": content}
- print(htmltemplate % attrs)
+ testinfo = get_testinfo(filename, modified)
+ write_html(testinfo, outputdir, modified)
return 0