Index: Lib/test/test_minidom.py =================================================================== --- Lib/test/test_minidom.py (revision 54434) +++ Lib/test/test_minidom.py (working copy) @@ -1,1397 +1,1414 @@ # test for xml.dom.minidom -import os -import sys +import unittest +from test import test_support + import pickle -import traceback from StringIO import StringIO -from test.test_support import verbose - import xml.dom import xml.dom.minidom import xml.parsers.expat - from xml.dom.minidom import parse, Node, Document, parseString from xml.dom.minidom import getDOMImplementation +try: + import gc +except ImportError: + gc = None +# Find absolute path to "test.xml". +import sys, os if __name__ == "__main__": base = sys.argv[0] else: base = __file__ tstfile = os.path.join(os.path.dirname(base), "test"+os.extsep+"xml") -del base +del base, sys, os -def confirm(test, testname = "Test"): - if not test: - print "Failed " + testname - raise Exception +class MinidomTest(unittest.TestCase): -def testParseFromFile(): - dom = parse(StringIO(open(tstfile).read())) - dom.unlink() - confirm(isinstance(dom,Document)) + def testParseFromFile(self): + dom = parse(StringIO(open(tstfile).read())) + dom.unlink() + self.assert_(isinstance(dom,Document)) -def testGetElementsByTagName(): - dom = parse(tstfile) - confirm(dom.getElementsByTagName("LI") == \ - dom.documentElement.getElementsByTagName("LI")) - dom.unlink() + def testGetElementsByTagName(self): + dom = parse(tstfile) + self.assertEqual(dom.getElementsByTagName("LI"), + dom.documentElement.getElementsByTagName("LI")) + dom.unlink() -def testInsertBefore(): - dom = parseString("") - root = dom.documentElement - elem = root.childNodes[0] - nelem = dom.createElement("element") - root.insertBefore(nelem, elem) - confirm(len(root.childNodes) == 2 - and root.childNodes.length == 2 - and root.childNodes[0] is nelem - and root.childNodes.item(0) is nelem - and root.childNodes[1] is elem - and root.childNodes.item(1) is elem - and root.firstChild is nelem - and root.lastChild is elem - and root.toxml() == "" - , "testInsertBefore -- node properly placed in tree") - nelem = dom.createElement("element") - root.insertBefore(nelem, None) - confirm(len(root.childNodes) == 3 - and root.childNodes.length == 3 - and root.childNodes[1] is elem - and root.childNodes.item(1) is elem - and root.childNodes[2] is nelem - and root.childNodes.item(2) is nelem - and root.lastChild is nelem - and nelem.previousSibling is elem - and root.toxml() == "" - , "testInsertBefore -- node properly placed in tree") - nelem2 = dom.createElement("bar") - root.insertBefore(nelem2, nelem) - confirm(len(root.childNodes) == 4 - and root.childNodes.length == 4 - and root.childNodes[2] is nelem2 - and root.childNodes.item(2) is nelem2 - and root.childNodes[3] is nelem - and root.childNodes.item(3) is nelem - and nelem2.nextSibling is nelem - and nelem.previousSibling is nelem2 - and root.toxml() == "" - , "testInsertBefore -- node properly placed in tree") - dom.unlink() + def testInsertBefore(self): + dom = parseString("") + root = dom.documentElement + elem = root.childNodes[0] + nelem = dom.createElement("element") + root.insertBefore(nelem, elem) + self.assertEqual(len(root.childNodes), 2) + self.assertEqual(root.childNodes.length, 2) + self.assert_(root.childNodes[0] is nelem) + self.assert_(root.childNodes.item(0) is nelem) + self.assert_(root.childNodes[1] is elem) + self.assert_(root.childNodes.item(1) is elem) + self.assert_(root.firstChild is nelem) + self.assert_(root.lastChild is elem) + self.assertEqual(root.toxml(), "") -def _create_fragment_test_nodes(): - dom = parseString("") - orig = dom.createTextNode("original") - c1 = dom.createTextNode("foo") - c2 = dom.createTextNode("bar") - c3 = dom.createTextNode("bat") - dom.documentElement.appendChild(orig) - frag = dom.createDocumentFragment() - frag.appendChild(c1) - frag.appendChild(c2) - frag.appendChild(c3) - return dom, orig, c1, c2, c3, frag + nelem = dom.createElement("element") + root.insertBefore(nelem, None) + self.assertEqual(len(root.childNodes), 3) + self.assertEqual(root.childNodes.length, 3) + self.assert_(root.childNodes[1] is elem) + self.assert_(root.childNodes.item(1) is elem) + self.assert_(root.childNodes[2] is nelem) + self.assert_(root.childNodes.item(2) is nelem) + self.assert_(root.lastChild is nelem) + self.assert_(nelem.previousSibling is elem) + self.assertEqual(root.toxml(), "") -def testInsertBeforeFragment(): - dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes() - dom.documentElement.insertBefore(frag, None) - confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3), + nelem2 = dom.createElement("bar") + root.insertBefore(nelem2, nelem) + self.assertEqual(len(root.childNodes), 4) + self.assertEqual(root.childNodes.length, 4) + self.assert_(root.childNodes[2] is nelem2) + self.assert_(root.childNodes.item(2) is nelem2) + self.assert_(root.childNodes[3] is nelem) + self.assert_(root.childNodes.item(3) is nelem) + self.assert_(nelem2.nextSibling is nelem) + self.assert_(nelem.previousSibling is nelem2) + self.assertEqual(root.toxml(), "") + + dom.unlink() + + def _create_fragment_test_nodes(self): + dom = parseString("") + orig = dom.createTextNode("original") + c1 = dom.createTextNode("foo") + c2 = dom.createTextNode("bar") + c3 = dom.createTextNode("bat") + dom.documentElement.appendChild(orig) + frag = dom.createDocumentFragment() + frag.appendChild(c1) + frag.appendChild(c2) + frag.appendChild(c3) + return dom, orig, c1, c2, c3, frag + + def testInsertBeforeFragment(self): + dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes() + dom.documentElement.insertBefore(frag, None) + self.assertEqual( + tuple(dom.documentElement.childNodes), (orig, c1, c2, c3), "insertBefore(, None)") - frag.unlink() - dom.unlink() - # - dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes() - dom.documentElement.insertBefore(frag, orig) - confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3, orig), + frag.unlink() + dom.unlink() + # + dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes() + dom.documentElement.insertBefore(frag, orig) + self.assertEqual( + tuple(dom.documentElement.childNodes), (c1, c2, c3, orig), "insertBefore(, orig)") - frag.unlink() - dom.unlink() + frag.unlink() + dom.unlink() -def testAppendChild(): - dom = parse(tstfile) - dom.documentElement.appendChild(dom.createComment(u"Hello")) - confirm(dom.documentElement.childNodes[-1].nodeName == "#comment") - confirm(dom.documentElement.childNodes[-1].data == "Hello") - dom.unlink() + def testAppendChild(self): + dom = parse(tstfile) + dom.documentElement.appendChild(dom.createComment(u"Hello")) + self.assertEqual(dom.documentElement.childNodes[-1].nodeName, "#comment") + self.assertEqual(dom.documentElement.childNodes[-1].data, "Hello") + dom.unlink() -def testAppendChildFragment(): - dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes() - dom.documentElement.appendChild(frag) - confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3), + def testAppendChildFragment(self): + dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes() + dom.documentElement.appendChild(frag) + self.assertEqual( + tuple(dom.documentElement.childNodes), (orig, c1, c2, c3), "appendChild()") - frag.unlink() - dom.unlink() + frag.unlink() + dom.unlink() -def testReplaceChildFragment(): - dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes() - dom.documentElement.replaceChild(frag, orig) - orig.unlink() - confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3), + def testReplaceChildFragment(self): + dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes() + dom.documentElement.replaceChild(frag, orig) + orig.unlink() + self.assertEqual( + tuple(dom.documentElement.childNodes), (c1, c2, c3), "replaceChild()") - frag.unlink() - dom.unlink() + frag.unlink() + dom.unlink() -def testLegalChildren(): - dom = Document() - elem = dom.createElement('element') - text = dom.createTextNode('text') + def testLegalChildren(self): + dom = Document() + elem = dom.createElement('element') + text = dom.createTextNode('text') - try: dom.appendChild(text) - except xml.dom.HierarchyRequestErr: pass - else: - print "dom.appendChild didn't raise HierarchyRequestErr" + self.assertRaises(xml.dom.HierarchyRequestErr, dom.appendChild, text) - dom.appendChild(elem) - try: dom.insertBefore(text, elem) - except xml.dom.HierarchyRequestErr: pass - else: - print "dom.appendChild didn't raise HierarchyRequestErr" + dom.appendChild(elem) + self.assertRaises(xml.dom.HierarchyRequestErr, + dom.insertBefore, text, elem) + self.assertRaises(xml.dom.HierarchyRequestErr, + dom.replaceChild, text, elem) - try: dom.replaceChild(text, elem) - except xml.dom.HierarchyRequestErr: pass - else: - print "dom.appendChild didn't raise HierarchyRequestErr" + nodemap = elem.attributes + self.assertRaises(xml.dom.HierarchyRequestErr, + nodemap.setNamedItem, text) + self.assertRaises(xml.dom.HierarchyRequestErr, + nodemap.setNamedItemNS, text) - nodemap = elem.attributes - try: nodemap.setNamedItem(text) - except xml.dom.HierarchyRequestErr: pass - else: - print "NamedNodeMap.setNamedItem didn't raise HierarchyRequestErr" + elem.appendChild(text) + dom.unlink() - try: nodemap.setNamedItemNS(text) - except xml.dom.HierarchyRequestErr: pass - else: - print "NamedNodeMap.setNamedItemNS didn't raise HierarchyRequestErr" + def testNamedNodeMapSetItem(self): + dom = Document() + elem = dom.createElement('element') + attrs = elem.attributes + attrs["foo"] = "bar" + a = attrs.item(0) + self.assert_(a.ownerDocument is dom, + "NamedNodeMap.__setitem__() sets ownerDocument") + self.assert_(a.ownerElement is elem, + "NamedNodeMap.__setitem__() sets ownerElement") + self.assertEqual(a.value, "bar", + "NamedNodeMap.__setitem__() sets value") + self.assertEqual(a.nodeValue, "bar", + "NamedNodeMap.__setitem__() sets nodeValue") + elem.unlink() + dom.unlink() - elem.appendChild(text) - dom.unlink() + def testNonZero(self): + dom = parse(tstfile) + self.assert_(dom, "result of parse() should not be zero") + dom.appendChild(dom.createComment("foo")) + self.assert_(not dom.childNodes[-1].childNodes) + dom.unlink() -def testNamedNodeMapSetItem(): - dom = Document() - elem = dom.createElement('element') - attrs = elem.attributes - attrs["foo"] = "bar" - a = attrs.item(0) - confirm(a.ownerDocument is dom, - "NamedNodeMap.__setitem__() sets ownerDocument") - confirm(a.ownerElement is elem, - "NamedNodeMap.__setitem__() sets ownerElement") - confirm(a.value == "bar", - "NamedNodeMap.__setitem__() sets value") - confirm(a.nodeValue == "bar", - "NamedNodeMap.__setitem__() sets nodeValue") - elem.unlink() - dom.unlink() + def testUnlink(self): + dom = parse(tstfile) + dom.unlink() -def testNonZero(): - dom = parse(tstfile) - confirm(dom)# should not be zero - dom.appendChild(dom.createComment("foo")) - confirm(not dom.childNodes[-1].childNodes) - dom.unlink() + def testDocumentElement(self): + dom = Document() + dom.appendChild(dom.createElement("abc")) + self.assert_(dom.documentElement) + dom.unlink() -def testUnlink(): - dom = parse(tstfile) - dom.unlink() + def testAAA(self): + dom = parseString("") + el = dom.documentElement + el.setAttribute("spam", "jam2") + self.assertEqual(el.toxml(), '', "testAAA") + a = el.getAttributeNode("spam") + self.assert_(a.ownerDocument is dom, + "setAttribute() sets ownerDocument") + self.assert_(a.ownerElement is dom.documentElement, + "setAttribute() sets ownerElement") + dom.unlink() -def testElement(): - dom = Document() - dom.appendChild(dom.createElement("abc")) - confirm(dom.documentElement) - dom.unlink() + def testAAB(self): + dom = parseString("") + el = dom.documentElement + el.setAttribute("spam", "jam") + el.setAttribute("spam", "jam2") + self.assertEqual(el.toxml(), '', "testAAB") + dom.unlink() -def testAAA(): - dom = parseString("") - el = dom.documentElement - el.setAttribute("spam", "jam2") - confirm(el.toxml() == '', "testAAA") - a = el.getAttributeNode("spam") - confirm(a.ownerDocument is dom, - "setAttribute() sets ownerDocument") - confirm(a.ownerElement is dom.documentElement, - "setAttribute() sets ownerElement") - dom.unlink() + def testAddAttr(self): + dom = Document() + child = dom.appendChild(dom.createElement("abc")) -def testAAB(): - dom = parseString("") - el = dom.documentElement - el.setAttribute("spam", "jam") - el.setAttribute("spam", "jam2") - confirm(el.toxml() == '', "testAAB") - dom.unlink() + child.setAttribute("def", "ghi") + self.assertEqual(child.getAttribute("def"), "ghi") + self.assertEqual(child.attributes["def"].value, "ghi") -def testAddAttr(): - dom = Document() - child = dom.appendChild(dom.createElement("abc")) + child.setAttribute("jkl", "mno") + self.assertEqual(child.getAttribute("jkl"), "mno") + self.assertEqual(child.attributes["jkl"].value, "mno") - child.setAttribute("def", "ghi") - confirm(child.getAttribute("def") == "ghi") - confirm(child.attributes["def"].value == "ghi") + self.assertEqual(len(child.attributes), 2) - child.setAttribute("jkl", "mno") - confirm(child.getAttribute("jkl") == "mno") - confirm(child.attributes["jkl"].value == "mno") + child.setAttribute("def", "newval") + self.assertEqual(child.getAttribute("def"), "newval") + self.assertEqual(child.attributes["def"].value, "newval") - confirm(len(child.attributes) == 2) + self.assertEqual(len(child.attributes), 2) + dom.unlink() - child.setAttribute("def", "newval") - confirm(child.getAttribute("def") == "newval") - confirm(child.attributes["def"].value == "newval") + def testDeleteAttr(self): + dom = Document() + child = dom.appendChild(dom.createElement("abc")) - confirm(len(child.attributes) == 2) - dom.unlink() + self.assertEqual(len(child.attributes), 0) + child.setAttribute("def", "ghi") + self.assertEqual(len(child.attributes), 1) + del child.attributes["def"] + self.assertEqual(len(child.attributes), 0) + dom.unlink() -def testDeleteAttr(): - dom = Document() - child = dom.appendChild(dom.createElement("abc")) + def testRemoveAttr(self): + dom = Document() + child = dom.appendChild(dom.createElement("abc")) - confirm(len(child.attributes) == 0) - child.setAttribute("def", "ghi") - confirm(len(child.attributes) == 1) - del child.attributes["def"] - confirm(len(child.attributes) == 0) - dom.unlink() + child.setAttribute("def", "ghi") + self.assertEqual(len(child.attributes), 1) + child.removeAttribute("def") + self.assertEqual(len(child.attributes), 0) -def testRemoveAttr(): - dom = Document() - child = dom.appendChild(dom.createElement("abc")) + dom.unlink() - child.setAttribute("def", "ghi") - confirm(len(child.attributes) == 1) - child.removeAttribute("def") - confirm(len(child.attributes) == 0) + def testRemoveAttrNS(self): + dom = Document() + child = dom.appendChild( + dom.createElementNS("http://www.python.org", "python:abc")) + child.setAttributeNS("http://www.w3.org", "xmlns:python", + "http://www.python.org") + child.setAttributeNS("http://www.python.org", "python:abcattr", "foo") + self.assertEqual(len(child.attributes), 2) + child.removeAttributeNS("http://www.python.org", "abcattr") + self.assertEqual(len(child.attributes), 1) - dom.unlink() + dom.unlink() -def testRemoveAttrNS(): - dom = Document() - child = dom.appendChild( - dom.createElementNS("http://www.python.org", "python:abc")) - child.setAttributeNS("http://www.w3.org", "xmlns:python", - "http://www.python.org") - child.setAttributeNS("http://www.python.org", "python:abcattr", "foo") - confirm(len(child.attributes) == 2) - child.removeAttributeNS("http://www.python.org", "abcattr") - confirm(len(child.attributes) == 1) + def testRemoveAttributeNode(self): + dom = Document() + child = dom.appendChild(dom.createElement("foo")) + child.setAttribute("spam", "jam") + self.assertEqual(len(child.attributes), 1) + node = child.getAttributeNode("spam") + child.removeAttributeNode(node) + self.assertEqual(len(child.attributes), 0) + self.assert_(child.getAttributeNode("spam") is None) - dom.unlink() + dom.unlink() -def testRemoveAttributeNode(): - dom = Document() - child = dom.appendChild(dom.createElement("foo")) - child.setAttribute("spam", "jam") - confirm(len(child.attributes) == 1) - node = child.getAttributeNode("spam") - child.removeAttributeNode(node) - confirm(len(child.attributes) == 0 - and child.getAttributeNode("spam") is None) + def testChangeAttr(self): + dom = parseString("") + el = dom.documentElement + el.setAttribute("spam", "jam") + self.assertEqual(len(el.attributes), 1) + el.setAttribute("spam", "bam") + # Set this attribute to be an ID and make sure that doesn't change + # when changing the value: + el.setIdAttribute("spam") + self.assertEqual(len(el.attributes), 1) + self.assertEqual(el.attributes["spam"].value, "bam") + self.assertEqual(el.attributes["spam"].nodeValue, "bam") + self.assertEqual(el.getAttribute("spam"), "bam") + self.assert_(el.getAttributeNode("spam").isId) + el.attributes["spam"] = "ham" + self.assertEqual(len(el.attributes), 1) + self.assertEqual(el.attributes["spam"].value, "ham") + self.assertEqual(el.attributes["spam"].nodeValue, "ham") + self.assertEqual(el.getAttribute("spam"), "ham") + self.assert_(el.attributes["spam"].isId) + el.setAttribute("spam2", "bam") + self.assertEqual(len(el.attributes), 2) + self.assertEqual(el.attributes["spam"].value, "ham") + self.assertEqual(el.attributes["spam"].nodeValue, "ham") + self.assertEqual(el.getAttribute("spam"), "ham") + self.assertEqual(el.attributes["spam2"].value, "bam") + self.assertEqual(el.attributes["spam2"].nodeValue, "bam") + self.assertEqual(el.getAttribute("spam2"), "bam") + el.attributes["spam2"] = "bam2" + self.assertEqual(len(el.attributes), 2) + self.assertEqual(el.attributes["spam"].value, "ham") + self.assertEqual(el.attributes["spam"].nodeValue, "ham") + self.assertEqual(el.getAttribute("spam"), "ham") + self.assertEqual(el.attributes["spam2"].value, "bam2") + self.assertEqual(el.attributes["spam2"].nodeValue, "bam2") + self.assertEqual(el.getAttribute("spam2"), "bam2") + dom.unlink() - dom.unlink() + def testGetAttrList(self): + pass -def testChangeAttr(): - dom = parseString("") - el = dom.documentElement - el.setAttribute("spam", "jam") - confirm(len(el.attributes) == 1) - el.setAttribute("spam", "bam") - # Set this attribute to be an ID and make sure that doesn't change - # when changing the value: - el.setIdAttribute("spam") - confirm(len(el.attributes) == 1 - and el.attributes["spam"].value == "bam" - and el.attributes["spam"].nodeValue == "bam" - and el.getAttribute("spam") == "bam" - and el.getAttributeNode("spam").isId) - el.attributes["spam"] = "ham" - confirm(len(el.attributes) == 1 - and el.attributes["spam"].value == "ham" - and el.attributes["spam"].nodeValue == "ham" - and el.getAttribute("spam") == "ham" - and el.attributes["spam"].isId) - el.setAttribute("spam2", "bam") - confirm(len(el.attributes) == 2 - and el.attributes["spam"].value == "ham" - and el.attributes["spam"].nodeValue == "ham" - and el.getAttribute("spam") == "ham" - and el.attributes["spam2"].value == "bam" - and el.attributes["spam2"].nodeValue == "bam" - and el.getAttribute("spam2") == "bam") - el.attributes["spam2"] = "bam2" - confirm(len(el.attributes) == 2 - and el.attributes["spam"].value == "ham" - and el.attributes["spam"].nodeValue == "ham" - and el.getAttribute("spam") == "ham" - and el.attributes["spam2"].value == "bam2" - and el.attributes["spam2"].nodeValue == "bam2" - and el.getAttribute("spam2") == "bam2") - dom.unlink() + def testGetAttrValues(self): pass -def testGetAttrList(): - pass + def testGetAttrLength(self): pass -def testGetAttrValues(): pass + def testGetAttribute(self): pass -def testGetAttrLength(): pass + def testGetAttributeNS(self): pass -def testGetAttribute(): pass + def testGetAttributeNode(self): pass -def testGetAttributeNS(): pass + def testGetElementsByTagNameNS(self): + d=""" + + """ + dom = parseString(d) + elems = dom.getElementsByTagNameNS( + "http://pyxml.sf.net/minidom", "myelem") + self.assertEqual(len(elems), 1) + self.assertEqual(elems[0].namespaceURI, "http://pyxml.sf.net/minidom") + self.assertEqual(elems[0].localName, "myelem") + self.assertEqual(elems[0].prefix, "minidom") + self.assertEqual(elems[0].tagName, "minidom:myelem") + self.assertEqual(elems[0].nodeName, "minidom:myelem") + dom.unlink() -def testGetAttributeNode(): pass + def get_empty_nodelist_from_elements_by_tagName_ns_helper( + self, doc, nsuri, lname): + nodelist = doc.getElementsByTagNameNS(nsuri, lname) + self.assertEqual(len(nodelist), 0) -def testGetElementsByTagNameNS(): - d=""" - - """ - dom = parseString(d) - elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom", "myelem") - confirm(len(elems) == 1 - and elems[0].namespaceURI == "http://pyxml.sf.net/minidom" - and elems[0].localName == "myelem" - and elems[0].prefix == "minidom" - and elems[0].tagName == "minidom:myelem" - and elems[0].nodeName == "minidom:myelem") - dom.unlink() + def testGetEmptyNodeListFromElementsByTagNameNS(self): + doc = parseString('') + self.get_empty_nodelist_from_elements_by_tagName_ns_helper( + doc, 'http://xml.python.org/namespaces/a', 'localname') + self.get_empty_nodelist_from_elements_by_tagName_ns_helper( + doc, '*', 'splat') + self.get_empty_nodelist_from_elements_by_tagName_ns_helper( + doc, 'http://xml.python.org/namespaces/a', '*') + doc.unlink() -def get_empty_nodelist_from_elements_by_tagName_ns_helper(doc, nsuri, lname): - nodelist = doc.getElementsByTagNameNS(nsuri, lname) - confirm(len(nodelist) == 0) + doc = parseString('') + self.get_empty_nodelist_from_elements_by_tagName_ns_helper( + doc, "http://xml.python.org/splat", "not-there") + self.get_empty_nodelist_from_elements_by_tagName_ns_helper( + doc, "*", "not-there") + self.get_empty_nodelist_from_elements_by_tagName_ns_helper( + doc, "http://somewhere.else.net/not-there", "e") + doc.unlink() -def testGetEmptyNodeListFromElementsByTagNameNS(): - doc = parseString('') - get_empty_nodelist_from_elements_by_tagName_ns_helper( - doc, 'http://xml.python.org/namespaces/a', 'localname') - get_empty_nodelist_from_elements_by_tagName_ns_helper( - doc, '*', 'splat') - get_empty_nodelist_from_elements_by_tagName_ns_helper( - doc, 'http://xml.python.org/namespaces/a', '*') + def testElementReprAndStr(self): + dom = Document() + el = dom.appendChild(dom.createElement("abc")) + string1 = repr(el) + string2 = str(el) + self.assertEqual(string1, string2) + dom.unlink() - doc = parseString('') - get_empty_nodelist_from_elements_by_tagName_ns_helper( - doc, "http://xml.python.org/splat", "not-there") - get_empty_nodelist_from_elements_by_tagName_ns_helper( - doc, "*", "not-there") - get_empty_nodelist_from_elements_by_tagName_ns_helper( - doc, "http://somewhere.else.net/not-there", "e") + def testElementReprAndStrUnicode(self): + dom = Document() + el = dom.appendChild(dom.createElement(u"abc")) + string1 = repr(el) + string2 = str(el) + self.assertEqual(string1, string2) + dom.unlink() -def testElementReprAndStr(): - dom = Document() - el = dom.appendChild(dom.createElement("abc")) - string1 = repr(el) - string2 = str(el) - confirm(string1 == string2) - dom.unlink() + def testElementReprAndStrUnicodeNS(self): + dom = Document() + el = dom.appendChild( + dom.createElementNS(u"http://www.slashdot.org", u"slash:abc")) + string1 = repr(el) + string2 = str(el) + self.assertEqual(string1, string2) + self.assert_("slash:abc" in string1) + dom.unlink() -# commented out until Fredrick's fix is checked in -def _testElementReprAndStrUnicode(): - dom = Document() - el = dom.appendChild(dom.createElement(u"abc")) - string1 = repr(el) - string2 = str(el) - confirm(string1 == string2) - dom.unlink() + def testAttributeRepr(self): + dom = Document() + el = dom.appendChild(dom.createElement(u"abc")) + node = el.setAttribute("abc", "def") + self.assertEqual(str(node), repr(node)) + dom.unlink() -# commented out until Fredrick's fix is checked in -def _testElementReprAndStrUnicodeNS(): - dom = Document() - el = dom.appendChild( - dom.createElementNS(u"http://www.slashdot.org", u"slash:abc")) - string1 = repr(el) - string2 = str(el) - confirm(string1 == string2) - confirm(string1.find("slash:abc") != -1) - dom.unlink() + def testTextNodeRepr(self): pass -def testAttributeRepr(): - dom = Document() - el = dom.appendChild(dom.createElement(u"abc")) - node = el.setAttribute("abc", "def") - confirm(str(node) == repr(node)) - dom.unlink() + def testWriteXML(self): + str = '' + dom = parseString(str) + domstr = dom.toxml() + dom.unlink() + self.assertEqual(str, domstr) -def testTextNodeRepr(): pass + def testAltNewline(self): + str = '\n\n' + dom = parseString(str) + domstr = dom.toprettyxml(newl="\r\n") + dom.unlink() + self.assertEqual(domstr, str.replace("\n", "\r\n")) -def testWriteXML(): - str = '' - dom = parseString(str) - domstr = dom.toxml() - dom.unlink() - confirm(str == domstr) + def testProcessingInstruction(self): + dom = parseString('') + pi = dom.documentElement.firstChild + self.assertEqual(pi.target, "mypi") + self.assertEqual(pi.data, "data \t\n ") + self.assertEqual(pi.nodeName, "mypi") + self.assertEqual(pi.nodeType, Node.PROCESSING_INSTRUCTION_NODE) + self.assert_(pi.attributes is None) + self.assert_(not pi.hasChildNodes()) + self.assertEqual(len(pi.childNodes), 0) + self.assert_(pi.firstChild is None) + self.assert_(pi.lastChild is None) + self.assert_(pi.localName is None) + self.assertEqual(pi.namespaceURI, xml.dom.EMPTY_NAMESPACE) + dom.unlink() -def testAltNewline(): - str = '\n\n' - dom = parseString(str) - domstr = dom.toprettyxml(newl="\r\n") - dom.unlink() - confirm(domstr == str.replace("\n", "\r\n")) + def testProcessingInstructionRepr(self): pass -def testProcessingInstruction(): - dom = parseString('') - pi = dom.documentElement.firstChild - confirm(pi.target == "mypi" - and pi.data == "data \t\n " - and pi.nodeName == "mypi" - and pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE - and pi.attributes is None - and not pi.hasChildNodes() - and len(pi.childNodes) == 0 - and pi.firstChild is None - and pi.lastChild is None - and pi.localName is None - and pi.namespaceURI == xml.dom.EMPTY_NAMESPACE) + def testTextRepr(self): pass -def testProcessingInstructionRepr(): pass + def testWriteText(self): pass -def testTextRepr(): pass + def testTooManyDocumentElements(self): + doc = parseString("") + elem = doc.createElement("extra") + self.assertRaises( + xml.dom.HierarchyRequestErr, + doc.appendChild, elem) + elem.unlink() + doc.unlink() -def testWriteText(): pass + def testCreateElementNS(self): pass -def testDocumentElement(): pass + def testCreateAttributeNS(self): pass -def testTooManyDocumentElements(): - doc = parseString("") - elem = doc.createElement("extra") - try: - doc.appendChild(elem) - except xml.dom.HierarchyRequestErr: - pass - else: - print "Failed to catch expected exception when" \ - " adding extra document element." - elem.unlink() - doc.unlink() + def testParse(self): pass -def testCreateElementNS(): pass + def testParseString(self): pass -def testCreateAttributeNS(): pass + def testComment(self): pass -def testParse(): pass + def testAttrListItem(self): pass -def testParseString(): pass + def testAttrListItems(self): pass -def testComment(): pass + def testAttrListItemNS(self): pass -def testAttrListItem(): pass + def testAttrListKeys(self): pass -def testAttrListItems(): pass + def testAttrListKeysNS(self): pass -def testAttrListItemNS(): pass + def testRemoveNamedItem(self): + doc = parseString("") + e = doc.documentElement + attrs = e.attributes + a1 = e.getAttributeNode("a") + a2 = attrs.removeNamedItem("a") + self.assert_(a1.isSameNode(a2)) + self.assertRaises( + xml.dom.NotFoundErr, + attrs.removeNamedItem, "a") + doc.unlink() -def testAttrListKeys(): pass + def testRemoveNamedItemNS(self): + doc = parseString("") + e = doc.documentElement + attrs = e.attributes + a1 = e.getAttributeNodeNS("http://xml.python.org/", "b") + a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b") + self.assert_(a1.isSameNode(a2)) + self.assertRaises( + xml.dom.NotFoundErr, + attrs.removeNamedItemNS, "http://xml.python.org/", "b") + doc.unlink() -def testAttrListKeysNS(): pass + def testAttrListValues(self): pass -def testRemoveNamedItem(): - doc = parseString("") - e = doc.documentElement - attrs = e.attributes - a1 = e.getAttributeNode("a") - a2 = attrs.removeNamedItem("a") - confirm(a1.isSameNode(a2)) - try: - attrs.removeNamedItem("a") - except xml.dom.NotFoundErr: - pass + def testAttrListLength(self): pass -def testRemoveNamedItemNS(): - doc = parseString("") - e = doc.documentElement - attrs = e.attributes - a1 = e.getAttributeNodeNS("http://xml.python.org/", "b") - a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b") - confirm(a1.isSameNode(a2)) - try: - attrs.removeNamedItemNS("http://xml.python.org/", "b") - except xml.dom.NotFoundErr: - pass + def testAttrList__getitem__(self): pass -def testAttrListValues(): pass + def testAttrList__setitem__(self): pass -def testAttrListLength(): pass + def testSetAttrValueandNodeValue(self): pass -def testAttrList__getitem__(): pass + def testParseElement(self): pass -def testAttrList__setitem__(): pass + def testParseAttributes(self): pass -def testSetAttrValueandNodeValue(): pass + def testParseElementNamespaces(self): pass -def testParseElement(): pass + def testParseAttributeNamespaces(self): pass -def testParseAttributes(): pass + def testParseProcessingInstructions(self): pass -def testParseElementNamespaces(): pass + def testChildNodes(self): pass -def testParseAttributeNamespaces(): pass + def testFirstChild(self): pass -def testParseProcessingInstructions(): pass + def testHasChildNodes(self): pass -def testChildNodes(): pass + def testCloneElementShallow(self): + dom, clone = self._setupCloneElement(0) + self.assertEqual(len(clone.childNodes), 0) + self.assertEqual(clone.childNodes.length, 0) + self.assertEqual(clone.parentNode, None) + self.assertEqual(clone.toxml(), '') + dom.unlink() + clone.unlink() -def testFirstChild(): pass + def testCloneElementDeep(self): + dom, clone = self._setupCloneElement(1) + self.assertEqual(len(clone.childNodes), 1) + self.assertEqual(clone.childNodes.length, 1) + self.assertEqual(clone.parentNode, None) + self.assertEqual(clone.toxml(), '') + dom.unlink() + clone.unlink() -def testHasChildNodes(): pass + def _setupCloneElement(self, deep): + dom = parseString("") + root = dom.documentElement + clone = root.cloneNode(deep) + self._checkCloneElementCopiesAttributes( + root, clone, "testCloneElement" + (deep and "Deep" or "Shallow")) + # mutilate the original so shared data is detected + root.tagName = root.nodeName = "MODIFIED" + root.setAttribute("attr", "NEW VALUE") + root.setAttribute("added", "VALUE") + return dom, clone -def testCloneElementShallow(): - dom, clone = _setupCloneElement(0) - confirm(len(clone.childNodes) == 0 - and clone.childNodes.length == 0 - and clone.parentNode is None - and clone.toxml() == '' - , "testCloneElementShallow") - dom.unlink() + def _checkCloneElementCopiesAttributes(self, e1, e2, test): + attrs1 = e1.attributes + attrs2 = e2.attributes + keys1 = attrs1.keys() + keys2 = attrs2.keys() + keys1.sort() + keys2.sort() + self.assertEqual(keys1, keys2, + "clone of element has same attribute keys") + for i in range(len(keys1)): + a1 = attrs1.item(i) + a2 = attrs2.item(i) + self.assert_(a1 is not a2) + self.assertEqual(a1.value, a2.value) + self.assertEqual(a1.nodeValue, a2.nodeValue) + self.assertEqual(a1.namespaceURI, a2.namespaceURI) + self.assertEqual(a1.localName, a2.localName) + self.assert_(a2.ownerElement is e2, + "clone of attribute node correctly owned") -def testCloneElementDeep(): - dom, clone = _setupCloneElement(1) - confirm(len(clone.childNodes) == 1 - and clone.childNodes.length == 1 - and clone.parentNode is None - and clone.toxml() == '' - , "testCloneElementDeep") - dom.unlink() + def testCloneDocumentShallow(self): + doc = parseString( + "\n" + "" + "\n" + "]>\n" + "") + doc2 = doc.cloneNode(0) + self.assert_(doc2 is None, + "testCloneDocumentShallow:" + " shallow cloning of documents makes no sense!") + doc.unlink() -def _setupCloneElement(deep): - dom = parseString("") - root = dom.documentElement - clone = root.cloneNode(deep) - _testCloneElementCopiesAttributes( - root, clone, "testCloneElement" + (deep and "Deep" or "Shallow")) - # mutilate the original so shared data is detected - root.tagName = root.nodeName = "MODIFIED" - root.setAttribute("attr", "NEW VALUE") - root.setAttribute("added", "VALUE") - return dom, clone - -def _testCloneElementCopiesAttributes(e1, e2, test): - attrs1 = e1.attributes - attrs2 = e2.attributes - keys1 = attrs1.keys() - keys2 = attrs2.keys() - keys1.sort() - keys2.sort() - confirm(keys1 == keys2, "clone of element has same attribute keys") - for i in range(len(keys1)): - a1 = attrs1.item(i) - a2 = attrs2.item(i) - confirm(a1 is not a2 - and a1.value == a2.value - and a1.nodeValue == a2.nodeValue - and a1.namespaceURI == a2.namespaceURI - and a1.localName == a2.localName - , "clone of attribute node has proper attribute values") - confirm(a2.ownerElement is e2, - "clone of attribute node correctly owned") - -def testCloneDocumentShallow(): - doc = parseString("\n" - "" - "\n" - "]>\n" - "") - doc2 = doc.cloneNode(0) - confirm(doc2 is None, - "testCloneDocumentShallow:" - " shallow cloning of documents makes no sense!") - -def testCloneDocumentDeep(): - doc = parseString("\n" - "" - "\n" - "]>\n" - "") - doc2 = doc.cloneNode(1) - confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)), + def testCloneDocumentDeep(self): + doc = parseString( + "\n" + "" + "\n" + "]>\n" + "") + doc2 = doc.cloneNode(1) + self.failIf( + doc.isSameNode(doc2) or doc2.isSameNode(doc), "testCloneDocumentDeep: document objects not distinct") - confirm(len(doc.childNodes) == len(doc2.childNodes), + self.assertEqual( + len(doc.childNodes), len(doc2.childNodes), "testCloneDocumentDeep: wrong number of Document children") - confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE, + self.assertEqual( + doc2.documentElement.nodeType, Node.ELEMENT_NODE, "testCloneDocumentDeep: documentElement not an ELEMENT_NODE") - confirm(doc2.documentElement.ownerDocument.isSameNode(doc2), + self.assert_( + doc2.documentElement.ownerDocument.isSameNode(doc2), "testCloneDocumentDeep: documentElement owner is not new document") - confirm(not doc.documentElement.isSameNode(doc2.documentElement), + self.failIf( + doc.documentElement.isSameNode(doc2.documentElement), "testCloneDocumentDeep: documentElement should not be shared") - if doc.doctype is not None: - # check the doctype iff the original DOM maintained it - confirm(doc2.doctype.nodeType == Node.DOCUMENT_TYPE_NODE, - "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE") - confirm(doc2.doctype.ownerDocument.isSameNode(doc2)) - confirm(not doc.doctype.isSameNode(doc2.doctype)) + if doc.doctype is not None: + # check the doctype iff the original DOM maintained it + self.assertEqual(doc2.doctype.nodeType, Node.DOCUMENT_TYPE_NODE, + "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE") + self.assert_(doc2.doctype.ownerDocument.isSameNode(doc2)) + self.failIf(doc.doctype.isSameNode(doc2.doctype)) + doc.unlink() + doc2.unlink() -def testCloneDocumentTypeDeepOk(): - doctype = create_nonempty_doctype() - clone = doctype.cloneNode(1) - confirm(clone is not None - and clone.nodeName == doctype.nodeName - and clone.name == doctype.name - and clone.publicId == doctype.publicId - and clone.systemId == doctype.systemId - and len(clone.entities) == len(doctype.entities) - and clone.entities.item(len(clone.entities)) is None - and len(clone.notations) == len(doctype.notations) - and clone.notations.item(len(clone.notations)) is None - and len(clone.childNodes) == 0) - for i in range(len(doctype.entities)): - se = doctype.entities.item(i) - ce = clone.entities.item(i) - confirm((not se.isSameNode(ce)) - and (not ce.isSameNode(se)) - and ce.nodeName == se.nodeName - and ce.notationName == se.notationName - and ce.publicId == se.publicId - and ce.systemId == se.systemId - and ce.encoding == se.encoding - and ce.actualEncoding == se.actualEncoding - and ce.version == se.version) - for i in range(len(doctype.notations)): - sn = doctype.notations.item(i) - cn = clone.notations.item(i) - confirm((not sn.isSameNode(cn)) - and (not cn.isSameNode(sn)) - and cn.nodeName == sn.nodeName - and cn.publicId == sn.publicId - and cn.systemId == sn.systemId) + def testCloneDocumentTypeDeepOk(self): + doctype = self.create_nonempty_doctype() + clone = doctype.cloneNode(1) + self.assert_(clone is not None) + self.assertEqual(clone.nodeName, doctype.nodeName) + self.assertEqual(clone.name, doctype.name) + self.assertEqual(clone.publicId, doctype.publicId) + self.assertEqual(clone.systemId, doctype.systemId) + self.assertEqual(len(clone.entities), len(doctype.entities)) + self.assert_(clone.entities.item(len(clone.entities)) is None) + self.assertEqual(len(clone.notations), len(doctype.notations)) + self.assert_(clone.notations.item(len(clone.notations)) is None) + self.assertEqual(len(clone.childNodes), 0) + for i in range(len(doctype.entities)): + se = doctype.entities.item(i) + ce = clone.entities.item(i) + self.failIf(se.isSameNode(ce)) + self.failIf(ce.isSameNode(se)) + self.assertEqual(ce.nodeName, se.nodeName) + self.assertEqual(ce.notationName, se.notationName) + self.assertEqual(ce.publicId, se.publicId) + self.assertEqual(ce.systemId, se.systemId) + self.assertEqual(ce.encoding, se.encoding) + self.assertEqual(ce.actualEncoding, se.actualEncoding) + self.assertEqual(ce.version, se.version) + for i in range(len(doctype.notations)): + sn = doctype.notations.item(i) + cn = clone.notations.item(i) + self.failIf(sn.isSameNode(cn)) + self.failIf(cn.isSameNode(sn)) + self.assertEqual(cn.nodeName, sn.nodeName) + self.assertEqual(cn.publicId, sn.publicId) + self.assertEqual(cn.systemId, sn.systemId) + doctype.unlink() + clone.unlink() -def testCloneDocumentTypeDeepNotOk(): - doc = create_doc_with_doctype() - clone = doc.doctype.cloneNode(1) - confirm(clone is None, "testCloneDocumentTypeDeepNotOk") + def testCloneDocumentTypeDeepNotOk(self): + doc = self.create_doc_with_doctype() + clone = doc.doctype.cloneNode(1) + self.assert_(clone is None) + doc.unlink() -def testCloneDocumentTypeShallowOk(): - doctype = create_nonempty_doctype() - clone = doctype.cloneNode(0) - confirm(clone is not None - and clone.nodeName == doctype.nodeName - and clone.name == doctype.name - and clone.publicId == doctype.publicId - and clone.systemId == doctype.systemId - and len(clone.entities) == 0 - and clone.entities.item(0) is None - and len(clone.notations) == 0 - and clone.notations.item(0) is None - and len(clone.childNodes) == 0) + def testCloneDocumentTypeShallowOk(self): + doctype = self.create_nonempty_doctype() + clone = doctype.cloneNode(0) + self.assert_(clone is not None) + self.assertEqual(clone.nodeName, doctype.nodeName) + self.assertEqual(clone.name, doctype.name) + self.assertEqual(clone.publicId, doctype.publicId) + self.assertEqual(clone.systemId, doctype.systemId) + self.assertEqual(len(clone.entities), 0) + self.assert_(clone.entities.item(0) is None) + self.assertEqual(len(clone.notations), 0) + self.assert_(clone.notations.item(0) is None) + self.assertEqual(len(clone.childNodes), 0) + doctype.unlink() + clone.unlink() -def testCloneDocumentTypeShallowNotOk(): - doc = create_doc_with_doctype() - clone = doc.doctype.cloneNode(0) - confirm(clone is None, "testCloneDocumentTypeShallowNotOk") + def testCloneDocumentTypeShallowNotOk(self): + doc = self.create_doc_with_doctype() + clone = doc.doctype.cloneNode(0) + self.assert_(clone is None) + doc.unlink() -def check_import_document(deep, testName): - doc1 = parseString("") - doc2 = parseString("") - try: - doc1.importNode(doc2, deep) - except xml.dom.NotSupportedErr: - pass - else: - raise Exception(testName + - ": expected NotSupportedErr when importing a document") + def check_import_document(self, deep): + doc1 = parseString("") + doc2 = parseString("") + self.assertRaises( + xml.dom.NotSupportedErr, + doc1.importNode, doc2, deep) + doc1.unlink() + doc2.unlink() -def testImportDocumentShallow(): - check_import_document(0, "testImportDocumentShallow") + def testImportDocumentShallow(self): + self.check_import_document(0) -def testImportDocumentDeep(): - check_import_document(1, "testImportDocumentDeep") + def testImportDocumentDeep(self): + self.check_import_document(1) -# The tests of DocumentType importing use these helpers to construct -# the documents to work with, since not all DOM builders actually -# create the DocumentType nodes. + # The tests of DocumentType importing use these helpers to construct + # the documents to work with, since not all DOM builders actually + # create the DocumentType nodes. -def create_doc_without_doctype(doctype=None): - return getDOMImplementation().createDocument(None, "doc", doctype) + def create_doc_without_doctype(self, doctype=None): + return getDOMImplementation().createDocument(None, "doc", doctype) -def create_nonempty_doctype(): - doctype = getDOMImplementation().createDocumentType("doc", None, None) - doctype.entities._seq = [] - doctype.notations._seq = [] - notation = xml.dom.minidom.Notation("my-notation", None, - "http://xml.python.org/notations/my") - doctype.notations._seq.append(notation) - entity = xml.dom.minidom.Entity("my-entity", None, - "http://xml.python.org/entities/my", - "my-notation") - entity.version = "1.0" - entity.encoding = "utf-8" - entity.actualEncoding = "us-ascii" - doctype.entities._seq.append(entity) - return doctype + def create_nonempty_doctype(self): + doctype = getDOMImplementation().createDocumentType("doc", None, None) + doctype.entities._seq = [] + doctype.notations._seq = [] + notation = xml.dom.minidom.Notation("my-notation", None, + "http://xml.python.org/notations/my") + doctype.notations._seq.append(notation) + entity = xml.dom.minidom.Entity("my-entity", None, + "http://xml.python.org/entities/my", + "my-notation") + entity.version = "1.0" + entity.encoding = "utf-8" + entity.actualEncoding = "us-ascii" + doctype.entities._seq.append(entity) + return doctype -def create_doc_with_doctype(): - doctype = create_nonempty_doctype() - doc = create_doc_without_doctype(doctype) - doctype.entities.item(0).ownerDocument = doc - doctype.notations.item(0).ownerDocument = doc - return doc + def create_doc_with_doctype(self): + doctype = self.create_nonempty_doctype() + doc = self.create_doc_without_doctype(doctype) + doctype.entities.item(0).ownerDocument = doc + doctype.notations.item(0).ownerDocument = doc + return doc -def testImportDocumentTypeShallow(): - src = create_doc_with_doctype() - target = create_doc_without_doctype() - try: - imported = target.importNode(src.doctype, 0) - except xml.dom.NotSupportedErr: - pass - else: - raise Exception( - "testImportDocumentTypeShallow: expected NotSupportedErr") + def testImportDocumentTypeShallow(self): + src = self.create_doc_with_doctype() + target = self.create_doc_without_doctype() + self.assertRaises( + xml.dom.NotSupportedErr, + target.importNode, src.doctype, 0) + src.unlink() + target.unlink() -def testImportDocumentTypeDeep(): - src = create_doc_with_doctype() - target = create_doc_without_doctype() - try: - imported = target.importNode(src.doctype, 1) - except xml.dom.NotSupportedErr: - pass - else: - raise Exception( - "testImportDocumentTypeDeep: expected NotSupportedErr") + def testImportDocumentTypeDeep(self): + src = self.create_doc_with_doctype() + target = self.create_doc_without_doctype() + self.assertRaises( + xml.dom.NotSupportedErr, + target.importNode, src.doctype, 1) + src.unlink() + target.unlink() -# Testing attribute clones uses a helper, and should always be deep, -# even if the argument to cloneNode is false. -def check_clone_attribute(deep, testName): - doc = parseString("") - attr = doc.documentElement.getAttributeNode("attr") - assert attr is not None - clone = attr.cloneNode(deep) - confirm(not clone.isSameNode(attr)) - confirm(not attr.isSameNode(clone)) - confirm(clone.ownerElement is None, - testName + ": ownerElement should be None") - confirm(clone.ownerDocument.isSameNode(attr.ownerDocument), - testName + ": ownerDocument does not match") - confirm(clone.specified, - testName + ": cloned attribute must have specified == True") + # Testing attribute clones uses a helper, and should always be deep, + # even if the argument to cloneNode is false. + def check_clone_attribute(self, deep, testName): + doc = parseString("") + attr = doc.documentElement.getAttributeNode("attr") + assert attr is not None + clone = attr.cloneNode(deep) + self.failIf(clone.isSameNode(attr)) + self.failIf(attr.isSameNode(clone)) + self.assert_(clone.ownerElement is None, + testName + ": ownerElement should be None") + self.assert_(clone.ownerDocument.isSameNode(attr.ownerDocument), + testName + ": ownerDocument does not match") + self.assert_(clone.specified, + testName + ": cloned attribute must have specified == True") + doc.unlink() -def testCloneAttributeShallow(): - check_clone_attribute(0, "testCloneAttributeShallow") + def testCloneAttributeShallow(self): + self.check_clone_attribute(0, "testCloneAttributeShallow") -def testCloneAttributeDeep(): - check_clone_attribute(1, "testCloneAttributeDeep") + def testCloneAttributeDeep(self): + self.check_clone_attribute(1, "testCloneAttributeDeep") -def check_clone_pi(deep, testName): - doc = parseString("") - pi = doc.firstChild - assert pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE - clone = pi.cloneNode(deep) - confirm(clone.target == pi.target - and clone.data == pi.data) + def check_clone_pi(self, deep, testName): + doc = parseString("") + pi = doc.firstChild + self.assertEqual(pi.nodeType, Node.PROCESSING_INSTRUCTION_NODE) + clone = pi.cloneNode(deep) + self.assertEqual(clone.target, pi.target) + self.assertEqual(clone.data, pi.data) + doc.unlink() -def testClonePIShallow(): - check_clone_pi(0, "testClonePIShallow") + def testClonePIShallow(self): + self.check_clone_pi(0, "testClonePIShallow") -def testClonePIDeep(): - check_clone_pi(1, "testClonePIDeep") + def testClonePIDeep(self): + self.check_clone_pi(1, "testClonePIDeep") -def testNormalize(): - doc = parseString("") - root = doc.documentElement - root.appendChild(doc.createTextNode("first")) - root.appendChild(doc.createTextNode("second")) - confirm(len(root.childNodes) == 2 - and root.childNodes.length == 2, "testNormalize -- preparation") - doc.normalize() - confirm(len(root.childNodes) == 1 - and root.childNodes.length == 1 - and root.firstChild is root.lastChild - and root.firstChild.data == "firstsecond" - , "testNormalize -- result") - doc.unlink() + def testNormalize(self): + doc = parseString("") + root = doc.documentElement + root.appendChild(doc.createTextNode("first")) + root.appendChild(doc.createTextNode("second")) + self.assertEqual(len(root.childNodes), 2) + self.assertEqual(root.childNodes.length, 2) + doc.normalize() + self.assertEqual(len(root.childNodes), 1) + self.assertEqual(root.childNodes.length, 1) + self.assert_(root.firstChild is root.lastChild) + self.assertEqual(root.firstChild.data, "firstsecond") + doc.unlink() - doc = parseString("") - root = doc.documentElement - root.appendChild(doc.createTextNode("")) - doc.normalize() - confirm(len(root.childNodes) == 0 - and root.childNodes.length == 0, - "testNormalize -- single empty node removed") - doc.unlink() + doc = parseString("") + root = doc.documentElement + root.appendChild(doc.createTextNode("")) + doc.normalize() + self.assertEqual(len(root.childNodes), 0) + self.assertEqual(root.childNodes.length, 0) + doc.unlink() -def testSiblings(): - doc = parseString("text?") - root = doc.documentElement - (pi, text, elm) = root.childNodes + def testSiblings(self): + doc = parseString("text?") + root = doc.documentElement + (pi, text, elm) = root.childNodes - confirm(pi.nextSibling is text and - pi.previousSibling is None and - text.nextSibling is elm and - text.previousSibling is pi and - elm.nextSibling is None and - elm.previousSibling is text, "testSiblings") + self.assert_(pi.nextSibling is text) + self.assert_(pi.previousSibling is None) + self.assert_(text.nextSibling is elm) + self.assert_(text.previousSibling is pi) + self.assert_(elm.nextSibling is None) + self.assert_(elm.previousSibling is text) - doc.unlink() + doc.unlink() -def testParents(): - doc = parseString("") - root = doc.documentElement - elm1 = root.childNodes[0] - (elm2a, elm2b) = elm1.childNodes - elm3 = elm2b.childNodes[0] + def testParents(self): + doc = parseString("") + root = doc.documentElement + elm1 = root.childNodes[0] + (elm2a, elm2b) = elm1.childNodes + elm3 = elm2b.childNodes[0] - confirm(root.parentNode is doc and - elm1.parentNode is root and - elm2a.parentNode is elm1 and - elm2b.parentNode is elm1 and - elm3.parentNode is elm2b, "testParents") + self.assert_(root.parentNode is doc) + self.assert_(elm1.parentNode is root) + self.assert_(elm2a.parentNode is elm1) + self.assert_(elm2b.parentNode is elm1) + self.assert_(elm3.parentNode is elm2b) - doc.unlink() + doc.unlink() -def testNodeListItem(): - doc = parseString("") - children = doc.childNodes - docelem = children[0] - confirm(children[0] is children.item(0) - and children.item(1) is None - and docelem.childNodes.item(0) is docelem.childNodes[0] - and docelem.childNodes.item(1) is docelem.childNodes[1] - and docelem.childNodes.item(0).childNodes.item(0) is None, - "test NodeList.item()") - doc.unlink() + def testNodeListItem(self): + doc = parseString("") + children = doc.childNodes + docelem = children[0] + self.assert_(children[0] is children.item(0)) + self.assert_(children.item(1) is None) + self.assert_(docelem.childNodes.item(0) is docelem.childNodes[0]) + self.assert_(docelem.childNodes.item(1) is docelem.childNodes[1]) + self.assert_(docelem.childNodes.item(0).childNodes.item(0) is None) + doc.unlink() -def testSAX2DOM(): - from xml.dom import pulldom + def testSAX2DOM(self): + from xml.dom import pulldom - sax2dom = pulldom.SAX2DOM() - sax2dom.startDocument() - sax2dom.startElement("doc", {}) - sax2dom.characters("text") - sax2dom.startElement("subelm", {}) - sax2dom.characters("text") - sax2dom.endElement("subelm") - sax2dom.characters("text") - sax2dom.endElement("doc") - sax2dom.endDocument() + sax2dom = pulldom.SAX2DOM() + sax2dom.startDocument() + sax2dom.startElement("doc", {}) + sax2dom.characters("text") + sax2dom.startElement("subelm", {}) + sax2dom.characters("text") + sax2dom.endElement("subelm") + sax2dom.characters("text") + sax2dom.endElement("doc") + sax2dom.endDocument() - doc = sax2dom.document - root = doc.documentElement - (text1, elm1, text2) = root.childNodes - text3 = elm1.childNodes[0] + doc = sax2dom.document + root = doc.documentElement + (text1, elm1, text2) = root.childNodes + text3 = elm1.childNodes[0] - confirm(text1.previousSibling is None and - text1.nextSibling is elm1 and - elm1.previousSibling is text1 and - elm1.nextSibling is text2 and - text2.previousSibling is elm1 and - text2.nextSibling is None and - text3.previousSibling is None and - text3.nextSibling is None, "testSAX2DOM - siblings") + self.assert_(text1.previousSibling is None) + self.assert_(text1.nextSibling is elm1) + self.assert_(elm1.previousSibling is text1) + self.assert_(elm1.nextSibling is text2) + self.assert_(text2.previousSibling is elm1) + self.assert_(text2.nextSibling is None) + self.assert_(text3.previousSibling is None) + self.assert_(text3.nextSibling is None) - confirm(root.parentNode is doc and - text1.parentNode is root and - elm1.parentNode is root and - text2.parentNode is root and - text3.parentNode is elm1, "testSAX2DOM - parents") + self.assert_(root.parentNode is doc) + self.assert_(text1.parentNode is root) + self.assert_(elm1.parentNode is root) + self.assert_(text2.parentNode is root) + self.assert_(text3.parentNode is elm1) - doc.unlink() + doc.unlink() -def testEncodings(): - doc = parseString('') - confirm(doc.toxml() == u'\u20ac' - and doc.toxml('utf-8') == '\xe2\x82\xac' - and doc.toxml('iso-8859-15') == '\xa4', - "testEncodings - encoding EURO SIGN") + def testEncodings(self): + # Test encoding euro sign + doc = parseString('') + self.assertEqual( + doc.toxml(), u'\u20ac') + self.assertEqual( + doc.toxml('utf-8'), + '\xe2\x82\xac') + self.assertEqual( + doc.toxml('iso-8859-15'), + '\xa4') + doc.unlink() - # Verify that character decoding errors throw exceptions instead of crashing - try: - doc = parseString('Comment \xe7a va ? Tr\xe8s bien ?') - except UnicodeDecodeError: - pass - else: - print 'parsing with bad encoding should raise a UnicodeDecodeError' + def testDecodingError(self): + # Verify that character decoding errors throw exceptions + # instead of crashing + self.assertRaises( + UnicodeDecodeError, + parseString, + 'Comment \xe7a va ? Tr\xe8s bien ?') - doc.unlink() + def testDecodingError2(self): + self.assertRaises( + UnicodeDecodeError, + parse, + StringIO('')) -class UserDataHandler: - called = 0 - def handle(self, operation, key, data, src, dst): - dst.setUserData(key, data + 1, self) - src.setUserData(key, None, None) - self.called = 1 + def testUserData(self): + dom = Document() + n = dom.createElement('e') + self.assert_(n.getUserData("foo") is None) + n.setUserData("foo", None, None) + self.assert_(n.getUserData("foo") is None) + n.setUserData("foo", 12, 12) + n.setUserData("bar", 13, 13) + self.assertEqual(n.getUserData("foo"), 12) + self.assertEqual(n.getUserData("bar"), 13) + n.setUserData("foo", None, None) + self.assert_(n.getUserData("foo") is None) + self.assertEqual(n.getUserData("bar"), 13) -def testUserData(): - dom = Document() - n = dom.createElement('e') - confirm(n.getUserData("foo") is None) - n.setUserData("foo", None, None) - confirm(n.getUserData("foo") is None) - n.setUserData("foo", 12, 12) - n.setUserData("bar", 13, 13) - confirm(n.getUserData("foo") == 12) - confirm(n.getUserData("bar") == 13) - n.setUserData("foo", None, None) - confirm(n.getUserData("foo") is None) - confirm(n.getUserData("bar") == 13) + class UserDataHandler: + called = 0 + def handle(self, operation, key, data, src, dst): + dst.setUserData(key, data + 1, self) + src.setUserData(key, None, None) + self.called = 1 - handler = UserDataHandler() - n.setUserData("bar", 12, handler) - c = n.cloneNode(1) - confirm(handler.called - and n.getUserData("bar") is None - and c.getUserData("bar") == 13) - n.unlink() - c.unlink() - dom.unlink() + handler = UserDataHandler() + n.setUserData("bar", 12, handler) + c = n.cloneNode(1) + self.assert_(handler.called) + self.assert_(n.getUserData("bar") is None) + self.assertEqual(c.getUserData("bar"), 13) + n.unlink() + c.unlink() + dom.unlink() -def testRenameAttribute(): - doc = parseString("") - elem = doc.documentElement - attrmap = elem.attributes - attr = elem.attributes['a'] + def testRenameAttribute(self): + doc = parseString("") + elem = doc.documentElement + attrmap = elem.attributes + attr = elem.attributes['a'] - # Simple renaming - attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b") - confirm(attr.name == "b" - and attr.nodeName == "b" - and attr.localName is None - and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE - and attr.prefix is None - and attr.value == "v" - and elem.getAttributeNode("a") is None - and elem.getAttributeNode("b").isSameNode(attr) - and attrmap["b"].isSameNode(attr) - and attr.ownerDocument.isSameNode(doc) - and attr.ownerElement.isSameNode(elem)) + # Simple renaming + attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b") + self.assertEqual(attr.name, "b") + self.assertEqual(attr.nodeName, "b") + self.assert_(attr.localName is None) + self.assertEqual(attr.namespaceURI, xml.dom.EMPTY_NAMESPACE) + self.assert_(attr.prefix is None) + self.assertEqual(attr.value, "v") + self.assert_(elem.getAttributeNode("a") is None) + self.assert_(elem.getAttributeNode("b").isSameNode(attr)) + self.assert_(attrmap["b"].isSameNode(attr)) + self.assert_(attr.ownerDocument.isSameNode(doc)) + self.assert_(attr.ownerElement.isSameNode(elem)) - # Rename to have a namespace, no prefix - attr = doc.renameNode(attr, "http://xml.python.org/ns", "c") - confirm(attr.name == "c" - and attr.nodeName == "c" - and attr.localName == "c" - and attr.namespaceURI == "http://xml.python.org/ns" - and attr.prefix is None - and attr.value == "v" - and elem.getAttributeNode("a") is None - and elem.getAttributeNode("b") is None - and elem.getAttributeNode("c").isSameNode(attr) - and elem.getAttributeNodeNS( - "http://xml.python.org/ns", "c").isSameNode(attr) - and attrmap["c"].isSameNode(attr) - and attrmap[("http://xml.python.org/ns", "c")].isSameNode(attr)) + # Rename to have a namespace, no prefix + attr = doc.renameNode(attr, "http://xml.python.org/ns", "c") + self.assertEqual(attr.name, "c") + self.assertEqual(attr.nodeName, "c") + self.assertEqual(attr.localName, "c") + self.assertEqual(attr.namespaceURI, "http://xml.python.org/ns") + self.assert_(attr.prefix is None) + self.assertEqual(attr.value, "v") + self.assert_(elem.getAttributeNode("a") is None) + self.assert_(elem.getAttributeNode("b") is None) + self.assert_(elem.getAttributeNode("c").isSameNode(attr)) + self.assert_(elem.getAttributeNodeNS("http://xml.python.org/ns", "c").isSameNode(attr)) + self.assert_(attrmap["c"].isSameNode(attr)) + self.assert_(attrmap[("http://xml.python.org/ns", "c")].isSameNode(attr)) - # Rename to have a namespace, with prefix - attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d") - confirm(attr.name == "p:d" - and attr.nodeName == "p:d" - and attr.localName == "d" - and attr.namespaceURI == "http://xml.python.org/ns2" - and attr.prefix == "p" - and attr.value == "v" - and elem.getAttributeNode("a") is None - and elem.getAttributeNode("b") is None - and elem.getAttributeNode("c") is None - and elem.getAttributeNodeNS( - "http://xml.python.org/ns", "c") is None - and elem.getAttributeNode("p:d").isSameNode(attr) - and elem.getAttributeNodeNS( - "http://xml.python.org/ns2", "d").isSameNode(attr) - and attrmap["p:d"].isSameNode(attr) - and attrmap[("http://xml.python.org/ns2", "d")].isSameNode(attr)) + # Rename to have a namespace, with prefix + attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d") + self.assertEqual(attr.name, "p:d") + self.assertEqual(attr.nodeName, "p:d") + self.assertEqual(attr.localName, "d") + self.assertEqual(attr.namespaceURI, "http://xml.python.org/ns2") + self.assertEqual(attr.prefix, "p") + self.assertEqual(attr.value, "v") + self.assert_(elem.getAttributeNode("a") is None) + self.assert_(elem.getAttributeNode("b") is None) + self.assert_(elem.getAttributeNode("c") is None) + self.assert_(elem.getAttributeNodeNS("http://xml.python.org/ns", "c") is None) + self.assert_(elem.getAttributeNode("p:d").isSameNode(attr)) + self.assert_(elem.getAttributeNodeNS("http://xml.python.org/ns2", "d").isSameNode(attr)) + self.assert_(attrmap["p:d"].isSameNode(attr)) + self.assert_(attrmap[("http://xml.python.org/ns2", "d")].isSameNode(attr)) - # Rename back to a simple non-NS node - attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e") - confirm(attr.name == "e" - and attr.nodeName == "e" - and attr.localName is None - and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE - and attr.prefix is None - and attr.value == "v" - and elem.getAttributeNode("a") is None - and elem.getAttributeNode("b") is None - and elem.getAttributeNode("c") is None - and elem.getAttributeNode("p:d") is None - and elem.getAttributeNodeNS( - "http://xml.python.org/ns", "c") is None - and elem.getAttributeNode("e").isSameNode(attr) - and attrmap["e"].isSameNode(attr)) + # Rename back to a simple non-NS node + attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e") + self.assertEqual(attr.name, "e") + self.assertEqual(attr.nodeName, "e") + self.assert_(attr.localName is None) + self.assertEqual(attr.namespaceURI, xml.dom.EMPTY_NAMESPACE) + self.assert_(attr.prefix is None) + self.assertEqual(attr.value, "v") + self.assert_(elem.getAttributeNode("a") is None) + self.assert_(elem.getAttributeNode("b") is None) + self.assert_(elem.getAttributeNode("c") is None) + self.assert_(elem.getAttributeNode("p:d") is None) + self.assert_(elem.getAttributeNodeNS("http://xml.python.org/ns", "c") is None) + self.assert_(elem.getAttributeNode("e").isSameNode(attr)) + self.assert_(attrmap["e"].isSameNode(attr)) - try: - doc.renameNode(attr, "http://xml.python.org/ns", "xmlns") - except xml.dom.NamespaceErr: - pass - else: - print "expected NamespaceErr" + self.assertRaises( + xml.dom.NamespaceErr, + doc.renameNode, attr, "http://xml.python.org/ns", "xmlns") - checkRenameNodeSharedConstraints(doc, attr) - doc.unlink() + self.checkRenameNodeSharedConstraints(doc, attr) + doc.unlink() -def testRenameElement(): - doc = parseString("") - elem = doc.documentElement + def testRenameElement(self): + doc = parseString("") + elem = doc.documentElement - # Simple renaming - elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a") - confirm(elem.tagName == "a" - and elem.nodeName == "a" - and elem.localName is None - and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE - and elem.prefix is None - and elem.ownerDocument.isSameNode(doc)) + # Simple renaming + elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a") + self.assertEqual(elem.tagName, "a") + self.assertEqual(elem.nodeName, "a") + self.assert_(elem.localName is None) + self.assertEqual(elem.namespaceURI, xml.dom.EMPTY_NAMESPACE) + self.assert_(elem.prefix is None) + self.assert_(elem.ownerDocument.isSameNode(doc)) - # Rename to have a namespace, no prefix - elem = doc.renameNode(elem, "http://xml.python.org/ns", "b") - confirm(elem.tagName == "b" - and elem.nodeName == "b" - and elem.localName == "b" - and elem.namespaceURI == "http://xml.python.org/ns" - and elem.prefix is None - and elem.ownerDocument.isSameNode(doc)) + # Rename to have a namespace, no prefix + elem = doc.renameNode(elem, "http://xml.python.org/ns", "b") + self.assertEqual(elem.tagName, "b") + self.assertEqual(elem.nodeName, "b") + self.assertEqual(elem.localName, "b") + self.assertEqual(elem.namespaceURI, "http://xml.python.org/ns") + self.assert_(elem.prefix is None) + self.assert_(elem.ownerDocument.isSameNode(doc)) - # Rename to have a namespace, with prefix - elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c") - confirm(elem.tagName == "p:c" - and elem.nodeName == "p:c" - and elem.localName == "c" - and elem.namespaceURI == "http://xml.python.org/ns2" - and elem.prefix == "p" - and elem.ownerDocument.isSameNode(doc)) + # Rename to have a namespace, with prefix + elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c") + self.assertEqual(elem.tagName, "p:c") + self.assertEqual(elem.nodeName, "p:c") + self.assertEqual(elem.localName, "c") + self.assertEqual(elem.namespaceURI, "http://xml.python.org/ns2") + self.assertEqual(elem.prefix, "p") + self.assert_(elem.ownerDocument.isSameNode(doc)) - # Rename back to a simple non-NS node - elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d") - confirm(elem.tagName == "d" - and elem.nodeName == "d" - and elem.localName is None - and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE - and elem.prefix is None - and elem.ownerDocument.isSameNode(doc)) + # Rename back to a simple non-NS node + elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d") + self.assertEqual(elem.tagName, "d") + self.assertEqual(elem.nodeName, "d") + self.assert_(elem.localName is None) + self.assertEqual(elem.namespaceURI, xml.dom.EMPTY_NAMESPACE) + self.assert_(elem.prefix is None) + self.assert_(elem.ownerDocument.isSameNode(doc)) - checkRenameNodeSharedConstraints(doc, elem) - doc.unlink() + self.checkRenameNodeSharedConstraints(doc, elem) + doc.unlink() -def checkRenameNodeSharedConstraints(doc, node): - # Make sure illegal NS usage is detected: - try: - doc.renameNode(node, "http://xml.python.org/ns", "xmlns:foo") - except xml.dom.NamespaceErr: - pass - else: - print "expected NamespaceErr" + def checkRenameNodeSharedConstraints(self, doc, node): + # Make sure illegal NS usage is detected: + self.assertRaises( + xml.dom.NamespaceErr, + doc.renameNode, node, "http://xml.python.org/ns", "xmlns:foo") - doc2 = parseString("") - try: - doc2.renameNode(node, xml.dom.EMPTY_NAMESPACE, "foo") - except xml.dom.WrongDocumentErr: - pass - else: - print "expected WrongDocumentErr" + doc2 = parseString("") + self.assertRaises( + xml.dom.WrongDocumentErr, + doc2.renameNode, node, xml.dom.EMPTY_NAMESPACE, "foo") + doc2.unlink() -def testRenameOther(): - # We have to create a comment node explicitly since not all DOM - # builders used with minidom add comments to the DOM. - doc = xml.dom.minidom.getDOMImplementation().createDocument( - xml.dom.EMPTY_NAMESPACE, "e", None) - node = doc.createComment("comment") - try: - doc.renameNode(node, xml.dom.EMPTY_NAMESPACE, "foo") - except xml.dom.NotSupportedErr: - pass - else: - print "expected NotSupportedErr when renaming comment node" - doc.unlink() + def testRenameOther(self): + # We have to create a comment node explicitly since not all DOM + # builders used with minidom add comments to the DOM. + doc = xml.dom.minidom.getDOMImplementation().createDocument( + xml.dom.EMPTY_NAMESPACE, "e", None) + node = doc.createComment("comment") + self.assertRaises( + xml.dom.NotSupportedErr, + doc.renameNode, node, xml.dom.EMPTY_NAMESPACE, "foo") + doc.unlink() -def checkWholeText(node, s): - t = node.wholeText - confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t))) + def testWholeText(self): + doc = parseString("a") + elem = doc.documentElement + text = elem.childNodes[0] + assert text.nodeType == Node.TEXT_NODE -def testWholeText(): - doc = parseString("a") - elem = doc.documentElement - text = elem.childNodes[0] - assert text.nodeType == Node.TEXT_NODE + self.assertEqual(text.wholeText, "a") + elem.appendChild(doc.createTextNode("b")) + self.assertEqual(text.wholeText, "ab") + elem.insertBefore(doc.createCDATASection("c"), text) + self.assertEqual(text.wholeText, "cab") - checkWholeText(text, "a") - elem.appendChild(doc.createTextNode("b")) - checkWholeText(text, "ab") - elem.insertBefore(doc.createCDATASection("c"), text) - checkWholeText(text, "cab") + # make sure we don't cross other nodes + splitter = doc.createComment("comment") + elem.appendChild(splitter) + text2 = doc.createTextNode("d") + elem.appendChild(text2) + self.assertEqual(text.wholeText, "cab") + self.assertEqual(text2.wholeText, "d") - # make sure we don't cross other nodes - splitter = doc.createComment("comment") - elem.appendChild(splitter) - text2 = doc.createTextNode("d") - elem.appendChild(text2) - checkWholeText(text, "cab") - checkWholeText(text2, "d") + x = doc.createElement("x") + elem.replaceChild(x, splitter) + splitter = x + self.assertEqual(text.wholeText, "cab") + self.assertEqual(text2.wholeText, "d") - x = doc.createElement("x") - elem.replaceChild(x, splitter) - splitter = x - checkWholeText(text, "cab") - checkWholeText(text2, "d") + x = doc.createProcessingInstruction("y", "z") + elem.replaceChild(x, splitter) + splitter = x + self.assertEqual(text.wholeText, "cab") + self.assertEqual(text2.wholeText, "d") - x = doc.createProcessingInstruction("y", "z") - elem.replaceChild(x, splitter) - splitter = x - checkWholeText(text, "cab") - checkWholeText(text2, "d") + elem.removeChild(splitter) + self.assertEqual(text.wholeText, "cabd") + self.assertEqual(text2.wholeText, "cabd") - elem.removeChild(splitter) - checkWholeText(text, "cabd") - checkWholeText(text2, "cabd") + doc.unlink() -def testPatch1094164 (): - doc = parseString("") - elem = doc.documentElement - e = elem.firstChild - confirm(e.parentNode is elem, "Before replaceChild()") - # Check that replacing a child with itself leaves the tree unchanged - elem.replaceChild(e, e) - confirm(e.parentNode is elem, "After replaceChild()") + def testPatch1094164(self): + doc = parseString("") + elem = doc.documentElement + e = elem.firstChild + self.assert_(e.parentNode is elem, "Before replaceChild()") + # Check that replacing a child with itself leaves the tree unchanged + elem.replaceChild(e, e) + self.assert_(e.parentNode is elem, "After replaceChild()") + doc.unlink() + def testReplaceWholeText(self): + def setup(): + doc = parseString("ad") + elem = doc.documentElement + text1 = elem.firstChild + text2 = elem.lastChild + splitter = text1.nextSibling + elem.insertBefore(doc.createTextNode("b"), splitter) + elem.insertBefore(doc.createCDATASection("c"), text1) + return doc, elem, text1, splitter, text2 + doc, elem, text1, splitter, text2 = setup() + text = text1.replaceWholeText("new content") + self.assertEqual(text.wholeText, "new content") + self.assertEqual(text2.wholeText, "d") + self.assertEqual(len(elem.childNodes), 3) + doc.unlink() -def testReplaceWholeText(): - def setup(): - doc = parseString("ad") - elem = doc.documentElement - text1 = elem.firstChild - text2 = elem.lastChild - splitter = text1.nextSibling - elem.insertBefore(doc.createTextNode("b"), splitter) - elem.insertBefore(doc.createCDATASection("c"), text1) - return doc, elem, text1, splitter, text2 + doc, elem, text1, splitter, text2 = setup() + text = text2.replaceWholeText("new content") + self.assertEqual(text.wholeText, "new content") + self.assertEqual(text1.wholeText, "cab") + self.assertEqual(len(elem.childNodes), 5) + doc.unlink() - doc, elem, text1, splitter, text2 = setup() - text = text1.replaceWholeText("new content") - checkWholeText(text, "new content") - checkWholeText(text2, "d") - confirm(len(elem.childNodes) == 3) + doc, elem, text1, splitter, text2 = setup() + text = text1.replaceWholeText("") + self.assertEqual(text2.wholeText, "d") + self.assert_(text is None) + self.assertEqual(len(elem.childNodes), 2) + doc.unlink() - doc, elem, text1, splitter, text2 = setup() - text = text2.replaceWholeText("new content") - checkWholeText(text, "new content") - checkWholeText(text1, "cab") - confirm(len(elem.childNodes) == 5) + def testSchemaType(self): + doc = parseString( + "\n" + " \n" + " \n" + "]>") + elem = doc.documentElement + # We don't want to rely on any specific loader at this point, so + # just make sure we can get to all the names, and that the + # DTD-based namespace is right. The names can vary by loader + # since each supports a different level of DTD information. + t = elem.schemaType + self.assert_(t.name is None) + self.assertEqual(t.namespace, xml.dom.EMPTY_NAMESPACE) + names = "id notid text enum ref refs ent ents nm nms".split() + for name in names: + a = elem.getAttributeNode(name) + t = a.schemaType + self.assert_(hasattr(t, "name")) + self.assertEqual(t.namespace, xml.dom.EMPTY_NAMESPACE) + doc.unlink() - doc, elem, text1, splitter, text2 = setup() - text = text1.replaceWholeText("") - checkWholeText(text2, "d") - confirm(text is None - and len(elem.childNodes) == 2) + def testSetIdAttribute(self): + doc = parseString("") + e = doc.documentElement + a1 = e.getAttributeNode("a1") + a2 = e.getAttributeNode("a2") + self.assert_(doc.getElementById("v") is None) + self.failIf(a1.isId) + self.failIf(a2.isId) + e.setIdAttribute("a1") + self.assert_(e.isSameNode(doc.getElementById("v"))) + self.assert_(a1.isId) + self.failIf(a2.isId) + e.setIdAttribute("a2") + self.assert_(e.isSameNode(doc.getElementById("v"))) + self.assert_(e.isSameNode(doc.getElementById("w"))) + self.assert_(a1.isId) + self.assert_(a2.isId) + # replace the a1 node; the new node should *not* be an ID + a3 = doc.createAttribute("a1") + a3.value = "v" + e.setAttributeNode(a3) + self.assert_(doc.getElementById("v") is None) + self.assert_(e.isSameNode(doc.getElementById("w"))) + self.failIf(a1.isId) + self.assert_(a2.isId) + self.failIf(a3.isId) + # renaming an attribute should not affect its ID-ness: + doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") + self.assert_(e.isSameNode(doc.getElementById("w"))) + self.assert_(a2.isId) + doc.unlink() -def testSchemaType(): - doc = parseString( - "\n" - " \n" - " \n" - "]>") - elem = doc.documentElement - # We don't want to rely on any specific loader at this point, so - # just make sure we can get to all the names, and that the - # DTD-based namespace is right. The names can vary by loader - # since each supports a different level of DTD information. - t = elem.schemaType - confirm(t.name is None - and t.namespace == xml.dom.EMPTY_NAMESPACE) - names = "id notid text enum ref refs ent ents nm nms".split() - for name in names: - a = elem.getAttributeNode(name) - t = a.schemaType - confirm(hasattr(t, "name") - and t.namespace == xml.dom.EMPTY_NAMESPACE) + def testSetIdAttributeNS(self): + NS1 = "http://xml.python.org/ns1" + NS2 = "http://xml.python.org/ns2" + doc = parseString("") + e = doc.documentElement + a1 = e.getAttributeNodeNS(NS1, "a1") + a2 = e.getAttributeNodeNS(NS2, "a2") + self.assert_(doc.getElementById("v") is None) + self.failIf(a1.isId) + self.failIf(a2.isId) + e.setIdAttributeNS(NS1, "a1") + self.assert_(e.isSameNode(doc.getElementById("v"))) + self.assert_(a1.isId) + self.failIf(a2.isId) + e.setIdAttributeNS(NS2, "a2") + self.assert_(e.isSameNode(doc.getElementById("v"))) + self.assert_(e.isSameNode(doc.getElementById("w"))) + self.assert_(a1.isId) + self.assert_(a2.isId) + # replace the a1 node; the new node should *not* be an ID + a3 = doc.createAttributeNS(NS1, "a1") + a3.value = "v" + e.setAttributeNode(a3) + self.assert_(e.isSameNode(doc.getElementById("w"))) + self.failIf(a1.isId) + self.assert_(a2.isId) + self.failIf(a3.isId) + self.assert_(doc.getElementById("v") is None) + # renaming an attribute should not affect its ID-ness: + doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") + self.assert_(e.isSameNode(doc.getElementById("w"))) + self.assert_(a2.isId) + doc.unlink() -def testSetIdAttribute(): - doc = parseString("") - e = doc.documentElement - a1 = e.getAttributeNode("a1") - a2 = e.getAttributeNode("a2") - confirm(doc.getElementById("v") is None - and not a1.isId - and not a2.isId) - e.setIdAttribute("a1") - confirm(e.isSameNode(doc.getElementById("v")) - and a1.isId - and not a2.isId) - e.setIdAttribute("a2") - confirm(e.isSameNode(doc.getElementById("v")) - and e.isSameNode(doc.getElementById("w")) - and a1.isId - and a2.isId) - # replace the a1 node; the new node should *not* be an ID - a3 = doc.createAttribute("a1") - a3.value = "v" - e.setAttributeNode(a3) - confirm(doc.getElementById("v") is None - and e.isSameNode(doc.getElementById("w")) - and not a1.isId - and a2.isId - and not a3.isId) - # renaming an attribute should not affect its ID-ness: - doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") - confirm(e.isSameNode(doc.getElementById("w")) - and a2.isId) + def testSetIdAttributeNode(self): + NS1 = "http://xml.python.org/ns1" + NS2 = "http://xml.python.org/ns2" + doc = parseString("") + e = doc.documentElement + a1 = e.getAttributeNodeNS(NS1, "a1") + a2 = e.getAttributeNodeNS(NS2, "a2") + self.assert_(doc.getElementById("v") is None) + self.failIf(a1.isId) + self.failIf(a2.isId) + e.setIdAttributeNode(a1) + self.assert_(e.isSameNode(doc.getElementById("v"))) + self.assert_(a1.isId) + self.failIf(a2.isId) + e.setIdAttributeNode(a2) + self.assert_(e.isSameNode(doc.getElementById("v"))) + self.assert_(e.isSameNode(doc.getElementById("w"))) + self.assert_(a1.isId) + self.assert_(a2.isId) + # replace the a1 node; the new node should *not* be an ID + a3 = doc.createAttributeNS(NS1, "a1") + a3.value = "v" + e.setAttributeNode(a3) + self.assert_(e.isSameNode(doc.getElementById("w"))) + self.failIf(a1.isId) + self.assert_(a2.isId) + self.failIf(a3.isId) + self.assert_(doc.getElementById("v") is None) + # renaming an attribute should not affect its ID-ness: + doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") + self.assert_(e.isSameNode(doc.getElementById("w"))) + self.assert_(a2.isId) + doc.unlink() -def testSetIdAttributeNS(): - NS1 = "http://xml.python.org/ns1" - NS2 = "http://xml.python.org/ns2" - doc = parseString("") - e = doc.documentElement - a1 = e.getAttributeNodeNS(NS1, "a1") - a2 = e.getAttributeNodeNS(NS2, "a2") - confirm(doc.getElementById("v") is None - and not a1.isId - and not a2.isId) - e.setIdAttributeNS(NS1, "a1") - confirm(e.isSameNode(doc.getElementById("v")) - and a1.isId - and not a2.isId) - e.setIdAttributeNS(NS2, "a2") - confirm(e.isSameNode(doc.getElementById("v")) - and e.isSameNode(doc.getElementById("w")) - and a1.isId - and a2.isId) - # replace the a1 node; the new node should *not* be an ID - a3 = doc.createAttributeNS(NS1, "a1") - a3.value = "v" - e.setAttributeNode(a3) - confirm(e.isSameNode(doc.getElementById("w"))) - confirm(not a1.isId) - confirm(a2.isId) - confirm(not a3.isId) - confirm(doc.getElementById("v") is None) - # renaming an attribute should not affect its ID-ness: - doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") - confirm(e.isSameNode(doc.getElementById("w")) - and a2.isId) + def testPickledDocument(self): + doc = parseString("\n" + "\n" + " \n" + "]> text\n" + " ") + s = pickle.dumps(doc) + doc2 = pickle.loads(s) + stack = [(doc, doc2)] + while stack: + n1, n2 = stack.pop() + self.assertEqual(n1.nodeType, n2.nodeType) + self.assertEqual(len(n1.childNodes), len(n2.childNodes)) + self.assertEqual(n1.nodeName, n2.nodeName) + self.failIf(n1.isSameNode(n2)) + self.failIf(n2.isSameNode(n1)) + if n1.nodeType == Node.DOCUMENT_TYPE_NODE: + len(n1.entities) + len(n2.entities) + len(n1.notations) + len(n2.notations) + self.assertEqual(len(n1.entities), len(n2.entities)) + self.assertEqual(len(n1.notations), len(n2.notations)) + for i in range(len(n1.notations)): + no1 = n1.notations.item(i) + no2 = n1.notations.item(i) + self.assertEqual(no1.name, no2.name) + self.assertEqual(no1.publicId, no2.publicId) + self.assertEqual(no1.systemId, no2.systemId) + statck.append((no1, no2)) + for i in range(len(n1.entities)): + e1 = n1.entities.item(i) + e2 = n2.entities.item(i) + self.assertEqual(e1.notationName, e2.notationName) + self.assertEqual(e1.publicId, e2.publicId) + self.assertEqual(e1.systemId, e2.systemId) + stack.append((e1, e2)) + if n1.nodeType != Node.DOCUMENT_NODE: + self.assert_(n1.ownerDocument.isSameNode(doc)) + self.assert_(n2.ownerDocument.isSameNode(doc2)) + for i in range(len(n1.childNodes)): + stack.append((n1.childNodes[i], n2.childNodes[i])) + doc.unlink() + doc2.unlink() -def testSetIdAttributeNode(): - NS1 = "http://xml.python.org/ns1" - NS2 = "http://xml.python.org/ns2" - doc = parseString("") - e = doc.documentElement - a1 = e.getAttributeNodeNS(NS1, "a1") - a2 = e.getAttributeNodeNS(NS2, "a2") - confirm(doc.getElementById("v") is None - and not a1.isId - and not a2.isId) - e.setIdAttributeNode(a1) - confirm(e.isSameNode(doc.getElementById("v")) - and a1.isId - and not a2.isId) - e.setIdAttributeNode(a2) - confirm(e.isSameNode(doc.getElementById("v")) - and e.isSameNode(doc.getElementById("w")) - and a1.isId - and a2.isId) - # replace the a1 node; the new node should *not* be an ID - a3 = doc.createAttributeNS(NS1, "a1") - a3.value = "v" - e.setAttributeNode(a3) - confirm(e.isSameNode(doc.getElementById("w"))) - confirm(not a1.isId) - confirm(a2.isId) - confirm(not a3.isId) - confirm(doc.getElementById("v") is None) - # renaming an attribute should not affect its ID-ness: - doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") - confirm(e.isSameNode(doc.getElementById("w")) - and a2.isId) + if gc is not None: + # Testing unlink() + # + # All the tests call unlink() properly. This should leave no + # cycles for the garbage collector to collect. To test that it + # works, we use the garbage collector's debug API. -def testPickledDocument(): - doc = parseString("\n" - "\n" - " \n" - "]> text\n" - " ") - s = pickle.dumps(doc) - doc2 = pickle.loads(s) - stack = [(doc, doc2)] - while stack: - n1, n2 = stack.pop() - confirm(n1.nodeType == n2.nodeType - and len(n1.childNodes) == len(n2.childNodes) - and n1.nodeName == n2.nodeName - and not n1.isSameNode(n2) - and not n2.isSameNode(n1)) - if n1.nodeType == Node.DOCUMENT_TYPE_NODE: - len(n1.entities) - len(n2.entities) - len(n1.notations) - len(n2.notations) - confirm(len(n1.entities) == len(n2.entities) - and len(n1.notations) == len(n2.notations)) - for i in range(len(n1.notations)): - no1 = n1.notations.item(i) - no2 = n1.notations.item(i) - confirm(no1.name == no2.name - and no1.publicId == no2.publicId - and no1.systemId == no2.systemId) - statck.append((no1, no2)) - for i in range(len(n1.entities)): - e1 = n1.entities.item(i) - e2 = n2.entities.item(i) - confirm(e1.notationName == e2.notationName - and e1.publicId == e2.publicId - and e1.systemId == e2.systemId) - stack.append((e1, e2)) - if n1.nodeType != Node.DOCUMENT_NODE: - confirm(n1.ownerDocument.isSameNode(doc) - and n2.ownerDocument.isSameNode(doc2)) - for i in range(len(n1.childNodes)): - stack.append((n1.childNodes[i], n2.childNodes[i])) + def setUp(self): + # Disable garbage collection before each test. + self._gc_was_enabled = gc.isenabled() + self._gc_old_debug_flags = gc.get_debug() + gc.disable() + # Do a manual collection to start clean. + gc.set_debug(0) + gc.collect() + del gc.garbage[:] + # During and after the test, no nodes should be collected. + gc.set_debug(gc.DEBUG_SAVEALL) + def tearDown(self): + # Re-enable garbage collection. + del gc.garbage[:] + gc.set_debug(self._gc_old_debug_flags) + if self._gc_was_enabled: + gc.enable() -# --- MAIN PROGRAM + def _check_cycles(self): + gc.collect() + garbageNodes = [obj for obj in gc.garbage if isinstance(obj, Node)] + garbageCount = len(garbageNodes) + if garbageCount: + print "Garbage left over: %i nodes" % garbageCount + if test_support.verbose: + try: + print garbageNodes[:10] + except: + print "?" + pass + # OK, now really get rid of them. + del garbageNodes[:] + del gc.garbage[:] + gc.set_debug(0) + print "Deleting %i nodes" % gc.collect() + gc.set_debug(gc.DEBUG_SAVEALL) + self.assertEqual(garbageCount, 0) -names = globals().keys() -names.sort() + # Fix up all tests to call _check_cycles() + # Can't use tearDown() to do this because it treats exceptions + # as errors, not test failures. + def _wrapTest(fn): + def memoryTestWrapper(self): + fn(self) + self._check_cycles() + return memoryTestWrapper + _loc = locals() + for _name, _fn in _loc.items(): + if _name.startswith('test'): + print _name + _loc[_name] = _wrapTest(_fn) + del _loc, _name, _fn, _wrapTest -failed = [] +def test_main(): + test_support.run_unittest(MinidomTest) -try: - Node.allnodes -except AttributeError: - # We don't actually have the minidom from the standard library, - # but are picking up the PyXML version from site-packages. - def check_allnodes(): - pass -else: - def check_allnodes(): - confirm(len(Node.allnodes) == 0, - "assertion: len(Node.allnodes) == 0") - if len(Node.allnodes): - print "Garbage left over:" - if verbose: - print Node.allnodes.items()[0:10] - else: - # Don't print specific nodes if repeatable results - # are needed - print len(Node.allnodes) - Node.allnodes = {} - -for name in names: - if name.startswith("test"): - func = globals()[name] - try: - func() - check_allnodes() - except: - failed.append(name) - print "Test Failed: ", name - sys.stdout.flush() - traceback.print_exception(*sys.exc_info()) - print repr(sys.exc_info()[1]) - Node.allnodes = {} - -if failed: - print "\n\n\n**** Check for failures in these tests:" - for name in failed: - print " " + name +if __name__ == "__main__": + test_main() Index: Lib/xml/dom/expatbuilder.py =================================================================== --- Lib/xml/dom/expatbuilder.py (revision 54434) +++ Lib/xml/dom/expatbuilder.py (working copy) @@ -171,9 +171,23 @@ self._elem_info = self.document._elem_info self._cdata = False + def unlink(self): + """Clean up cycles.""" + if self.document: + self.document.unlink() + self.document = None + self._parser = None + self._intern_setdefault = None + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.unlink() + def install(self, parser): """Install the callbacks needed to build the DOM into the parser.""" - # This creates circular references! + # This creates circular references! Call unlink() to clear them. parser.StartDoctypeDeclHandler = self.start_doctype_decl_handler parser.StartElementHandler = self.first_element_handler parser.EndElementHandler = self.end_element_handler @@ -211,6 +225,10 @@ parser.Parse("", True) except ParseEscape: pass + except: + self.document.unlink() + self.reset() + raise doc = self.document self.reset() self._parser = None @@ -224,6 +242,10 @@ self._setup_subset(string) except ParseEscape: pass + except: + self.document.unlink() + self.reset() + raise doc = self.document self.reset() self._parser = None @@ -918,14 +940,12 @@ else: builder = ExpatBuilder() - if isinstance(file, StringTypes): - fp = open(file, 'rb') - try: - result = builder.parseFile(fp) - finally: - fp.close() - else: - result = builder.parseFile(file) + with builder: + if isinstance(file, StringTypes): + with open(file, 'rb') as fp: + result = builder.parseFile(fp) + else: + result = builder.parseFile(file) return result @@ -937,8 +957,9 @@ builder = ExpatBuilderNS() else: builder = ExpatBuilder() - return builder.parseString(string) + with builder: + return builder.parseString(string) def parseFragment(file, context, namespaces=True): """Parse a fragment of a document, given the context from which it @@ -952,14 +973,12 @@ else: builder = FragmentBuilder(context) - if isinstance(file, StringTypes): - fp = open(file, 'rb') - try: - result = builder.parseFile(fp) - finally: - fp.close() - else: - result = builder.parseFile(file) + with builder: + if isinstance(file, StringTypes): + with open(file, 'rb') as fp: + result = builder.parseFile(fp) + else: + result = builder.parseFile(file) return result @@ -972,8 +991,9 @@ builder = FragmentBuilderNS(context) else: builder = FragmentBuilder(context) - return builder.parseString(string) + with builder: + return builder.parseString(string) def makeBuilder(options): """Create a builder based on an Options object."""