# -*- coding: utf-8 -*- """ Options class: collect the possible options that govern the parsing possibilities. It also includes a reference and handling of the extra Graph for warnings, informations, errors. @summary: RDFa parser (distiller) @requires: U{RDFLib} @requires: U{html5lib} for the HTML5 parsing; note possible dependecies on Python's version on the project's web site @organization: U{World Wide Web Consortium} @author: U{Ivan Herman} @license: This software is available for use under the U{W3C® SOFTWARE NOTICE AND LICENSE} """ import sys from rdflib.graph import Graph from rdflib.term import BNode, Literal, URIRef from rdflib.namespace import Namespace __all__ = ['CommentGraph', 'Options'] DIST_URI = "http://www.w3.org/2007/08/pyRdfa/distiller" DIST_NS = DIST_URI + '#' ns_errors = Namespace(DIST_NS) distillerURI = URIRef(DIST_URI) WARNING = 'warning' ERROR = 'error' INFO = 'info' DEBUG = 'debug' _message_properties = { WARNING: ns_errors["warning"], ERROR: ns_errors["error"], INFO: ns_errors["information"], DEBUG: ns_errors["debug"] } def _add_to_comment_graph(graph, msg, prop, uri): """ Add a distiller message to the graph. @param graph: RDFLib Graph @param msg: message of an exception @type msg: RDFLIb Literal @param prop: the property to be used @type prop: string, must be one of 'warning', 'error', 'info', 'debug' @param uri: the top URI used to invoke the distiller @type uri: URIRef """ bnode = BNode() graph.add((distillerURI, _message_properties[prop], bnode)) graph.add((bnode, ns_errors["onURI"], uri)) graph.add((bnode, ns_errors["message"], msg)) class CommentGraph(object): """Class to handle the 'comment graph', ie, the (RDF) Graph containing the warnings, error messages, and informational messages. """ def __init__(self, warnings = False): """ @param warnings: whether a graph should effectively be set up, or whether this should just be an empty shell for the various calls to work (without effect) """ if warnings: self.graph = Graph() else: self.graph = None self.accumulated_literals = [] self.baseURI = None def _add_triple(self, msg, prop): obj = Literal(msg) if self.baseURI == None: self.accumulated_literals.append((obj,prop)) elif self.graph != None: _add_to_comment_graph(self.graph, obj, prop, self.baseURI) def set_base_URI(self, URI): """Set the base URI for the comment triples. Note that this method I{must} be called at some point to complete the triples. Without it the triples added via L{add_warning}, L{add_info}, etc, will not be added to the final graph. @param URI: URIRef for the subject of the comments """ self.baseURI = URI if self.graph != None: for obj, prop in self.accumulated_literals: _add_to_comment_graph(self.graph, obj, prop, self.baseURI) self.accumulated_literals = [] def add_warning(self, txt): """Add a warning. A comment triplet is added to the separate "warning" graph. @param txt: the warning text. It will be preceded by the string "==== pyRdfa Warning ==== " """ self._add_triple(txt, WARNING) def add_info(self, txt): """Add an informational comment. A comment triplet is added to the separate "warning" graph. @param txt: the information text. It will be preceded by the string "==== pyRdfa information ==== " """ self._add_triple(txt, INFO) def add_error(self, txt): """Add an error comment. A comment triplet is added to the separate "warning" graph. @param txt: the information text. It will be preceded by the string "==== pyRdfa information ==== " """ self._add_triple(txt, ERROR) def _add_debug(self, txt): self._add_triple(txt, DEBUG) GENERIC_XML = 0 XHTML_RDFA = 1 HTML5_RDFA = 2 class Options(object): """Settable options. An instance of this class is stored in the L{execution context} of the parser. @ivar space_preserve: whether plain literals should preserve spaces at output or not @type space_preserve: Boolean @ivar comment_graph: Graph for the storage of warnings @type comment_graph: L{CommentGraph} @ivar warnings: whether warnings should be generated or not @type warnings: Boolean @ivar transformers: extra transformers @type transformers: list @type host_language: the host language for the RDFa attributes. Default is XHTML_RDFA, but it can be GENERIC_XML and HTML5_RDFA @ivar host_language: integer (logically: an enumeration) @ivar lax: whether a 'lax' parsing of XHTML (ie, HTML5) is allowed. This means that the value of the host language might change run time @type lax: Boolean """ def __init__(self, warnings=False, space_preserve=True, transformers=[], xhtml=True, lax=False): """ @param space_preserve: whether plain literals should preserve spaces at output or not @type space_preserve: Boolean @param warnings: whether warnings should be generated or not @type warnings: Boolean @param transformers: extra transformers @type transformers: list @param xhtml: initial value for the host language. If True, the value is set to XHTML_RDFA. Note that run-time the class variable might be set ot HTML5_RDFA, depending on the value of the lax flag and the result of parsing. @type xhtml: Booelan @param lax: whether a 'lax' parsing of XHTML (ie, HTML5) is allowed. This means that the value of the host language might change run time @type lax: Boolean """ self.space_preserve = space_preserve self.transformers = transformers self.comment_graph = CommentGraph(warnings) self.warnings = warnings self.lax = lax if xhtml: self.host_language = XHTML_RDFA else: self.host_language = GENERIC_XML def __str__(self): retval = """Current options: space_preserve : %s warnings : %s lax parsing : %s host language : %s """ return retval % (self.space_preserve, self.warnings, self.lax, self.host_language)