import sys from lxml import etree from deliverance.htmlserialize import tostring import urllib from deliverance.interpreter import Renderer as PythonRenderer from deliverance.xslt import Renderer as XSLTRenderer from optparse import OptionParser import re import os """ Command line utility to run a deliverance transform given the urls of the rules, theme and content. themeurl, rulesfile and baseurl can be rolled into a file specified with -f it should contain an element like """ DEFAULT_BASE_URL = "http://www.example.com" usage = "usage: %prog [options] " parser = OptionParser(usage=usage) parser.add_option("-t", "--theme", dest="theme_url", help="url of theme html") parser.add_option("-b", "--baseurl", dest="base_url", help="relative urls in the theme will be made absolute relative to this url [default %default]", default=DEFAULT_BASE_URL) parser.add_option("-r", "--rules", dest="rules_file", help="path to file containing the deliverance rules to apply") parser.add_option("-f", "--from-file", dest="blend_file", help="take theme, baseurl and rules parameters from the referenced file") parser.add_option("-R", "--renderer", dest="renderer_type", help="(xslt|py) [default %default]", default="xslt", choices=['xslt','py']) def grab_url(url): """ returns the data referenced by the url provided. """ f = urllib.urlopen(url) data = f.read() f.close() return data def do_transform(renderer_type, theme_url, base_url, rules_url, content_url): """ Perform the deliverance transform using the rules referenced by rules_url on the pages referenced by theme_url and content_url. Renderer type determines which deliverance renderer class is used to perform the transform, which may be either 'xslt' or 'py'. Relative urls in the theme page will rewritten as absolute urls relative to the base_url given. returns the result of the transformation """ rules = etree.XML(grab_url(rules_url)) theme = etree.HTML(grab_url(theme_url)) content = etree.HTML(grab_url(content_url)) def reference_resolver(href, parse, encoding=None): text = grab_url(href) if parse == "xml": return etree.XML(text) elif encoding: return text.decode(encoding) renderer = None if renderer_type == 'xslt': renderer = XSLTRenderer(theme,base_url,rules,rules_url,reference_resolver) elif renderer_type == 'py': renderer = PythonRenderer(theme,base_url,rules,rules_url,reference_resolver) else: print "Unknown renderer type '" + renderer_type + "'" return etree.Element("error") return renderer.render(content) def parse_blend_file(filename): """ returns the theme url, base url and rules url specified in the file given. filename is expected to contain an xml document containing a toplevel element with attributes 'theme', 'baseurl' and 'rules' """ b = etree.XML(open(filename).read()) return b.get('theme'),b.get('baseurl'),b.get('rules') def die(message,parser): """ prints an error message, the usage of the program, then quits. """ print message parser.print_usage() sys.exit(0) def main(args=None): """ main function, see usage information """ if args is None: args = sys.argv[1:] options, args = parser.parse_args(args) if len(args) == 0: die("no content url specified.", parser) content_url = args[0] theme_url = None base_url = None rules_file = None if options.blend_file: if (options.rules_file or options.theme_url or options.base_url != DEFAULT_BASE_URL): die("cannot specify base url, rules file or theme url when taking parameters from file.",parser) try: theme_url, base_url, rules_file = parse_blend_file(options.blend_file) except Exception, message: die(message, parser) else: theme_url = options.theme_url rules_file = options.rules_file base_url = options.base_url if theme_url is None: die("no theme url specified.",parser) if rules_file is None: die("no rules file specified.",parser) if base_url is None: die("no base url specified",parser) print tostring(do_transform(options.renderer_type, theme_url, base_url, rules_file, content_url)) if __name__ == '__main__': main()