diff -r 87cfa131b535 -r e7e0ae78773e configurationengine/source/cone/public/_etree_wrapper.py --- a/configurationengine/source/cone/public/_etree_wrapper.py Fri Mar 12 08:30:17 2010 +0200 +++ b/configurationengine/source/cone/public/_etree_wrapper.py Tue Aug 10 14:29:28 2010 +0300 @@ -32,8 +32,11 @@ def get_lineno(self, element): raise NotImplementedError() + def get_elem_from_lineno(self, root, lineno): + raise NotImplementedError() + class ElementTreeBackendWrapper(ElementTreeBackendWrapperBase): - + class CustomTreeBuilder(ElementTree.TreeBuilder): """ Custom TreeBuilder for ElementTree that records line numbers @@ -42,7 +45,7 @@ def start(self, tag, attrs): elem = ElementTree.TreeBuilder.start(self, tag, attrs) lineno = self._xmltreebuilder._parser.CurrentLineNumber - #print "Tag: %s, line: %r" % (tag, lineno) + # print "Tag: %s, line: %r" % (tag, lineno) elem.sourceline = lineno return elem @@ -55,7 +58,8 @@ parser = ElementTree.XMLTreeBuilder(target=treebuilder) treebuilder._xmltreebuilder = parser parser.feed(text) - return parser.close() + self.root = parser.close() + return self.root except expat.ExpatError, e: raise exceptions.XmlParseError( "XML parse error on line %d: %s" % (e.lineno, e), @@ -65,8 +69,16 @@ return ElementTree.tostring(etree, encoding) def get_lineno(self, element): - return element.sourceline + try: + return element.sourceline + except AttributeError: + return None + def get_elem_from_lineno(self, root, lineno): + for elem in root.getiterator(): + if elem.sourceline == lineno: + return elem + return None class CElementTreeBackendWrapper(ElementTreeBackendWrapperBase): def __init__(self): @@ -82,7 +94,8 @@ def fromstring(self, text): try: - return self.cElementTree.fromstring(text) + self.root = self.cElementTree.fromstring(text) + return self.root except SyntaxError, e: # cElementTree raises a SyntaxError, but does not set # its lineno attribute, so look for the line number @@ -103,6 +116,9 @@ # cElementTree does not support line numbers return None + def get_elem_from_lineno(self, root, lineno): + # cElementTree does not support line numbers + return None class LxmlBackendWrapper(ElementTreeBackendWrapperBase): @@ -115,39 +131,48 @@ def fromstring(self, text): try: - elem = self.lxml.etree.fromstring(text) - - # lxml parses also comments, but ConE does not expect those, - # so remove them to prevent any errors on that account - def remove_comments(elem): - # Find the comments under this element - comments = [] - for x in elem: - if isinstance(x, self.lxml.etree._Comment): - comments.append(x) - - # Remove them - for c in comments: - elem.remove(c) - - # Recurse to sub-elements - for subelem in elem: - remove_comments(subelem) - - remove_comments(elem) - - return elem + self.root = self.lxml.etree.fromstring(text) + self.remove_comments(self.root) + return self.root except self.lxml.etree.XMLSyntaxError, e: raise exceptions.XmlParseError( "XML parse error on line %d: %s" % (e.position[0], e), e.position[0], str(e)) + def remove_comments(self, elem): + """ + lxml parses also comments, but ConE does not expect those, + so remove them to prevent any errors on that account + """ + # Find the comments under this element + comments = [] + for x in elem: + if isinstance(x, self.lxml.etree._Comment): + comments.append(x) + + # Remove them + for c in comments: + elem.remove(c) + + # Recurse to sub-elements + for subelem in elem: + self.remove_comments(subelem) + def tostring(self, etree, encoding=None): return self.lxml.etree.tostring(etree, encoding=encoding) def get_lineno(self, element): - return element.sourceline + try: + return element.sourceline + except AttributeError: + return None + def get_elem_from_lineno(self, root, lineno): + for elem in root.getiterator(): + if elem.sourceline == lineno: + return elem + return None + # ============================================================================ # # ============================================================================ @@ -167,7 +192,8 @@ # Import order for the default back-end. The list is traversed # top-down and the first back-end whose importing is successful is # used as the default back-end - DEFAULT_BACKEND_IMPORT_ORDER = [BACKEND_C_ELEMENT_TREE, + DEFAULT_BACKEND_IMPORT_ORDER = [BACKEND_LXML, + BACKEND_C_ELEMENT_TREE, BACKEND_ELEMENT_TREE] _backend_mapping = {BACKEND_ELEMENT_TREE: ElementTreeBackendWrapper, @@ -229,6 +255,18 @@ """ return self._get_backend().get_lineno(element) + def get_elem_from_lineno(self, root, lineno): + """ + Return the element from the given line number of the given XML element. + + @param root: the root element to search from + @param lineno: the line number to search for + + Note that for the cElementTree parser this will always return + None, since that parser does not support line numbers. + """ + return self._get_backend().get_elem_from_lineno(root, lineno) + def __getattribute__(self, attrname): try: # Try to get the attribute from this object (the top-level wrapper)