blob: ac6b7e76945d56949292ac4a44144a2bd1d8ed01 [file] [log] [blame]
#!/usr/bin/env python
"""Boostbook tests
Usage: python build_docs.py [--generate-gold]
"""
import difflib, getopt, os, re, sys
import lxml.ElementInclude
from lxml import etree
# Globals
def usage_and_exit():
print __doc__
sys.exit(2)
def main(argv):
script_directory = os.path.dirname(sys.argv[0])
boostbook_directory = os.path.join(script_directory, "../../xsl")
try:
opts, args = getopt.getopt(argv, "",
["generate-gold"])
if(len(args)): usage_and_exit()
except getopt.GetoptError:
usage_and_exit()
generate_gold = False
for opt, arg in opts:
if opt == '--generate-gold':
generate_gold = True
# Walk the test directory
parser = etree.XMLParser()
try:
boostbook_xsl = etree.XSLT(
etree.parse(os.path.join(boostbook_directory, "docbook.xsl"), parser)
)
except lxml.etree.XMLSyntaxError, error:
print "Error parsing boostbook xsl:"
print error
sys.exit(1)
for root, dirs, files in os.walk(os.path.join(script_directory, 'tests')):
for filename in files:
(base, ext) = os.path.splitext(filename)
if (ext == '.xml'):
src_path = os.path.join(root, filename)
gold_path = os.path.join(root, base + '.gold')
try:
doc_text = run_boostbook(parser, boostbook_xsl, src_path)
except:
# TODO: Need better error reporting here:
print "Error running boostbook for " + src_path
continue
if (generate_gold):
file = open(gold_path, 'w')
try:
file.write(doc_text)
finally: file.close()
else:
file = open(gold_path, 'r')
try:
gold_text = file.read()
finally:
file.close()
compare_xml(filename, doc_text, gold_text)
def run_boostbook(parser, boostbook_xsl, file):
doc = boostbook_xsl(etree.parse(file, parser))
normalize_boostbook_ids(doc)
return etree.tostring(doc)
def normalize_boostbook_ids(doc):
ids = {}
id_bases = {}
for node in doc.xpath("//*[starts-with(@id, 'id') or contains(@id, '_id')]"):
id = node.get('id')
if(id in ids):
print 'Duplicate id: ' + id
match = re.match("(id|.+_id)(\d+)((?:-bb)?)", id)
if(match):
count = 1
if(match.group(1) in id_bases):
count = id_bases[match.group(1)] + 1
id_bases[match.group(1)] = count
ids[id] = match.group(1) + str(count) + match.group(3)
for node in doc.xpath("//*[@linkend or @id]"):
x = node.get('linkend')
if(x in ids): node.set('linkend', ids[x])
x = node.get('id')
if(x in ids): node.set('id', ids[x])
def compare_xml(file, doc_text, gold_text):
# Had hoped to use xmldiff but it turned out to be a pain to install.
# So instead just do a text diff.
if (doc_text != gold_text):
print "Error: " + file
print
sys.stdout.writelines(
difflib.unified_diff(
gold_text.splitlines(True),
doc_text.splitlines(True)
)
)
if __name__ == "__main__":
main(sys.argv[1:])