[Python-checkins] r54603 - in python/trunk/Lib/test: output/test_pyexpat output/xmltests test_minidom.py test_pyexpat.py test_sax.py

collin.winter python-checkins at python.org
Thu Mar 29 01:34:10 CEST 2007


Author: collin.winter
Date: Thu Mar 29 01:34:06 2007
New Revision: 54603

Removed:
   python/trunk/Lib/test/output/test_pyexpat
   python/trunk/Lib/test/output/xmltests
Modified:
   python/trunk/Lib/test/test_minidom.py
   python/trunk/Lib/test/test_pyexpat.py
   python/trunk/Lib/test/test_sax.py
Log:
Consolidate patches #1690164, 1683397, and 1690169, all of which refactor XML-related test suites. The patches are applied together because they use a common output/xmltests file.
Thanks to Jerry Seutter for all three patches.


Deleted: /python/trunk/Lib/test/output/test_pyexpat
==============================================================================
--- /python/trunk/Lib/test/output/test_pyexpat	Thu Mar 29 01:34:06 2007
+++ (empty file)
@@ -1,110 +0,0 @@
-test_pyexpat
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-PI:
-	'xml-stylesheet' 'href="stylesheet.css"'
-Comment:
-	' comment data '
-Notation declared: ('notation', None, 'notation.jpeg', None)
-Unparsed entity decl:
-	('unparsed_entity', None, 'entity.file', None, 'notation')
-Start element:
-	'root' {'attr1': 'value1', 'attr2': 'value2\xe1\xbd\x80'}
-NS decl:
-	'myns' 'http://www.python.org/namespace'
-Start element:
-	'http://www.python.org/namespace!subelement' {}
-Character data:
-	'Contents of subelements'
-End element:
-	'http://www.python.org/namespace!subelement'
-End of NS decl:
-	'myns'
-Start element:
-	'sub2' {}
-Start of CDATA section
-Character data:
-	'contents of CDATA section'
-End of CDATA section
-End element:
-	'sub2'
-External entity ref: (None, 'entity.file', None)
-End element:
-	'root'
-PI:
-	u'xml-stylesheet' u'href="stylesheet.css"'
-Comment:
-	u' comment data '
-Notation declared: (u'notation', None, u'notation.jpeg', None)
-Unparsed entity decl:
-	(u'unparsed_entity', None, u'entity.file', None, u'notation')
-Start element:
-	u'root' {u'attr1': u'value1', u'attr2': u'value2\u1f40'}
-NS decl:
-	u'myns' u'http://www.python.org/namespace'
-Start element:
-	u'http://www.python.org/namespace!subelement' {}
-Character data:
-	u'Contents of subelements'
-End element:
-	u'http://www.python.org/namespace!subelement'
-End of NS decl:
-	u'myns'
-Start element:
-	u'sub2' {}
-Start of CDATA section
-Character data:
-	u'contents of CDATA section'
-End of CDATA section
-End element:
-	u'sub2'
-External entity ref: (None, u'entity.file', None)
-End element:
-	u'root'
-PI:
-	u'xml-stylesheet' u'href="stylesheet.css"'
-Comment:
-	u' comment data '
-Notation declared: (u'notation', None, u'notation.jpeg', None)
-Unparsed entity decl:
-	(u'unparsed_entity', None, u'entity.file', None, u'notation')
-Start element:
-	u'root' {u'attr1': u'value1', u'attr2': u'value2\u1f40'}
-NS decl:
-	u'myns' u'http://www.python.org/namespace'
-Start element:
-	u'http://www.python.org/namespace!subelement' {}
-Character data:
-	u'Contents of subelements'
-End element:
-	u'http://www.python.org/namespace!subelement'
-End of NS decl:
-	u'myns'
-Start element:
-	u'sub2' {}
-Start of CDATA section
-Character data:
-	u'contents of CDATA section'
-End of CDATA section
-End element:
-	u'sub2'
-External entity ref: (None, u'entity.file', None)
-End element:
-	u'root'
-
-Testing constructor for proper handling of namespace_separator values:
-Legal values tested o.k.
-Caught expected TypeError:
-ParserCreate() argument 2 must be string or None, not int
-Caught expected ValueError:
-namespace_separator must be at most one character, omitted, or None

Deleted: /python/trunk/Lib/test/output/xmltests
==============================================================================
--- /python/trunk/Lib/test/output/xmltests	Thu Mar 29 01:34:06 2007
+++ (empty file)
@@ -1,364 +0,0 @@
-xmltests
-Passed testAAA
-Passed setAttribute() sets ownerDocument
-Passed setAttribute() sets ownerElement
-Test Succeeded testAAA
-Passed assertion: len(Node.allnodes) == 0
-Passed testAAB
-Test Succeeded testAAB
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Passed Test
-Passed Test
-Passed Test
-Passed Test
-Passed Test
-Passed Test
-Test Succeeded testAddAttr
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Test Succeeded testAppendChild
-Passed assertion: len(Node.allnodes) == 0
-Passed appendChild(<fragment>)
-Test Succeeded testAppendChildFragment
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testAttrListItem
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testAttrListItemNS
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testAttrListItems
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testAttrListKeys
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testAttrListKeysNS
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testAttrListLength
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testAttrListValues
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testAttrList__getitem__
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testAttrList__setitem__
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Test Succeeded testAttributeRepr
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Passed Test
-Passed Test
-Passed Test
-Test Succeeded testChangeAttr
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testChildNodes
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testCloneAttributeDeep
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testCloneAttributeShallow
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testCloneDocumentDeep
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testCloneDocumentShallow
-Passed assertion: len(Node.allnodes) == 0
-Passed clone of element has same attribute keys
-Passed clone of attribute node has proper attribute values
-Passed clone of attribute node correctly owned
-Passed testCloneElementDeep
-Test Succeeded testCloneElementDeep
-Passed assertion: len(Node.allnodes) == 0
-Passed clone of element has same attribute keys
-Passed clone of attribute node has proper attribute values
-Passed clone of attribute node correctly owned
-Passed testCloneElementShallow
-Test Succeeded testCloneElementShallow
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testClonePIDeep
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testClonePIShallow
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testComment
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testCreateAttributeNS
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testCreateElementNS
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Passed Test
-Test Succeeded testDeleteAttr
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testDocumentElement
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Test Succeeded testElement
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Test Succeeded testElementReprAndStr
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testFirstChild
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testGetAttrLength
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testGetAttrList
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testGetAttrValues
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testGetAttribute
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testGetAttributeNS
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testGetAttributeNode
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Test Succeeded testGetElementsByTagName
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Test Succeeded testGetElementsByTagNameNS
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testGetEmptyNodeListFromElementsByTagNameNS
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testHasChildNodes
-Passed assertion: len(Node.allnodes) == 0
-Passed testInsertBefore -- node properly placed in tree
-Passed testInsertBefore -- node properly placed in tree
-Passed testInsertBefore -- node properly placed in tree
-Test Succeeded testInsertBefore
-Passed assertion: len(Node.allnodes) == 0
-Passed insertBefore(<fragment>, None)
-Passed insertBefore(<fragment>, orig)
-Test Succeeded testInsertBeforeFragment
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testLegalChildren
-Passed assertion: len(Node.allnodes) == 0
-Passed NamedNodeMap.__setitem__() sets ownerDocument
-Passed NamedNodeMap.__setitem__() sets ownerElement
-Passed NamedNodeMap.__setitem__() sets value
-Passed NamedNodeMap.__setitem__() sets nodeValue
-Test Succeeded testNamedNodeMapSetItem
-Passed assertion: len(Node.allnodes) == 0
-Passed test NodeList.item()
-Test Succeeded testNodeListItem
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Test Succeeded testNonZero
-Passed assertion: len(Node.allnodes) == 0
-Passed testNormalize -- preparation
-Passed testNormalize -- result
-Passed testNormalize -- single empty node removed
-Test Succeeded testNormalize
-Passed assertion: len(Node.allnodes) == 0
-Passed testParents
-Test Succeeded testParents
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testParse
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testParseAttributeNamespaces
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testParseAttributes
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testParseElement
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testParseElementNamespaces
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Test Succeeded testParseFromFile
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testParseProcessingInstructions
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testParseString
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testProcessingInstruction
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testProcessingInstructionRepr
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Test Succeeded testRemoveAttr
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Test Succeeded testRemoveAttrNS
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Test Succeeded testRemoveAttributeNode
-Passed assertion: len(Node.allnodes) == 0
-Passed replaceChild(<fragment>)
-Test Succeeded testReplaceChildFragment
-Passed assertion: len(Node.allnodes) == 0
-Passed testSAX2DOM - siblings
-Passed testSAX2DOM - parents
-Test Succeeded testSAX2DOM
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testSetAttrValueandNodeValue
-Passed assertion: len(Node.allnodes) == 0
-Passed testSiblings
-Test Succeeded testSiblings
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testTextNodeRepr
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testTextRepr
-Passed assertion: len(Node.allnodes) == 0
-Caught expected exception when adding extra document element.
-Test Succeeded testTooManyDocumentElements
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testUnlink
-Passed assertion: len(Node.allnodes) == 0
-Test Succeeded testWriteText
-Passed assertion: len(Node.allnodes) == 0
-Passed Test
-Passed Test
-Test Succeeded testWriteXML
-Passed assertion: len(Node.allnodes) == 0
-All tests succeeded
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-OK.
-PI:
-	'xml-stylesheet' 'href="stylesheet.css"'
-Comment:
-	' comment data '
-Notation declared: ('notation', None, 'notation.jpeg', None)
-Unparsed entity decl:
-	('unparsed_entity', None, 'entity.file', None, 'notation')
-Start element:
-	'root' {'attr1': 'value1', 'attr2': 'value2\xe1\xbd\x80'}
-NS decl:
-	'myns' 'http://www.python.org/namespace'
-Start element:
-	'http://www.python.org/namespace!subelement' {}
-Character data:
-	'Contents of subelements'
-End element:
-	'http://www.python.org/namespace!subelement'
-End of NS decl:
-	'myns'
-Start element:
-	'sub2' {}
-Start of CDATA section
-Character data:
-	'contents of CDATA section'
-End of CDATA section
-End element:
-	'sub2'
-External entity ref: (None, 'entity.file', None)
-End element:
-	'root'
-PI:
-	u'xml-stylesheet' u'href="stylesheet.css"'
-Comment:
-	u' comment data '
-Notation declared: (u'notation', None, u'notation.jpeg', None)
-Unparsed entity decl:
-	(u'unparsed_entity', None, u'entity.file', None, u'notation')
-Start element:
-	u'root' {u'attr1': u'value1', u'attr2': u'value2\u1f40'}
-NS decl:
-	u'myns' u'http://www.python.org/namespace'
-Start element:
-	u'http://www.python.org/namespace!subelement' {}
-Character data:
-	u'Contents of subelements'
-End element:
-	u'http://www.python.org/namespace!subelement'
-End of NS decl:
-	u'myns'
-Start element:
-	u'sub2' {}
-Start of CDATA section
-Character data:
-	u'contents of CDATA section'
-End of CDATA section
-End element:
-	u'sub2'
-External entity ref: (None, u'entity.file', None)
-End element:
-	u'root'
-PI:
-	u'xml-stylesheet' u'href="stylesheet.css"'
-Comment:
-	u' comment data '
-Notation declared: (u'notation', None, u'notation.jpeg', None)
-Unparsed entity decl:
-	(u'unparsed_entity', None, u'entity.file', None, u'notation')
-Start element:
-	u'root' {u'attr1': u'value1', u'attr2': u'value2\u1f40'}
-NS decl:
-	u'myns' u'http://www.python.org/namespace'
-Start element:
-	u'http://www.python.org/namespace!subelement' {}
-Character data:
-	u'Contents of subelements'
-End element:
-	u'http://www.python.org/namespace!subelement'
-End of NS decl:
-	u'myns'
-Start element:
-	u'sub2' {}
-Start of CDATA section
-Character data:
-	u'contents of CDATA section'
-End of CDATA section
-End element:
-	u'sub2'
-External entity ref: (None, u'entity.file', None)
-End element:
-	u'root'
-
-Testing constructor for proper handling of namespace_separator values:
-Legal values tested o.k.
-Caught expected TypeError:
-ParserCreate() argument 2 must be string or None, not int
-Caught expected ValueError:
-namespace_separator must be at most one character, omitted, or None
-Passed test_attrs_empty
-Passed test_attrs_wattr
-Passed test_double_quoteattr
-Passed test_escape_all
-Passed test_escape_basic
-Passed test_escape_extra
-Passed test_expat_attrs_empty
-Passed test_expat_attrs_wattr
-Passed test_expat_dtdhandler
-Passed test_expat_entityresolver
-Passed test_expat_file
-Passed test_expat_incomplete
-Passed test_expat_incremental
-Passed test_expat_incremental_reset
-Passed test_expat_inpsource_filename
-Passed test_expat_inpsource_location
-Passed test_expat_inpsource_stream
-Passed test_expat_inpsource_sysid
-Passed test_expat_locator_noinfo
-Passed test_expat_locator_withinfo
-Passed test_expat_nsattrs_empty
-Passed test_expat_nsattrs_wattr
-Passed test_filter_basic
-Passed test_make_parser
-Passed test_make_parser2
-Passed test_nsattrs_empty
-Passed test_nsattrs_wattr
-Passed test_quoteattr_basic
-Passed test_single_double_quoteattr
-Passed test_single_quoteattr
-Passed test_xmlgen_attr_escape
-Passed test_xmlgen_basic
-Passed test_xmlgen_content
-Passed test_xmlgen_content_escape
-Passed test_xmlgen_ignorable
-Passed test_xmlgen_ns
-Passed test_xmlgen_pi
-37 tests, 0 failures

Modified: python/trunk/Lib/test/test_minidom.py
==============================================================================
--- python/trunk/Lib/test/test_minidom.py	(original)
+++ python/trunk/Lib/test/test_minidom.py	Thu Mar 29 01:34:06 2007
@@ -5,7 +5,8 @@
 import pickle
 import traceback
 from StringIO import StringIO
-from test.test_support import verbose
+from test.test_support import verbose, run_unittest, TestSkipped
+import unittest
 
 import xml.dom
 import xml.dom.minidom
@@ -22,682 +23,9 @@
 tstfile = os.path.join(os.path.dirname(base), "test"+os.extsep+"xml")
 del base
 
-def confirm(test, testname = "Test"):
-    if not test:
-        print "Failed " + testname
-        raise Exception
-
-def testParseFromFile():
-    dom = parse(StringIO(open(tstfile).read()))
-    dom.unlink()
-    confirm(isinstance(dom,Document))
-
-def testGetElementsByTagName():
-    dom = parse(tstfile)
-    confirm(dom.getElementsByTagName("LI") == \
-            dom.documentElement.getElementsByTagName("LI"))
-    dom.unlink()
-
-def testInsertBefore():
-    dom = parseString("<doc><foo/></doc>")
-    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() == "<doc><element/><foo/></doc>"
-            , "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() == "<doc><element/><foo/><element/></doc>"
-            , "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() == "<doc><element/><foo/><bar/><element/></doc>"
-            , "testInsertBefore -- node properly placed in tree")
-    dom.unlink()
-
-def _create_fragment_test_nodes():
-    dom = parseString("<doc/>")
-    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():
-    dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
-    dom.documentElement.insertBefore(frag, None)
-    confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3),
-            "insertBefore(<fragment>, 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),
-            "insertBefore(<fragment>, orig)")
-    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 testAppendChildFragment():
-    dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
-    dom.documentElement.appendChild(frag)
-    confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3),
-            "appendChild(<fragment>)")
-    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),
-            "replaceChild(<fragment>)")
-    frag.unlink()
-    dom.unlink()
-
-def testLegalChildren():
-    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"
-
-    dom.appendChild(elem)
-    try: dom.insertBefore(text, elem)
-    except xml.dom.HierarchyRequestErr: pass
-    else:
-        print "dom.appendChild didn't raise HierarchyRequestErr"
-
-    try: dom.replaceChild(text, elem)
-    except xml.dom.HierarchyRequestErr: pass
-    else:
-        print "dom.appendChild didn't raise HierarchyRequestErr"
-
-    nodemap = elem.attributes
-    try: nodemap.setNamedItem(text)
-    except xml.dom.HierarchyRequestErr: pass
-    else:
-        print "NamedNodeMap.setNamedItem didn't raise HierarchyRequestErr"
-
-    try: nodemap.setNamedItemNS(text)
-    except xml.dom.HierarchyRequestErr: pass
-    else:
-        print "NamedNodeMap.setNamedItemNS didn't raise HierarchyRequestErr"
-
-    elem.appendChild(text)
-    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 testNonZero():
-    dom = parse(tstfile)
-    confirm(dom)# should not be zero
-    dom.appendChild(dom.createComment("foo"))
-    confirm(not dom.childNodes[-1].childNodes)
-    dom.unlink()
-
-def testUnlink():
-    dom = parse(tstfile)
-    dom.unlink()
-
-def testElement():
-    dom = Document()
-    dom.appendChild(dom.createElement("abc"))
-    confirm(dom.documentElement)
-    dom.unlink()
-
-def testAAA():
-    dom = parseString("<abc/>")
-    el = dom.documentElement
-    el.setAttribute("spam", "jam2")
-    confirm(el.toxml() == '<abc spam="jam2"/>', "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 testAAB():
-    dom = parseString("<abc/>")
-    el = dom.documentElement
-    el.setAttribute("spam", "jam")
-    el.setAttribute("spam", "jam2")
-    confirm(el.toxml() == '<abc spam="jam2"/>', "testAAB")
-    dom.unlink()
-
-def testAddAttr():
-    dom = Document()
-    child = dom.appendChild(dom.createElement("abc"))
-
-    child.setAttribute("def", "ghi")
-    confirm(child.getAttribute("def") == "ghi")
-    confirm(child.attributes["def"].value == "ghi")
-
-    child.setAttribute("jkl", "mno")
-    confirm(child.getAttribute("jkl") == "mno")
-    confirm(child.attributes["jkl"].value == "mno")
-
-    confirm(len(child.attributes) == 2)
-
-    child.setAttribute("def", "newval")
-    confirm(child.getAttribute("def") == "newval")
-    confirm(child.attributes["def"].value == "newval")
-
-    confirm(len(child.attributes) == 2)
-    dom.unlink()
-
-def testDeleteAttr():
-    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()
-
-def testRemoveAttr():
-    dom = Document()
-    child = dom.appendChild(dom.createElement("abc"))
-
-    child.setAttribute("def", "ghi")
-    confirm(len(child.attributes) == 1)
-    child.removeAttribute("def")
-    confirm(len(child.attributes) == 0)
-
-    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)
-
-    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)
-
-    dom.unlink()
-
-def testChangeAttr():
-    dom = parseString("<abc/>")
-    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 testGetAttrList():
-    pass
-
-def testGetAttrValues(): pass
-
-def testGetAttrLength(): pass
-
-def testGetAttribute(): pass
-
-def testGetAttributeNS(): pass
-
-def testGetAttributeNode(): pass
-
-def testGetElementsByTagNameNS():
-    d="""<foo xmlns:minidom='http://pyxml.sf.net/minidom'>
-    <minidom:myelem/>
-    </foo>"""
-    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 get_empty_nodelist_from_elements_by_tagName_ns_helper(doc, nsuri, lname):
-    nodelist = doc.getElementsByTagNameNS(nsuri, lname)
-    confirm(len(nodelist) == 0)
-
-def testGetEmptyNodeListFromElementsByTagNameNS():
-    doc = parseString('<doc/>')
-    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', '*')
-
-    doc = parseString('<doc xmlns="http://xml.python.org/splat"><e/></doc>')
-    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 testElementReprAndStr():
-    dom = Document()
-    el = dom.appendChild(dom.createElement("abc"))
-    string1 = repr(el)
-    string2 = str(el)
-    confirm(string1 == string2)
-    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()
-
-# 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 testAttributeRepr():
-    dom = Document()
-    el = dom.appendChild(dom.createElement(u"abc"))
-    node = el.setAttribute("abc", "def")
-    confirm(str(node) == repr(node))
-    dom.unlink()
-
-def testTextNodeRepr(): pass
-
-def testWriteXML():
-    str = '<?xml version="1.0" ?><a b="c"/>'
-    dom = parseString(str)
-    domstr = dom.toxml()
-    dom.unlink()
-    confirm(str == domstr)
-
-def testAltNewline():
-    str = '<?xml version="1.0" ?>\n<a b="c"/>\n'
-    dom = parseString(str)
-    domstr = dom.toprettyxml(newl="\r\n")
-    dom.unlink()
-    confirm(domstr == str.replace("\n", "\r\n"))
-
-def testProcessingInstruction():
-    dom = parseString('<e><?mypi \t\n data \t\n ?></e>')
-    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 testProcessingInstructionRepr(): pass
-
-def testTextRepr(): pass
-
-def testWriteText(): pass
-
-def testDocumentElement(): pass
-
-def testTooManyDocumentElements():
-    doc = parseString("<doc/>")
-    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 testCreateElementNS(): pass
-
-def testCreateAttributeNS(): pass
-
-def testParse(): pass
-
-def testParseString(): pass
-
-def testComment(): pass
-
-def testAttrListItem(): pass
-
-def testAttrListItems(): pass
-
-def testAttrListItemNS(): pass
-
-def testAttrListKeys(): pass
-
-def testAttrListKeysNS(): pass
-
-def testRemoveNamedItem():
-    doc = parseString("<doc a=''/>")
-    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 testRemoveNamedItemNS():
-    doc = parseString("<doc xmlns:a='http://xml.python.org/' a:b=''/>")
-    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 testAttrListValues(): pass
-
-def testAttrListLength(): pass
-
-def testAttrList__getitem__(): pass
-
-def testAttrList__setitem__(): pass
-
-def testSetAttrValueandNodeValue(): pass
-
-def testParseElement(): pass
-
-def testParseAttributes(): pass
-
-def testParseElementNamespaces(): pass
-
-def testParseAttributeNamespaces(): pass
-
-def testParseProcessingInstructions(): pass
-
-def testChildNodes(): pass
-
-def testFirstChild(): pass
-
-def testHasChildNodes(): pass
-
-def testCloneElementShallow():
-    dom, clone = _setupCloneElement(0)
-    confirm(len(clone.childNodes) == 0
-            and clone.childNodes.length == 0
-            and clone.parentNode is None
-            and clone.toxml() == '<doc attr="value"/>'
-            , "testCloneElementShallow")
-    dom.unlink()
-
-def testCloneElementDeep():
-    dom, clone = _setupCloneElement(1)
-    confirm(len(clone.childNodes) == 1
-            and clone.childNodes.length == 1
-            and clone.parentNode is None
-            and clone.toxml() == '<doc attr="value"><foo/></doc>'
-            , "testCloneElementDeep")
-    dom.unlink()
-
-def _setupCloneElement(deep):
-    dom = parseString("<doc attr='value'><foo/></doc>")
-    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("<?xml version='1.0'?>\n"
-                      "<!-- comment -->"
-                      "<!DOCTYPE doc [\n"
-                      "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
-                      "]>\n"
-                      "<doc attr='value'/>")
-    doc2 = doc.cloneNode(0)
-    confirm(doc2 is None,
-            "testCloneDocumentShallow:"
-            " shallow cloning of documents makes no sense!")
-
-def testCloneDocumentDeep():
-    doc = parseString("<?xml version='1.0'?>\n"
-                      "<!-- comment -->"
-                      "<!DOCTYPE doc [\n"
-                      "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
-                      "]>\n"
-                      "<doc attr='value'/>")
-    doc2 = doc.cloneNode(1)
-    confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)),
-            "testCloneDocumentDeep: document objects not distinct")
-    confirm(len(doc.childNodes) == len(doc2.childNodes),
-            "testCloneDocumentDeep: wrong number of Document children")
-    confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE,
-            "testCloneDocumentDeep: documentElement not an ELEMENT_NODE")
-    confirm(doc2.documentElement.ownerDocument.isSameNode(doc2),
-            "testCloneDocumentDeep: documentElement owner is not new document")
-    confirm(not 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))
-
-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 testCloneDocumentTypeDeepNotOk():
-    doc = create_doc_with_doctype()
-    clone = doc.doctype.cloneNode(1)
-    confirm(clone is None, "testCloneDocumentTypeDeepNotOk")
-
-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 testCloneDocumentTypeShallowNotOk():
-    doc = create_doc_with_doctype()
-    clone = doc.doctype.cloneNode(0)
-    confirm(clone is None, "testCloneDocumentTypeShallowNotOk")
-
-def check_import_document(deep, testName):
-    doc1 = parseString("<doc/>")
-    doc2 = parseString("<doc/>")
-    try:
-        doc1.importNode(doc2, deep)
-    except xml.dom.NotSupportedErr:
-        pass
-    else:
-        raise Exception(testName +
-                        ": expected NotSupportedErr when importing a document")
-
-def testImportDocumentShallow():
-    check_import_document(0, "testImportDocumentShallow")
-
-def testImportDocumentDeep():
-    check_import_document(1, "testImportDocumentDeep")
-
 # 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)
 
@@ -724,674 +52,1263 @@
     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 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")
-
-# 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("<doc attr='value'/>")
-    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")
-
-def testCloneAttributeShallow():
-    check_clone_attribute(0, "testCloneAttributeShallow")
-
-def testCloneAttributeDeep():
-    check_clone_attribute(1, "testCloneAttributeDeep")
-
-def check_clone_pi(deep, testName):
-    doc = parseString("<?target data?><doc/>")
-    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 testClonePIShallow():
-    check_clone_pi(0, "testClonePIShallow")
-
-def testClonePIDeep():
-    check_clone_pi(1, "testClonePIDeep")
-
-def testNormalize():
-    doc = parseString("<doc/>")
-    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()
-
-    doc = parseString("<doc/>")
-    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()
-
-def testSiblings():
-    doc = parseString("<doc><?pi?>text?<elm/></doc>")
-    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")
-
-    doc.unlink()
-
-def testParents():
-    doc = parseString("<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
-    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")
-
-    doc.unlink()
-
-def testNodeListItem():
-    doc = parseString("<doc><e/><e/></doc>")
-    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 testSAX2DOM():
-    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()
-
-    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")
-
-    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")
-
-    doc.unlink()
-
-def testEncodings():
-    doc = parseString('<foo>&#x20ac;</foo>')
-    confirm(doc.toxml() == u'<?xml version="1.0" ?><foo>\u20ac</foo>'
-            and doc.toxml('utf-8') == '<?xml version="1.0" encoding="utf-8"?><foo>\xe2\x82\xac</foo>'
-            and doc.toxml('iso-8859-15') == '<?xml version="1.0" encoding="iso-8859-15"?><foo>\xa4</foo>',
-            "testEncodings - encoding EURO SIGN")
-
-    # Verify that character decoding errors throw exceptions instead of crashing
-    try:
-        doc = parseString('<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')
-    except UnicodeDecodeError:
-        pass
-    else:
-        print 'parsing with bad encoding should raise a UnicodeDecodeError'
-
-    doc.unlink()
-
-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():
-    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)
-
-    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()
-
-def testRenameAttribute():
-    doc = parseString("<doc a='v'/>")
-    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))
-
-    # 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, 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 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))
-
-    try:
-        doc.renameNode(attr, "http://xml.python.org/ns", "xmlns")
-    except xml.dom.NamespaceErr:
-        pass
-    else:
-        print "expected NamespaceErr"
-
-    checkRenameNodeSharedConstraints(doc, attr)
-    doc.unlink()
-
-def testRenameElement():
-    doc = parseString("<doc/>")
-    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))
-
-    # 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, 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 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))
-
-    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"
-
-    doc2 = parseString("<doc/>")
-    try:
-        doc2.renameNode(node, xml.dom.EMPTY_NAMESPACE, "foo")
-    except xml.dom.WrongDocumentErr:
-        pass
-    else:
-        print "expected WrongDocumentErr"
-
-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:
+class MinidomTest(unittest.TestCase):
+    def tearDown(self):
+        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.
+            pass
+        else:
+            self.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 = {}
+    
+    def confirm(self, test, testname = "Test"):
+        self.assertTrue(test, testname)
+    
+    def checkWholeText(self, node, s):
+        t = node.wholeText
+        self.confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t)))
+    
+    def testParseFromFile(self):
+        dom = parse(StringIO(open(tstfile).read()))
+        dom.unlink()
+        self.confirm(isinstance(dom,Document))
+    
+    def testGetElementsByTagName(self):
+        dom = parse(tstfile)
+        self.confirm(dom.getElementsByTagName("LI") == \
+                dom.documentElement.getElementsByTagName("LI"))
+        dom.unlink()
+    
+    def testInsertBefore(self):
+        dom = parseString("<doc><foo/></doc>")
+        root = dom.documentElement
+        elem = root.childNodes[0]
+        nelem = dom.createElement("element")
+        root.insertBefore(nelem, elem)
+        self.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() == "<doc><element/><foo/></doc>"
+                , "testInsertBefore -- node properly placed in tree")
+        nelem = dom.createElement("element")
+        root.insertBefore(nelem, None)
+        self.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() == "<doc><element/><foo/><element/></doc>"
+                , "testInsertBefore -- node properly placed in tree")
+        nelem2 = dom.createElement("bar")
+        root.insertBefore(nelem2, nelem)
+        self.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() == 
+                "<doc><element/><foo/><bar/><element/></doc>"
+                , "testInsertBefore -- node properly placed in tree")
+        dom.unlink()
+    
+    def _create_fragment_test_nodes(self):
+        dom = parseString("<doc/>")
+        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.confirm(tuple(dom.documentElement.childNodes) == 
+                     (orig, c1, c2, c3),
+                     "insertBefore(<fragment>, None)")
+        frag.unlink()
+        dom.unlink()
+
+        dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
+        dom.documentElement.insertBefore(frag, orig)
+        self.confirm(tuple(dom.documentElement.childNodes) == 
+                     (c1, c2, c3, orig),
+                     "insertBefore(<fragment>, orig)")
+        frag.unlink()
+        dom.unlink()
+    
+    def testAppendChild(self):
+        dom = parse(tstfile)
+        dom.documentElement.appendChild(dom.createComment(u"Hello"))
+        self.confirm(dom.documentElement.childNodes[-1].nodeName == "#comment")
+        self.confirm(dom.documentElement.childNodes[-1].data == "Hello")
+        dom.unlink()
+    
+    def testAppendChildFragment(self):
+        dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
+        dom.documentElement.appendChild(frag)
+        self.confirm(tuple(dom.documentElement.childNodes) == 
+                     (orig, c1, c2, c3),
+                     "appendChild(<fragment>)")
+        frag.unlink()
+        dom.unlink()
+    
+    def testReplaceChildFragment(self):
+        dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
+        dom.documentElement.replaceChild(frag, orig)
+        orig.unlink()
+        self.confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3),
+                "replaceChild(<fragment>)")
+        frag.unlink()
+        dom.unlink()
+    
+    def testLegalChildren(self):
+        dom = Document()
+        elem = dom.createElement('element')
+        text = dom.createTextNode('text')
+        self.assertRaises(xml.dom.HierarchyRequestErr, dom.appendChild, text)
+    
+        dom.appendChild(elem)
+        self.assertRaises(xml.dom.HierarchyRequestErr, dom.insertBefore, text, 
+                          elem)
+        self.assertRaises(xml.dom.HierarchyRequestErr, dom.replaceChild, text, 
+                          elem)
+    
+        nodemap = elem.attributes
+        self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItem, 
+                          text)
+        self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItemNS, 
+                          text)
+    
+        elem.appendChild(text)
+        dom.unlink()
+    
+    def testNamedNodeMapSetItem(self):
+        dom = Document()
+        elem = dom.createElement('element')
+        attrs = elem.attributes
+        attrs["foo"] = "bar"
+        a = attrs.item(0)
+        self.confirm(a.ownerDocument is dom,
+                "NamedNodeMap.__setitem__() sets ownerDocument")
+        self.confirm(a.ownerElement is elem,
+                "NamedNodeMap.__setitem__() sets ownerElement")
+        self.confirm(a.value == "bar",
+                "NamedNodeMap.__setitem__() sets value")
+        self.confirm(a.nodeValue == "bar",
+                "NamedNodeMap.__setitem__() sets nodeValue")
+        elem.unlink()
+        dom.unlink()
+    
+    def testNonZero(self):
+        dom = parse(tstfile)
+        self.confirm(dom)# should not be zero
+        dom.appendChild(dom.createComment("foo"))
+        self.confirm(not dom.childNodes[-1].childNodes)
+        dom.unlink()
+    
+    def testUnlink(self):
+        dom = parse(tstfile)
+        dom.unlink()
+    
+    def testElement(self):
+        dom = Document()
+        dom.appendChild(dom.createElement("abc"))
+        self.confirm(dom.documentElement)
+        dom.unlink()
+    
+    def testAAA(self):
+        dom = parseString("<abc/>")
+        el = dom.documentElement
+        el.setAttribute("spam", "jam2")
+        self.confirm(el.toxml() == '<abc spam="jam2"/>', "testAAA")
+        a = el.getAttributeNode("spam")
+        self.confirm(a.ownerDocument is dom,
+                "setAttribute() sets ownerDocument")
+        self.confirm(a.ownerElement is dom.documentElement,
+                "setAttribute() sets ownerElement")
+        dom.unlink()
+    
+    def testAAB(self):
+        dom = parseString("<abc/>")
+        el = dom.documentElement
+        el.setAttribute("spam", "jam")
+        el.setAttribute("spam", "jam2")
+        self.confirm(el.toxml() == '<abc spam="jam2"/>', "testAAB")
+        dom.unlink()
+    
+    def testAddAttr(self):
+        dom = Document()
+        child = dom.appendChild(dom.createElement("abc"))
+    
+        child.setAttribute("def", "ghi")
+        self.confirm(child.getAttribute("def") == "ghi")
+        self.confirm(child.attributes["def"].value == "ghi")
+    
+        child.setAttribute("jkl", "mno")
+        self.confirm(child.getAttribute("jkl") == "mno")
+        self.confirm(child.attributes["jkl"].value == "mno")
+    
+        self.confirm(len(child.attributes) == 2)
+    
+        child.setAttribute("def", "newval")
+        self.confirm(child.getAttribute("def") == "newval")
+        self.confirm(child.attributes["def"].value == "newval")
+    
+        self.confirm(len(child.attributes) == 2)
+        dom.unlink()
+    
+    def testDeleteAttr(self):
+        dom = Document()
+        child = dom.appendChild(dom.createElement("abc"))
+    
+        self.confirm(len(child.attributes) == 0)
+        child.setAttribute("def", "ghi")
+        self.confirm(len(child.attributes) == 1)
+        del child.attributes["def"]
+        self.confirm(len(child.attributes) == 0)
+        dom.unlink()
+    
+    def testRemoveAttr(self):
+        dom = Document()
+        child = dom.appendChild(dom.createElement("abc"))
+    
+        child.setAttribute("def", "ghi")
+        self.confirm(len(child.attributes) == 1)
+        child.removeAttribute("def")
+        self.confirm(len(child.attributes) == 0)
+        dom.unlink()
+    
+    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.confirm(len(child.attributes) == 2)
+        child.removeAttributeNS("http://www.python.org", "abcattr")
+        self.confirm(len(child.attributes) == 1)
+        dom.unlink()
+    
+    def testRemoveAttributeNode(self):
+        dom = Document()
+        child = dom.appendChild(dom.createElement("foo"))
+        child.setAttribute("spam", "jam")
+        self.confirm(len(child.attributes) == 1)
+        node = child.getAttributeNode("spam")
+        child.removeAttributeNode(node)
+        self.confirm(len(child.attributes) == 0
+                and child.getAttributeNode("spam") is None)
+        dom.unlink()
+    
+    def testChangeAttr(self):
+        dom = parseString("<abc/>")
+        el = dom.documentElement
+        el.setAttribute("spam", "jam")
+        self.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")
+        self.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"
+        self.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")
+        self.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"
+        self.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 testGetAttrList(self):
         pass
-    else:
-        print "expected NotSupportedErr when renaming comment node"
-    doc.unlink()
-
-def checkWholeText(node, s):
-    t = node.wholeText
-    confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t)))
-
-def testWholeText():
-    doc = parseString("<doc>a</doc>")
-    elem = doc.documentElement
-    text = elem.childNodes[0]
-    assert text.nodeType == Node.TEXT_NODE
-
-    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)
-    checkWholeText(text, "cab")
-    checkWholeText(text2, "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
-    checkWholeText(text, "cab")
-    checkWholeText(text2, "d")
-
-    elem.removeChild(splitter)
-    checkWholeText(text, "cabd")
-    checkWholeText(text2, "cabd")
-
-def testPatch1094164 ():
-    doc = parseString("<doc><e/></doc>")
-    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 testGetAttrValues(self): pass
+    
+    def testGetAttrLength(self): pass
+    
+    def testGetAttribute(self): pass
+    
+    def testGetAttributeNS(self): pass
+    
+    def testGetAttributeNode(self): pass
+    
+    def testGetElementsByTagNameNS(self):
+        d="""<foo xmlns:minidom='http://pyxml.sf.net/minidom'>
+        <minidom:myelem/>
+        </foo>"""
+        dom = parseString(d)
+        elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom", 
+                                           "myelem")
+        self.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 get_empty_nodelist_from_elements_by_tagName_ns_helper(self, doc, nsuri, 
+                                                              lname):
+        nodelist = doc.getElementsByTagNameNS(nsuri, lname)
+        self.confirm(len(nodelist) == 0)
+    
+    def testGetEmptyNodeListFromElementsByTagNameNS(self):
+        doc = parseString('<doc/>')
+        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 = parseString('<doc xmlns="http://xml.python.org/splat"><e/></doc>')
+        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")
+    
+    def testElementReprAndStr(self):
+        dom = Document()
+        el = dom.appendChild(dom.createElement("abc"))
+        string1 = repr(el)
+        string2 = str(el)
+        self.confirm(string1 == string2)
+        dom.unlink()
+    
+    def testElementReprAndStrUnicode(self):
+        dom = Document()
+        el = dom.appendChild(dom.createElement(u"abc"))
+        string1 = repr(el)
+        string2 = str(el)
+        self.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.confirm(string1 == string2)
+        self.confirm(string1.find("slash:abc") != -1)
+        dom.unlink()
+    
+    def testAttributeRepr(self):
+        dom = Document()
+        el = dom.appendChild(dom.createElement(u"abc"))
+        node = el.setAttribute("abc", "def")
+        self.confirm(str(node) == repr(node))
+        dom.unlink()
+    
+    def testTextNodeRepr(self): pass
+    
+    def testWriteXML(self):
+        str = '<?xml version="1.0" ?><a b="c"/>'
+        dom = parseString(str)
+        domstr = dom.toxml()
+        dom.unlink()
+        self.confirm(str == domstr)
+    
+    def testAltNewline(self):
+        str = '<?xml version="1.0" ?>\n<a b="c"/>\n'
+        dom = parseString(str)
+        domstr = dom.toprettyxml(newl="\r\n")
+        dom.unlink()
+        self.confirm(domstr == str.replace("\n", "\r\n"))
+    
+    def testProcessingInstruction(self):
+        dom = parseString('<e><?mypi \t\n data \t\n ?></e>')
+        pi = dom.documentElement.firstChild
+        self.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 testProcessingInstructionRepr(self): pass
+    
+    def testTextRepr(self): pass
+    
+    def testWriteText(self): pass
+    
+    def testDocumentElement(self): pass
+    
+    def testTooManyDocumentElements(self):
+        doc = parseString("<doc/>")
+        elem = doc.createElement("extra")
+        # Should raise an exception when adding an extra document element.
+        self.assertRaises(xml.dom.HierarchyRequestErr, doc.appendChild, elem)
+        elem.unlink()
+        doc.unlink()
+    
+    def testCreateElementNS(self): pass
+    
+    def testCreateAttributeNS(self): pass
+    
+    def testParse(self): pass
+    
+    def testParseString(self): pass
+    
+    def testComment(self): pass
+    
+    def testAttrListItem(self): pass
+    
+    def testAttrListItems(self): pass
+    
+    def testAttrListItemNS(self): pass
+    
+    def testAttrListKeys(self): pass
+    
+    def testAttrListKeysNS(self): pass
+    
+    def testRemoveNamedItem(self):
+        doc = parseString("<doc a=''/>")
+        e = doc.documentElement
+        attrs = e.attributes
+        a1 = e.getAttributeNode("a")
+        a2 = attrs.removeNamedItem("a")
+        self.confirm(a1.isSameNode(a2))
+        self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItem, "a")
+    
+    def testRemoveNamedItemNS(self):
+        doc = parseString("<doc xmlns:a='http://xml.python.org/' a:b=''/>")
+        e = doc.documentElement
+        attrs = e.attributes
+        a1 = e.getAttributeNodeNS("http://xml.python.org/", "b")
+        a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b")
+        self.confirm(a1.isSameNode(a2))
+        self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItemNS, 
+                          "http://xml.python.org/", "b")
+    
+    def testAttrListValues(self): pass
+    
+    def testAttrListLength(self): pass
+    
+    def testAttrList__getitem__(self): pass
+    
+    def testAttrList__setitem__(self): pass
+    
+    def testSetAttrValueandNodeValue(self): pass
+    
+    def testParseElement(self): pass
+    
+    def testParseAttributes(self): pass
+    
+    def testParseElementNamespaces(self): pass
+    
+    def testParseAttributeNamespaces(self): pass
+    
+    def testParseProcessingInstructions(self): pass
+    
+    def testChildNodes(self): pass
+    
+    def testFirstChild(self): pass
+    
+    def testHasChildNodes(self): pass
+
+    def _testCloneElementCopiesAttributes(self, e1, e2, test):
+        attrs1 = e1.attributes
+        attrs2 = e2.attributes
+        keys1 = attrs1.keys()
+        keys2 = attrs2.keys()
+        keys1.sort()
+        keys2.sort()
+        self.confirm(keys1 == keys2, "clone of element has same attribute keys")
+        for i in range(len(keys1)):
+            a1 = attrs1.item(i)
+            a2 = attrs2.item(i)
+            self.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")
+            self.confirm(a2.ownerElement is e2,
+                    "clone of attribute node correctly owned")
+    
+    def _setupCloneElement(self, deep):
+        dom = parseString("<doc attr='value'><foo/></doc>")
+        root = dom.documentElement
+        clone = root.cloneNode(deep)
+        self._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 testCloneElementShallow(self):
+        dom, clone = self._setupCloneElement(0)
+        self.confirm(len(clone.childNodes) == 0
+                and clone.childNodes.length == 0
+                and clone.parentNode is None
+                and clone.toxml() == '<doc attr="value"/>'
+                , "testCloneElementShallow")
+        dom.unlink()
+    
+    def testCloneElementDeep(self):
+        dom, clone = self._setupCloneElement(1)
+        self.confirm(len(clone.childNodes) == 1
+                and clone.childNodes.length == 1
+                and clone.parentNode is None
+                and clone.toxml() == '<doc attr="value"><foo/></doc>'
+                , "testCloneElementDeep")
+        dom.unlink()
+
+    def testCloneDocumentShallow(self):
+        doc = parseString("<?xml version='1.0'?>\n"
+                    "<!-- comment -->"
+                    "<!DOCTYPE doc [\n"
+                    "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
+                    "]>\n"
+                    "<doc attr='value'/>")
+        doc2 = doc.cloneNode(0)
+        self.confirm(doc2 is None,
+                "testCloneDocumentShallow:"
+                " shallow cloning of documents makes no sense!")
+
+    def testCloneDocumentDeep(self):
+        doc = parseString("<?xml version='1.0'?>\n"
+                    "<!-- comment -->"
+                    "<!DOCTYPE doc [\n"
+                    "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
+                    "]>\n"
+                    "<doc attr='value'/>")
+        doc2 = doc.cloneNode(1)
+        self.confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)),
+                "testCloneDocumentDeep: document objects not distinct")
+        self.confirm(len(doc.childNodes) == len(doc2.childNodes),
+                "testCloneDocumentDeep: wrong number of Document children")
+        self.confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE,
+                "testCloneDocumentDeep: documentElement not an ELEMENT_NODE")
+        self.confirm(doc2.documentElement.ownerDocument.isSameNode(doc2),
+            "testCloneDocumentDeep: documentElement owner is not new document")
+        self.confirm(not 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
+            self.confirm(doc2.doctype.nodeType == Node.DOCUMENT_TYPE_NODE,
+                    "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE")
+            self.confirm(doc2.doctype.ownerDocument.isSameNode(doc2))
+            self.confirm(not doc.doctype.isSameNode(doc2.doctype))
+
+    def testCloneDocumentTypeDeepOk(self):
+        doctype = create_nonempty_doctype()
+        clone = doctype.cloneNode(1)
+        self.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)
+            self.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)
+            self.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 testCloneDocumentTypeDeepNotOk(self):
+        doc = create_doc_with_doctype()
+        clone = doc.doctype.cloneNode(1)
+        self.confirm(clone is None, "testCloneDocumentTypeDeepNotOk")
+
+    def testCloneDocumentTypeShallowOk(self):
+        doctype = create_nonempty_doctype()
+        clone = doctype.cloneNode(0)
+        self.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 testCloneDocumentTypeShallowNotOk(self):
+        doc = create_doc_with_doctype()
+        clone = doc.doctype.cloneNode(0)
+        self.confirm(clone is None, "testCloneDocumentTypeShallowNotOk")
+
+    def check_import_document(self, deep, testName):
+        doc1 = parseString("<doc/>")
+        doc2 = parseString("<doc/>")
+        self.assertRaises(xml.dom.NotSupportedErr, doc1.importNode, doc2, deep)
+    
+    def testImportDocumentShallow(self):
+        self.check_import_document(0, "testImportDocumentShallow")
+    
+    def testImportDocumentDeep(self):
+        self.check_import_document(1, "testImportDocumentDeep")
+    
+    def testImportDocumentTypeShallow(self):
+        src = create_doc_with_doctype()
+        target = create_doc_without_doctype()
+        self.assertRaises(xml.dom.NotSupportedErr, target.importNode, 
+                          src.doctype, 0)
+    
+    def testImportDocumentTypeDeep(self):
+        src = create_doc_with_doctype()
+        target = create_doc_without_doctype()
+        self.assertRaises(xml.dom.NotSupportedErr, target.importNode, 
+                          src.doctype, 1)
+    
+    # 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("<doc attr='value'/>")
+        attr = doc.documentElement.getAttributeNode("attr")
+        self.failIfEqual(attr, None)
+        clone = attr.cloneNode(deep)
+        self.confirm(not clone.isSameNode(attr))
+        self.confirm(not attr.isSameNode(clone))
+        self.confirm(clone.ownerElement is None,
+                testName + ": ownerElement should be None")
+        self.confirm(clone.ownerDocument.isSameNode(attr.ownerDocument),
+                testName + ": ownerDocument does not match")
+        self.confirm(clone.specified,
+                testName + ": cloned attribute must have specified == True")
+    
+    def testCloneAttributeShallow(self):
+        self.check_clone_attribute(0, "testCloneAttributeShallow")
+    
+    def testCloneAttributeDeep(self):
+        self.check_clone_attribute(1, "testCloneAttributeDeep")
+    
+    def check_clone_pi(self, deep, testName):
+        doc = parseString("<?target data?><doc/>")
+        pi = doc.firstChild
+        self.assertEquals(pi.nodeType, Node.PROCESSING_INSTRUCTION_NODE)
+        clone = pi.cloneNode(deep)
+        self.confirm(clone.target == pi.target
+                and clone.data == pi.data)
+    
+    def testClonePIShallow(self):
+        self.check_clone_pi(0, "testClonePIShallow")
+    
+    def testClonePIDeep(self):
+        self.check_clone_pi(1, "testClonePIDeep")
+
+    def testNormalize(self):
+        doc = parseString("<doc/>")
+        root = doc.documentElement
+        root.appendChild(doc.createTextNode("first"))
+        root.appendChild(doc.createTextNode("second"))
+        self.confirm(len(root.childNodes) == 2
+                and root.childNodes.length == 2, 
+                "testNormalize -- preparation")
+        doc.normalize()
+        self.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()
+    
+        doc = parseString("<doc/>")
+        root = doc.documentElement
+        root.appendChild(doc.createTextNode(""))
+        doc.normalize()
+        self.confirm(len(root.childNodes) == 0
+                and root.childNodes.length == 0,
+                "testNormalize -- single empty node removed")
+        doc.unlink()
+    
+    def testSiblings(self):
+        doc = parseString("<doc><?pi?>text?<elm/></doc>")
+        root = doc.documentElement
+        (pi, text, elm) = root.childNodes
+    
+        self.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")
+    
+        doc.unlink()
+    
+    def testParents(self):
+        doc = parseString(
+            "<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
+        root = doc.documentElement
+        elm1 = root.childNodes[0]
+        (elm2a, elm2b) = elm1.childNodes
+        elm3 = elm2b.childNodes[0]
+    
+        self.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")
+        doc.unlink()
+    
+    def testNodeListItem(self):
+        doc = parseString("<doc><e/><e/></doc>")
+        children = doc.childNodes
+        docelem = children[0]
+        self.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 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()
+    
+        doc = sax2dom.document
+        root = doc.documentElement
+        (text1, elm1, text2) = root.childNodes
+        text3 = elm1.childNodes[0]
+    
+        self.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.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")
+        doc.unlink()
+    
+    def testEncodings(self):
+        doc = parseString('<foo>&#x20ac;</foo>')
+        self.confirm(doc.toxml() == u'<?xml version="1.0" ?><foo>\u20ac</foo>'
+                and doc.toxml('utf-8') == 
+                '<?xml version="1.0" encoding="utf-8"?><foo>\xe2\x82\xac</foo>'
+                and doc.toxml('iso-8859-15') == 
+                '<?xml version="1.0" encoding="iso-8859-15"?><foo>\xa4</foo>',
+                "testEncodings - encoding EURO SIGN")
+    
+        # Verify that character decoding errors throw exceptions instead 
+        # of crashing
+        self.assertRaises(UnicodeDecodeError, parseString, 
+                '<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')
+    
+        doc.unlink()
+
+    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.confirm(n.getUserData("foo") is None)
+        n.setUserData("foo", None, None)
+        self.confirm(n.getUserData("foo") is None)
+        n.setUserData("foo", 12, 12)
+        n.setUserData("bar", 13, 13)
+        self.confirm(n.getUserData("foo") == 12)
+        self.confirm(n.getUserData("bar") == 13)
+        n.setUserData("foo", None, None)
+        self.confirm(n.getUserData("foo") is None)
+        self.confirm(n.getUserData("bar") == 13)
+    
+        handler = self.UserDataHandler()
+        n.setUserData("bar", 12, handler)
+        c = n.cloneNode(1)
+        self.confirm(handler.called
+                and n.getUserData("bar") is None
+                and c.getUserData("bar") == 13)
+        n.unlink()
+        c.unlink()
+        dom.unlink()
+
+    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("<doc/>")
+        self.assertRaises(xml.dom.WrongDocumentErr, doc2.renameNode, node, 
+                          xml.dom.EMPTY_NAMESPACE, "foo")
+    
+    def testRenameAttribute(self):
+        doc = parseString("<doc a='v'/>")
+        elem = doc.documentElement
+        attrmap = elem.attributes
+        attr = elem.attributes['a']
+    
+        # Simple renaming
+        attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b")
+        self.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))
+    
+        # Rename to have a namespace, no prefix
+        attr = doc.renameNode(attr, "http://xml.python.org/ns", "c")
+        self.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, with prefix
+        attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d")
+        self.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 back to a simple non-NS node
+        attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e")
+        self.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))
+
+        self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, attr, 
+                          "http://xml.python.org/ns", "xmlns")
+        self.checkRenameNodeSharedConstraints(doc, attr)
+        doc.unlink()
+    
+    def testRenameElement(self):
+        doc = parseString("<doc/>")
+        elem = doc.documentElement
+    
+        # Simple renaming
+        elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a")
+        self.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))
+    
+        # Rename to have a namespace, no prefix
+        elem = doc.renameNode(elem, "http://xml.python.org/ns", "b")
+        self.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, with prefix
+        elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c")
+        self.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 back to a simple non-NS node
+        elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d")
+        self.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))
+    
+        self.checkRenameNodeSharedConstraints(doc, elem)
+        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 testReplaceWholeText():
-    def setup():
-        doc = parseString("<doc>a<e/>d</doc>")
+    def testWholeText(self):
+        doc = parseString("<doc>a</doc>")
+        elem = doc.documentElement
+        text = elem.childNodes[0]
+        self.assertEquals(text.nodeType, Node.TEXT_NODE)
+    
+        self.checkWholeText(text, "a")
+        elem.appendChild(doc.createTextNode("b"))
+        self.checkWholeText(text, "ab")
+        elem.insertBefore(doc.createCDATASection("c"), text)
+        self.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.checkWholeText(text, "cab")
+        self.checkWholeText(text2, "d")
+    
+        x = doc.createElement("x")
+        elem.replaceChild(x, splitter)
+        splitter = x
+        self.checkWholeText(text, "cab")
+        self.checkWholeText(text2, "d")
+    
+        x = doc.createProcessingInstruction("y", "z")
+        elem.replaceChild(x, splitter)
+        splitter = x
+        self.checkWholeText(text, "cab")
+        self.checkWholeText(text2, "d")
+    
+        elem.removeChild(splitter)
+        self.checkWholeText(text, "cabd")
+        self.checkWholeText(text2, "cabd")
+    
+    def testPatch1094164(self):
+        doc = parseString("<doc><e/></doc>")
+        elem = doc.documentElement
+        e = elem.firstChild
+        self.confirm(e.parentNode is elem, "Before replaceChild()")
+        # Check that replacing a child with itself leaves the tree unchanged
+        elem.replaceChild(e, e)
+        self.confirm(e.parentNode is elem, "After replaceChild()")
+    
+    def testReplaceWholeText(self):
+        def setup():
+            doc = parseString("<doc>a<e/>d</doc>")
+            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.checkWholeText(text, "new content")
+        self.checkWholeText(text2, "d")
+        self.confirm(len(elem.childNodes) == 3)
+    
+        doc, elem, text1, splitter, text2 = setup()
+        text = text2.replaceWholeText("new content")
+        self.checkWholeText(text, "new content")
+        self.checkWholeText(text1, "cab")
+        self.confirm(len(elem.childNodes) == 5)
+    
+        doc, elem, text1, splitter, text2 = setup()
+        text = text1.replaceWholeText("")
+        self.checkWholeText(text2, "d")
+        self.confirm(text is None
+                and len(elem.childNodes) == 2)
+    
+    def testSchemaType(self):
+        doc = parseString(
+            "<!DOCTYPE doc [\n"
+            "  <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n"
+            "  <!ENTITY e2 SYSTEM 'http://xml.python.org/e2'>\n"
+            "  <!ATTLIST doc id   ID       #IMPLIED \n"
+            "                ref  IDREF    #IMPLIED \n"
+            "                refs IDREFS   #IMPLIED \n"
+            "                enum (a|b)    #IMPLIED \n"
+            "                ent  ENTITY   #IMPLIED \n"
+            "                ents ENTITIES #IMPLIED \n"
+            "                nm   NMTOKEN  #IMPLIED \n"
+            "                nms  NMTOKENS #IMPLIED \n"
+            "                text CDATA    #IMPLIED \n"
+            "    >\n"
+            "]><doc id='name' notid='name' text='splat!' enum='b'"
+            "       ref='name' refs='name name' ent='e1' ents='e1 e2'"
+            "       nm='123' nms='123 abc' />")
         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")
-    checkWholeText(text, "new content")
-    checkWholeText(text2, "d")
-    confirm(len(elem.childNodes) == 3)
-
-    doc, elem, text1, splitter, text2 = setup()
-    text = text2.replaceWholeText("new content")
-    checkWholeText(text, "new content")
-    checkWholeText(text1, "cab")
-    confirm(len(elem.childNodes) == 5)
-
-    doc, elem, text1, splitter, text2 = setup()
-    text = text1.replaceWholeText("")
-    checkWholeText(text2, "d")
-    confirm(text is None
-            and len(elem.childNodes) == 2)
-
-def testSchemaType():
-    doc = parseString(
-        "<!DOCTYPE doc [\n"
-        "  <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n"
-        "  <!ENTITY e2 SYSTEM 'http://xml.python.org/e2'>\n"
-        "  <!ATTLIST doc id   ID       #IMPLIED \n"
-        "                ref  IDREF    #IMPLIED \n"
-        "                refs IDREFS   #IMPLIED \n"
-        "                enum (a|b)    #IMPLIED \n"
-        "                ent  ENTITY   #IMPLIED \n"
-        "                ents ENTITIES #IMPLIED \n"
-        "                nm   NMTOKEN  #IMPLIED \n"
-        "                nms  NMTOKENS #IMPLIED \n"
-        "                text CDATA    #IMPLIED \n"
-        "    >\n"
-        "]><doc id='name' notid='name' text='splat!' enum='b'"
-        "       ref='name' refs='name name' ent='e1' ents='e1 e2'"
-        "       nm='123' nms='123 abc' />")
-    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")
+        # 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.confirm(t.name is None
                 and t.namespace == xml.dom.EMPTY_NAMESPACE)
-
-def testSetIdAttribute():
-    doc = parseString("<doc a1='v' a2='w'/>")
-    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 testSetIdAttributeNS():
-    NS1 = "http://xml.python.org/ns1"
-    NS2 = "http://xml.python.org/ns2"
-    doc = parseString("<doc"
-                      " xmlns:ns1='" + NS1 + "'"
-                      " xmlns:ns2='" + NS2 + "'"
-                      " ns1:a1='v' ns2:a2='w'/>")
-    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 testSetIdAttributeNode():
-    NS1 = "http://xml.python.org/ns1"
-    NS2 = "http://xml.python.org/ns2"
-    doc = parseString("<doc"
-                      " xmlns:ns1='" + NS1 + "'"
-                      " xmlns:ns2='" + NS2 + "'"
-                      " ns1:a1='v' ns2:a2='w'/>")
-    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)
-
-def testPickledDocument():
-    doc = parseString("<?xml version='1.0' encoding='us-ascii'?>\n"
-                      "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
-                      " 'http://xml.python.org/system' [\n"
-                      "  <!ELEMENT e EMPTY>\n"
-                      "  <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"
-                      "]><doc attr='value'> text\n"
-                      "<?pi sample?> <!-- comment --> <e/> </doc>")
-    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]))
-
-
-# --- MAIN PROGRAM
-
-names = globals().keys()
-names.sort()
-
-failed = []
-
-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
+        names = "id notid text enum ref refs ent ents nm nms".split()
+        for name in names:
+            a = elem.getAttributeNode(name)
+            t = a.schemaType
+            self.confirm(hasattr(t, "name")
+                    and t.namespace == xml.dom.EMPTY_NAMESPACE)
+    
+    def testSetIdAttribute(self):
+        doc = parseString("<doc a1='v' a2='w'/>")
+        e = doc.documentElement
+        a1 = e.getAttributeNode("a1")
+        a2 = e.getAttributeNode("a2")
+        self.confirm(doc.getElementById("v") is None
+                and not a1.isId
+                and not a2.isId)
+        e.setIdAttribute("a1")
+        self.confirm(e.isSameNode(doc.getElementById("v"))
+                and a1.isId
+                and not a2.isId)
+        e.setIdAttribute("a2")
+        self.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)
+        self.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")
+        self.confirm(e.isSameNode(doc.getElementById("w"))
+                and a2.isId)
+    
+    def testSetIdAttributeNS(self):
+        NS1 = "http://xml.python.org/ns1"
+        NS2 = "http://xml.python.org/ns2"
+        doc = parseString("<doc"
+                          " xmlns:ns1='" + NS1 + "'"
+                          " xmlns:ns2='" + NS2 + "'"
+                          " ns1:a1='v' ns2:a2='w'/>")
+        e = doc.documentElement
+        a1 = e.getAttributeNodeNS(NS1, "a1")
+        a2 = e.getAttributeNodeNS(NS2, "a2")
+        self.confirm(doc.getElementById("v") is None
+                and not a1.isId
+                and not a2.isId)
+        e.setIdAttributeNS(NS1, "a1")
+        self.confirm(e.isSameNode(doc.getElementById("v"))
+                and a1.isId
+                and not a2.isId)
+        e.setIdAttributeNS(NS2, "a2")
+        self.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)
+        self.confirm(e.isSameNode(doc.getElementById("w")))
+        self.confirm(not a1.isId)
+        self.confirm(a2.isId)
+        self.confirm(not a3.isId)
+        self.confirm(doc.getElementById("v") is None)
+        # renaming an attribute should not affect its ID-ness:
+        doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
+        self.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("<doc"
+                          " xmlns:ns1='" + NS1 + "'"
+                          " xmlns:ns2='" + NS2 + "'"
+                          " ns1:a1='v' ns2:a2='w'/>")
+        e = doc.documentElement
+        a1 = e.getAttributeNodeNS(NS1, "a1")
+        a2 = e.getAttributeNodeNS(NS2, "a2")
+        self.confirm(doc.getElementById("v") is None
+                and not a1.isId
+                and not a2.isId)
+        e.setIdAttributeNode(a1)
+        self.confirm(e.isSameNode(doc.getElementById("v"))
+                and a1.isId
+                and not a2.isId)
+        e.setIdAttributeNode(a2)
+        self.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)
+        self.confirm(e.isSameNode(doc.getElementById("w")))
+        self.confirm(not a1.isId)
+        self.confirm(a2.isId)
+        self.confirm(not a3.isId)
+        self.confirm(doc.getElementById("v") is None)
+        # renaming an attribute should not affect its ID-ness:
+        doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
+        self.confirm(e.isSameNode(doc.getElementById("w"))
+                and a2.isId)
+
+    def testPickledDocument(self):
+        doc = parseString("<?xml version='1.0' encoding='us-ascii'?>\n"
+                    "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
+                    " 'http://xml.python.org/system' [\n"
+                    "  <!ELEMENT e EMPTY>\n"
+                    "  <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"
+                    "]><doc attr='value'> text\n"
+                    "<?pi sample?> <!-- comment --> <e/> </doc>")
+        s = pickle.dumps(doc)
+        doc2 = pickle.loads(s)
+        stack = [(doc, doc2)]
+        while stack:
+            n1, n2 = stack.pop()
+            self.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)
+                self.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)
+                    self.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)
+                    self.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:
+                self.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 test_main():
+    run_unittest(MinidomTest)
+    
+if __name__ == "__main__":
+    test_main()

Modified: python/trunk/Lib/test/test_pyexpat.py
==============================================================================
--- python/trunk/Lib/test/test_pyexpat.py	(original)
+++ python/trunk/Lib/test/test_pyexpat.py	Thu Mar 29 01:34:06 2007
@@ -1,108 +1,40 @@
-# Very simple test - Parse a file and print what happens
-
 # XXX TypeErrors on calling handlers, or on bad return values from a
 # handler, are obscure and unhelpful.
 
+import StringIO
+import unittest
+
 import pyexpat
 from xml.parsers import expat
 
-from test.test_support import sortdict, TestFailed
+from test.test_support import sortdict, run_unittest
 
-class Outputter:
-    def StartElementHandler(self, name, attrs):
-        print 'Start element:\n\t', repr(name), sortdict(attrs)
 
-    def EndElementHandler(self, name):
-        print 'End element:\n\t', repr(name)
+class SetAttributeTest(unittest.TestCase):
+    def setUp(self):
+        self.parser = expat.ParserCreate(namespace_separator='!')
+        self.set_get_pairs = [
+            [0, 0],
+            [1, 1],
+            [2, 1],
+            [0, 0],
+            ]
+        
+    def test_returns_unicode(self):
+        for x, y in self.set_get_pairs:
+            self.parser.returns_unicode = x
+            self.assertEquals(self.parser.returns_unicode, y)
+        
+    def test_ordered_attributes(self):
+        for x, y in self.set_get_pairs:
+            self.parser.ordered_attributes = x
+            self.assertEquals(self.parser.ordered_attributes, y)
+
+    def test_specified_attributes(self):
+        for x, y in self.set_get_pairs:
+            self.parser.specified_attributes = x
+            self.assertEquals(self.parser.specified_attributes, y)
 
-    def CharacterDataHandler(self, data):
-        data = data.strip()
-        if data:
-            print 'Character data:'
-            print '\t', repr(data)
-
-    def ProcessingInstructionHandler(self, target, data):
-        print 'PI:\n\t', repr(target), repr(data)
-
-    def StartNamespaceDeclHandler(self, prefix, uri):
-        print 'NS decl:\n\t', repr(prefix), repr(uri)
-
-    def EndNamespaceDeclHandler(self, prefix):
-        print 'End of NS decl:\n\t', repr(prefix)
-
-    def StartCdataSectionHandler(self):
-        print 'Start of CDATA section'
-
-    def EndCdataSectionHandler(self):
-        print 'End of CDATA section'
-
-    def CommentHandler(self, text):
-        print 'Comment:\n\t', repr(text)
-
-    def NotationDeclHandler(self, *args):
-        name, base, sysid, pubid = args
-        print 'Notation declared:', args
-
-    def UnparsedEntityDeclHandler(self, *args):
-        entityName, base, systemId, publicId, notationName = args
-        print 'Unparsed entity decl:\n\t', args
-
-    def NotStandaloneHandler(self, userData):
-        print 'Not standalone'
-        return 1
-
-    def ExternalEntityRefHandler(self, *args):
-        context, base, sysId, pubId = args
-        print 'External entity ref:', args[1:]
-        return 1
-
-    def DefaultHandler(self, userData):
-        pass
-
-    def DefaultHandlerExpand(self, userData):
-        pass
-
-
-def confirm(ok):
-    if ok:
-        print "OK."
-    else:
-        print "Not OK."
-
-out = Outputter()
-parser = expat.ParserCreate(namespace_separator='!')
-
-# Test getting/setting returns_unicode
-parser.returns_unicode = 0; confirm(parser.returns_unicode == 0)
-parser.returns_unicode = 1; confirm(parser.returns_unicode == 1)
-parser.returns_unicode = 2; confirm(parser.returns_unicode == 1)
-parser.returns_unicode = 0; confirm(parser.returns_unicode == 0)
-
-# Test getting/setting ordered_attributes
-parser.ordered_attributes = 0; confirm(parser.ordered_attributes == 0)
-parser.ordered_attributes = 1; confirm(parser.ordered_attributes == 1)
-parser.ordered_attributes = 2; confirm(parser.ordered_attributes == 1)
-parser.ordered_attributes = 0; confirm(parser.ordered_attributes == 0)
-
-# Test getting/setting specified_attributes
-parser.specified_attributes = 0; confirm(parser.specified_attributes == 0)
-parser.specified_attributes = 1; confirm(parser.specified_attributes == 1)
-parser.specified_attributes = 2; confirm(parser.specified_attributes == 1)
-parser.specified_attributes = 0; confirm(parser.specified_attributes == 0)
-
-HANDLER_NAMES = [
-    'StartElementHandler', 'EndElementHandler',
-    'CharacterDataHandler', 'ProcessingInstructionHandler',
-    'UnparsedEntityDeclHandler', 'NotationDeclHandler',
-    'StartNamespaceDeclHandler', 'EndNamespaceDeclHandler',
-    'CommentHandler', 'StartCdataSectionHandler',
-    'EndCdataSectionHandler',
-    'DefaultHandler', 'DefaultHandlerExpand',
-    #'NotStandaloneHandler',
-    'ExternalEntityRefHandler'
-    ]
-for name in HANDLER_NAMES:
-    setattr(parser, name, getattr(out, name))
 
 data = '''\
 <?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
@@ -126,108 +58,228 @@
 </root>
 '''
 
-# Produce UTF-8 output
-parser.returns_unicode = 0
-try:
-    parser.Parse(data, 1)
-except expat.error:
-    print '** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode)
-    print '** Line', parser.ErrorLineNumber
-    print '** Column', parser.ErrorColumnNumber
-    print '** Byte', parser.ErrorByteIndex
-
-# Try the parse again, this time producing Unicode output
-parser = expat.ParserCreate(namespace_separator='!')
-parser.returns_unicode = 1
-
-for name in HANDLER_NAMES:
-    setattr(parser, name, getattr(out, name))
-try:
-    parser.Parse(data, 1)
-except expat.error:
-    print '** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode)
-    print '** Line', parser.ErrorLineNumber
-    print '** Column', parser.ErrorColumnNumber
-    print '** Byte', parser.ErrorByteIndex
-
-# Try parsing a file
-parser = expat.ParserCreate(namespace_separator='!')
-parser.returns_unicode = 1
 
-for name in HANDLER_NAMES:
-    setattr(parser, name, getattr(out, name))
-import StringIO
-file = StringIO.StringIO(data)
-try:
-    parser.ParseFile(file)
-except expat.error:
-    print '** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode)
-    print '** Line', parser.ErrorLineNumber
-    print '** Column', parser.ErrorColumnNumber
-    print '** Byte', parser.ErrorByteIndex
-
-
-# Tests that make sure we get errors when the namespace_separator value
-# is illegal, and that we don't for good values:
-print
-print "Testing constructor for proper handling of namespace_separator values:"
-expat.ParserCreate()
-expat.ParserCreate(namespace_separator=None)
-expat.ParserCreate(namespace_separator=' ')
-print "Legal values tested o.k."
-try:
-    expat.ParserCreate(namespace_separator=42)
-except TypeError, e:
-    print "Caught expected TypeError:"
-    print e
-else:
-    print "Failed to catch expected TypeError."
-
-try:
-    expat.ParserCreate(namespace_separator='too long')
-except ValueError, e:
-    print "Caught expected ValueError:"
-    print e
-else:
-    print "Failed to catch expected ValueError."
-
-# ParserCreate() needs to accept a namespace_separator of zero length
-# to satisfy the requirements of RDF applications that are required
-# to simply glue together the namespace URI and the localname.  Though
-# considered a wart of the RDF specifications, it needs to be supported.
-#
-# See XML-SIG mailing list thread starting with
-# http://mail.python.org/pipermail/xml-sig/2001-April/005202.html
-#
-expat.ParserCreate(namespace_separator='') # too short
-
-# Test the interning machinery.
-p = expat.ParserCreate()
-L = []
-def collector(name, *args):
-    L.append(name)
-p.StartElementHandler = collector
-p.EndElementHandler = collector
-p.Parse("<e> <e/> <e></e> </e>", 1)
-tag = L[0]
-if len(L) != 6:
-    print "L should only contain 6 entries; found", len(L)
-for entry in L:
-    if tag is not entry:
-        print "expected L to contain many references to the same string",
-        print "(it didn't)"
-        print "L =", repr(L)
-        break
+# Produce UTF-8 output
+class ParseTest(unittest.TestCase):
+    class Outputter:
+        def __init__(self):
+            self.out = []
+            
+        def StartElementHandler(self, name, attrs):
+            self.out.append('Start element: ' + repr(name) + ' ' + 
+                            sortdict(attrs))
+    
+        def EndElementHandler(self, name):
+            self.out.append('End element: ' + repr(name))
+    
+        def CharacterDataHandler(self, data):
+            data = data.strip()
+            if data:
+                self.out.append('Character data: ' + repr(data))
+    
+        def ProcessingInstructionHandler(self, target, data):
+            self.out.append('PI: ' + repr(target) + ' ' + repr(data))
+    
+        def StartNamespaceDeclHandler(self, prefix, uri):
+            self.out.append('NS decl: ' + repr(prefix) + ' ' + repr(uri))
+    
+        def EndNamespaceDeclHandler(self, prefix):
+            self.out.append('End of NS decl: ' + repr(prefix))
+    
+        def StartCdataSectionHandler(self):
+            self.out.append('Start of CDATA section')
+    
+        def EndCdataSectionHandler(self):
+            self.out.append('End of CDATA section')
+    
+        def CommentHandler(self, text):
+            self.out.append('Comment: ' + repr(text))
+    
+        def NotationDeclHandler(self, *args):
+            name, base, sysid, pubid = args
+            self.out.append('Notation declared: %s' %(args,))
+    
+        def UnparsedEntityDeclHandler(self, *args):
+            entityName, base, systemId, publicId, notationName = args
+            self.out.append('Unparsed entity decl: %s' %(args,))
+    
+        def NotStandaloneHandler(self, userData):
+            self.out.append('Not standalone')
+            return 1
+    
+        def ExternalEntityRefHandler(self, *args):
+            context, base, sysId, pubId = args
+            self.out.append('External entity ref: %s' %(args[1:],))
+            return 1
+    
+        def DefaultHandler(self, userData):
+            pass
+    
+        def DefaultHandlerExpand(self, userData):
+            pass
+
+    handler_names = [
+        'StartElementHandler', 'EndElementHandler',
+        'CharacterDataHandler', 'ProcessingInstructionHandler',
+        'UnparsedEntityDeclHandler', 'NotationDeclHandler',
+        'StartNamespaceDeclHandler', 'EndNamespaceDeclHandler',
+        'CommentHandler', 'StartCdataSectionHandler',
+        'EndCdataSectionHandler',
+        'DefaultHandler', 'DefaultHandlerExpand',
+        #'NotStandaloneHandler',
+        'ExternalEntityRefHandler'
+        ]
+    
+    def test_utf8(self):
+
+        out = self.Outputter()
+        parser = expat.ParserCreate(namespace_separator='!')
+        for name in self.handler_names:
+            setattr(parser, name, getattr(out, name))
+        parser.returns_unicode = 0
+        parser.Parse(data, 1)
+            
+        # Verify output
+        op = out.out
+        self.assertEquals(op[0], 'PI: \'xml-stylesheet\' \'href="stylesheet.css"\'')
+        self.assertEquals(op[1], "Comment: ' comment data '")
+        self.assertEquals(op[2], "Notation declared: ('notation', None, 'notation.jpeg', None)")
+        self.assertEquals(op[3], "Unparsed entity decl: ('unparsed_entity', None, 'entity.file', None, 'notation')")
+        self.assertEquals(op[4], "Start element: 'root' {'attr1': 'value1', 'attr2': 'value2\\xe1\\xbd\\x80'}")
+        self.assertEquals(op[5], "NS decl: 'myns' 'http://www.python.org/namespace'")
+        self.assertEquals(op[6], "Start element: 'http://www.python.org/namespace!subelement' {}")
+        self.assertEquals(op[7], "Character data: 'Contents of subelements'")
+        self.assertEquals(op[8], "End element: 'http://www.python.org/namespace!subelement'")
+        self.assertEquals(op[9], "End of NS decl: 'myns'")
+        self.assertEquals(op[10], "Start element: 'sub2' {}")
+        self.assertEquals(op[11], 'Start of CDATA section')
+        self.assertEquals(op[12], "Character data: 'contents of CDATA section'")
+        self.assertEquals(op[13], 'End of CDATA section')
+        self.assertEquals(op[14], "End element: 'sub2'")
+        self.assertEquals(op[15], "External entity ref: (None, 'entity.file', None)")
+        self.assertEquals(op[16], "End element: 'root'")
+
+    def test_unicode(self):
+        # Try the parse again, this time producing Unicode output
+        out = self.Outputter()
+        parser = expat.ParserCreate(namespace_separator='!')
+        parser.returns_unicode = 1
+        for name in self.handler_names:
+            setattr(parser, name, getattr(out, name))
+            
+        parser.Parse(data, 1)
+
+        op = out.out
+        self.assertEquals(op[0], 'PI: u\'xml-stylesheet\' u\'href="stylesheet.css"\'')
+        self.assertEquals(op[1], "Comment: u' comment data '")
+        self.assertEquals(op[2], "Notation declared: (u'notation', None, u'notation.jpeg', None)")
+        self.assertEquals(op[3], "Unparsed entity decl: (u'unparsed_entity', None, u'entity.file', None, u'notation')")
+        self.assertEquals(op[4], "Start element: u'root' {u'attr1': u'value1', u'attr2': u'value2\\u1f40'}")
+        self.assertEquals(op[5], "NS decl: u'myns' u'http://www.python.org/namespace'")
+        self.assertEquals(op[6], "Start element: u'http://www.python.org/namespace!subelement' {}")
+        self.assertEquals(op[7], "Character data: u'Contents of subelements'")
+        self.assertEquals(op[8], "End element: u'http://www.python.org/namespace!subelement'")
+        self.assertEquals(op[9], "End of NS decl: u'myns'")
+        self.assertEquals(op[10], "Start element: u'sub2' {}")
+        self.assertEquals(op[11], 'Start of CDATA section')
+        self.assertEquals(op[12], "Character data: u'contents of CDATA section'")
+        self.assertEquals(op[13], 'End of CDATA section')
+        self.assertEquals(op[14], "End element: u'sub2'")
+        self.assertEquals(op[15], "External entity ref: (None, u'entity.file', None)")
+        self.assertEquals(op[16], "End element: u'root'")
+
+    def test_parse_file(self):
+        # Try parsing a file
+        out = self.Outputter()
+        parser = expat.ParserCreate(namespace_separator='!')
+        parser.returns_unicode = 1
+        for name in self.handler_names:
+            setattr(parser, name, getattr(out, name))
+        file = StringIO.StringIO(data)
+        
+        parser.ParseFile(file)
+
+        op = out.out
+        self.assertEquals(op[0], 'PI: u\'xml-stylesheet\' u\'href="stylesheet.css"\'')
+        self.assertEquals(op[1], "Comment: u' comment data '")
+        self.assertEquals(op[2], "Notation declared: (u'notation', None, u'notation.jpeg', None)")
+        self.assertEquals(op[3], "Unparsed entity decl: (u'unparsed_entity', None, u'entity.file', None, u'notation')")
+        self.assertEquals(op[4], "Start element: u'root' {u'attr1': u'value1', u'attr2': u'value2\\u1f40'}")
+        self.assertEquals(op[5], "NS decl: u'myns' u'http://www.python.org/namespace'")
+        self.assertEquals(op[6], "Start element: u'http://www.python.org/namespace!subelement' {}")
+        self.assertEquals(op[7], "Character data: u'Contents of subelements'")
+        self.assertEquals(op[8], "End element: u'http://www.python.org/namespace!subelement'")
+        self.assertEquals(op[9], "End of NS decl: u'myns'")
+        self.assertEquals(op[10], "Start element: u'sub2' {}")
+        self.assertEquals(op[11], 'Start of CDATA section')
+        self.assertEquals(op[12], "Character data: u'contents of CDATA section'")
+        self.assertEquals(op[13], 'End of CDATA section')
+        self.assertEquals(op[14], "End element: u'sub2'")
+        self.assertEquals(op[15], "External entity ref: (None, u'entity.file', None)")
+        self.assertEquals(op[16], "End element: u'root'")
+
+
+class NamespaceSeparatorTest(unittest.TestCase):
+    def test_legal(self):
+        # Tests that make sure we get errors when the namespace_separator value
+        # is illegal, and that we don't for good values:
+        expat.ParserCreate()
+        expat.ParserCreate(namespace_separator=None)
+        expat.ParserCreate(namespace_separator=' ')
+        
+    def test_illegal(self):
+        try:
+            expat.ParserCreate(namespace_separator=42)
+            self.fail()
+        except TypeError, e:
+            self.assertEquals(str(e), 
+                'ParserCreate() argument 2 must be string or None, not int')
+        
+        try:
+            expat.ParserCreate(namespace_separator='too long')
+            self.fail()
+        except ValueError, e:
+            self.assertEquals(str(e),
+                'namespace_separator must be at most one character, omitted, or None')
+
+    def test_zero_length(self):
+        # ParserCreate() needs to accept a namespace_separator of zero length
+        # to satisfy the requirements of RDF applications that are required
+        # to simply glue together the namespace URI and the localname.  Though
+        # considered a wart of the RDF specifications, it needs to be supported.
+        #
+        # See XML-SIG mailing list thread starting with
+        # http://mail.python.org/pipermail/xml-sig/2001-April/005202.html
+        #
+        expat.ParserCreate(namespace_separator='') # too short
+
+
+class InterningTest(unittest.TestCase):
+    def test(self):
+        # Test the interning machinery.
+        p = expat.ParserCreate()
+        L = []
+        def collector(name, *args):
+            L.append(name)
+        p.StartElementHandler = collector
+        p.EndElementHandler = collector
+        p.Parse("<e> <e/> <e></e> </e>", 1)
+        tag = L[0]
+        self.assertEquals(len(L), 6)
+        for entry in L:
+            # L should have the same string repeated over and over.
+            self.assertTrue(tag is entry)
 
-# Tests of the buffer_text attribute.
-import sys
 
-class TextCollector:
-    def __init__(self, parser):
+class BufferTextTest(unittest.TestCase):
+    def setUp(self):
         self.stuff = []
-
+        self.parser = expat.ParserCreate()
+        self.parser.buffer_text = 1
+        self.parser.CharacterDataHandler = self.CharacterDataHandler
+        
     def check(self, expected, label):
-        require(self.stuff == expected,
+        self.assertEquals(self.stuff, expected,
                 "%s\nstuff    = %r\nexpected = %r"
                 % (label, self.stuff, map(unicode, expected)))
 
@@ -238,9 +290,9 @@
         self.stuff.append("<%s>" % name)
         bt = attrs.get("buffer-text")
         if bt == "yes":
-            parser.buffer_text = 1
+            self.parser.buffer_text = 1
         elif bt == "no":
-            parser.buffer_text = 0
+            self.parser.buffer_text = 0
 
     def EndElementHandler(self, name):
         self.stuff.append("</%s>" % name)
@@ -248,95 +300,91 @@
     def CommentHandler(self, data):
         self.stuff.append("<!--%s-->" % data)
 
-def require(cond, label):
-    # similar to confirm(), but no extraneous output
-    if not cond:
-        raise TestFailed(label)
-
-def setup(handlers=[]):
-    parser = expat.ParserCreate()
-    require(not parser.buffer_text,
-            "buffer_text not disabled by default")
-    parser.buffer_text = 1
-    handler = TextCollector(parser)
-    parser.CharacterDataHandler = handler.CharacterDataHandler
-    for name in handlers:
-        setattr(parser, name, getattr(handler, name))
-    return parser, handler
-
-parser, handler = setup()
-require(parser.buffer_text,
-        "text buffering either not acknowledged or not enabled")
-parser.Parse("<a>1<b/>2<c/>3</a>", 1)
-handler.check(["123"],
-              "buffered text not properly collapsed")
-
-# XXX This test exposes more detail of Expat's text chunking than we
-# XXX like, but it tests what we need to concisely.
-parser, handler = setup(["StartElementHandler"])
-parser.Parse("<a>1<b buffer-text='no'/>2\n3<c buffer-text='yes'/>4\n5</a>", 1)
-handler.check(["<a>", "1", "<b>", "2", "\n", "3", "<c>", "4\n5"],
-              "buffering control not reacting as expected")
-
-parser, handler = setup()
-parser.Parse("<a>1<b/>&lt;2&gt;<c/>&#32;\n&#x20;3</a>", 1)
-handler.check(["1<2> \n 3"],
-              "buffered text not properly collapsed")
-
-parser, handler = setup(["StartElementHandler"])
-parser.Parse("<a>1<b/>2<c/>3</a>", 1)
-handler.check(["<a>", "1", "<b>", "2", "<c>", "3"],
-              "buffered text not properly split")
-
-parser, handler = setup(["StartElementHandler", "EndElementHandler"])
-parser.CharacterDataHandler = None
-parser.Parse("<a>1<b/>2<c/>3</a>", 1)
-handler.check(["<a>", "<b>", "</b>", "<c>", "</c>", "</a>"],
-              "huh?")
-
-parser, handler = setup(["StartElementHandler", "EndElementHandler"])
-parser.Parse("<a>1<b></b>2<c/>3</a>", 1)
-handler.check(["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "3", "</a>"],
-              "huh?")
-
-parser, handler = setup(["CommentHandler", "EndElementHandler",
-                         "StartElementHandler"])
-parser.Parse("<a>1<b/>2<c></c>345</a> ", 1)
-handler.check(["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "345", "</a>"],
-              "buffered text not properly split")
-
-parser, handler = setup(["CommentHandler", "EndElementHandler",
-                         "StartElementHandler"])
-parser.Parse("<a>1<b/>2<c></c>3<!--abc-->4<!--def-->5</a> ", 1)
-handler.check(["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "3",
-               "<!--abc-->", "4", "<!--def-->", "5", "</a>"],
-              "buffered text not properly split")
+    def setHandlers(self, handlers=[]):
+        for name in handlers:
+            setattr(self.parser, name, getattr(self, name))
+
+    def test_default_to_disabled(self):
+        parser = expat.ParserCreate()
+        self.assertFalse(parser.buffer_text)
+        
+    def test_buffering_enabled(self):
+        # Make sure buffering is turned on
+        self.assertTrue(self.parser.buffer_text)
+        self.parser.Parse("<a>1<b/>2<c/>3</a>", 1)
+        self.assertEquals(self.stuff, ['123'], 
+                          "buffered text not properly collapsed")
+
+    def test1(self):
+        # XXX This test exposes more detail of Expat's text chunking than we
+        # XXX like, but it tests what we need to concisely.
+        self.setHandlers(["StartElementHandler"])
+        self.parser.Parse("<a>1<b buffer-text='no'/>2\n3<c buffer-text='yes'/>4\n5</a>", 1)
+        self.assertEquals(self.stuff, 
+                          ["<a>", "1", "<b>", "2", "\n", "3", "<c>", "4\n5"],
+                          "buffering control not reacting as expected")
+    
+    def test2(self):
+        self.parser.Parse("<a>1<b/>&lt;2&gt;<c/>&#32;\n&#x20;3</a>", 1)
+        self.assertEquals(self.stuff, ["1<2> \n 3"],
+                          "buffered text not properly collapsed")
+
+    def test3(self):
+        self.setHandlers(["StartElementHandler"])
+        self.parser.Parse("<a>1<b/>2<c/>3</a>", 1)
+        self.assertEquals(self.stuff, ["<a>", "1", "<b>", "2", "<c>", "3"],
+                          "buffered text not properly split")
+
+    def test4(self):
+        self.setHandlers(["StartElementHandler", "EndElementHandler"])
+        self.parser.CharacterDataHandler = None
+        self.parser.Parse("<a>1<b/>2<c/>3</a>", 1)
+        self.assertEquals(self.stuff, 
+                          ["<a>", "<b>", "</b>", "<c>", "</c>", "</a>"])
+
+    def test5(self):
+        self.setHandlers(["StartElementHandler", "EndElementHandler"])
+        self.parser.Parse("<a>1<b></b>2<c/>3</a>", 1)
+        self.assertEquals(self.stuff,
+            ["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "3", "</a>"])
+
+    def test6(self):
+        self.setHandlers(["CommentHandler", "EndElementHandler", 
+                    "StartElementHandler"])
+        self.parser.Parse("<a>1<b/>2<c></c>345</a> ", 1)
+        self.assertEquals(self.stuff, 
+            ["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "345", "</a>"], 
+            "buffered text not properly split")
+
+    def test7(self):
+        self.setHandlers(["CommentHandler", "EndElementHandler",
+                    "StartElementHandler"])
+        self.parser.Parse("<a>1<b/>2<c></c>3<!--abc-->4<!--def-->5</a> ", 1)
+        self.assertEquals(self.stuff,
+                          ["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "3",
+                           "<!--abc-->", "4", "<!--def-->", "5", "</a>"],
+                          "buffered text not properly split")
+
 
 # Test handling of exception from callback:
-def StartElementHandler(name, attrs):
-    raise RuntimeError(name)
+class HandlerExceptionTest(unittest.TestCase):
+    def StartElementHandler(self, name, attrs):
+        raise RuntimeError(name)
 
-parser = expat.ParserCreate()
-parser.StartElementHandler = StartElementHandler
+    def test(self):
+        parser = expat.ParserCreate()
+        parser.StartElementHandler = self.StartElementHandler
+        try:
+            parser.Parse("<a><b><c/></b></a>", 1)
+            self.fail()
+        except RuntimeError, e:
+            self.assertEquals(e.args[0], 'a',
+                              "Expected RuntimeError for element 'a', but" + \
+                              " found %r" % e.args[0])
 
-try:
-    parser.Parse("<a><b><c/></b></a>", 1)
-except RuntimeError, e:
-    if e.args[0] != "a":
-        print "Expected RuntimeError for element 'a'; found %r" % e.args[0]
-else:
-    print "Expected RuntimeError for 'a'"
 
 # Test Current* members:
-class PositionTest:
-
-    def __init__(self, expected_list, parser):
-        self.parser = parser
-        self.parser.StartElementHandler = self.StartElementHandler
-        self.parser.EndElementHandler = self.EndElementHandler
-        self.expected_list = expected_list
-        self.upto = 0
-
+class PositionTest(unittest.TestCase):
     def StartElementHandler(self, name, attrs):
         self.check_pos('s')
 
@@ -348,41 +396,54 @@
                self.parser.CurrentByteIndex,
                self.parser.CurrentLineNumber,
                self.parser.CurrentColumnNumber)
-        require(self.upto < len(self.expected_list),
-                'too many parser events')
+        self.assertTrue(self.upto < len(self.expected_list),
+                        'too many parser events')
         expected = self.expected_list[self.upto]
-        require(pos == expected,
-                'expected position %s, got %s' % (expected, pos))
+        self.assertEquals(pos, expected, 
+                'Expected position %s, got position %s' %(pos, expected))
         self.upto += 1
 
+    def test(self):
+        self.parser = expat.ParserCreate()
+        self.parser.StartElementHandler = self.StartElementHandler
+        self.parser.EndElementHandler = self.EndElementHandler
+        self.upto = 0
+        self.expected_list = [('s', 0, 1, 0), ('s', 5, 2, 1), ('s', 11, 3, 2),
+                              ('e', 15, 3, 6), ('e', 17, 4, 1), ('e', 22, 5, 0)]
+
+        xml = '<a>\n <b>\n  <c/>\n </b>\n</a>'
+        self.parser.Parse(xml, 1)
+
 
-parser = expat.ParserCreate()
-handler = PositionTest([('s', 0, 1, 0), ('s', 5, 2, 1), ('s', 11, 3, 2),
-                        ('e', 15, 3, 6), ('e', 17, 4, 1), ('e', 22, 5, 0)],
-                       parser)
-parser.Parse('''<a>
- <b>
-  <c/>
- </b>
-</a>''', 1)
-
-
-def test_parse_only_xml_data():
-    # http://python.org/sf/1296433
-    #
-    xml = "<?xml version='1.0' encoding='iso8859'?><s>%s</s>" % ('a' * 1025)
-    # this one doesn't crash
-    #xml = "<?xml version='1.0'?><s>%s</s>" % ('a' * 10000)
-
-    def handler(text):
-        raise Exception
-
-    parser = expat.ParserCreate()
-    parser.CharacterDataHandler = handler
-
-    try:
-        parser.Parse(xml)
-    except:
-        pass
+class sf1296433Test(unittest.TestCase):
+    def test_parse_only_xml_data(self):
+        # http://python.org/sf/1296433
+        #
+        xml = "<?xml version='1.0' encoding='iso8859'?><s>%s</s>" % ('a' * 1025)
+        # this one doesn't crash
+        #xml = "<?xml version='1.0'?><s>%s</s>" % ('a' * 10000)
+    
+        class SpecificException(Exception):
+            pass
+        
+        def handler(text):
+            raise SpecificException
+    
+        parser = expat.ParserCreate()
+        parser.CharacterDataHandler = handler
+    
+        self.assertRaises(Exception, parser.Parse, xml)
+
+
+def test_main():
+    run_unittest(SetAttributeTest,
+                 ParseTest,
+                 NamespaceSeparatorTest,
+                 InterningTest,
+                 BufferTextTest,
+                 HandlerExceptionTest,
+                 PositionTest,
+                 sf1296433Test)
 
-test_parse_only_xml_data()
+if __name__ == "__main__":
+    test_main()

Modified: python/trunk/Lib/test/test_sax.py
==============================================================================
--- python/trunk/Lib/test/test_sax.py	(original)
+++ python/trunk/Lib/test/test_sax.py	Thu Mar 29 01:34:06 2007
@@ -13,26 +13,66 @@
 from xml.sax.expatreader import create_parser
 from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl
 from cStringIO import StringIO
-from test.test_support import verify, verbose, TestFailed, findfile
+from test.test_support import findfile, run_unittest
+import unittest
 import os
 
-# ===== Utilities
-
-tests = 0
-failures = []
-
-def confirm(outcome, name):
-    global tests
-
-    tests = tests + 1
-    if outcome:
-        if verbose:
-            print "Passed", name
-    else:
-        failures.append(name)
+ns_uri = "http://www.python.org/xml-ns/saxtest/"
 
-def test_make_parser2():
-    try:
+class XmlTestBase(unittest.TestCase):
+    def verify_empty_attrs(self, attrs):
+        self.assertRaises(KeyError, attrs.getValue, "attr")
+        self.assertRaises(KeyError, attrs.getValueByQName, "attr")
+        self.assertRaises(KeyError, attrs.getNameByQName, "attr")
+        self.assertRaises(KeyError, attrs.getQNameByName, "attr")
+        self.assertRaises(KeyError, attrs.__getitem__, "attr")
+        self.assertEquals(attrs.getLength(), 0)
+        self.assertEquals(attrs.getNames(), [])
+        self.assertEquals(attrs.getQNames(), [])
+        self.assertEquals(len(attrs), 0)
+        self.assertFalse(attrs.has_key("attr"))
+        self.assertEquals(attrs.keys(), [])
+        self.assertEquals(attrs.get("attrs"), None)
+        self.assertEquals(attrs.get("attrs", 25), 25)
+        self.assertEquals(attrs.items(), [])
+        self.assertEquals(attrs.values(), [])
+    
+    def verify_empty_nsattrs(self, attrs):
+        self.assertRaises(KeyError, attrs.getValue, (ns_uri, "attr"))
+        self.assertRaises(KeyError, attrs.getValueByQName, "ns:attr")
+        self.assertRaises(KeyError, attrs.getNameByQName, "ns:attr")
+        self.assertRaises(KeyError, attrs.getQNameByName, (ns_uri, "attr"))
+        self.assertRaises(KeyError, attrs.__getitem__, (ns_uri, "attr"))
+        self.assertEquals(attrs.getLength(), 0)
+        self.assertEquals(attrs.getNames(), [])
+        self.assertEquals(attrs.getQNames(), [])
+        self.assertEquals(len(attrs), 0)
+        self.assertFalse(attrs.has_key((ns_uri, "attr")))
+        self.assertEquals(attrs.keys(), [])
+        self.assertEquals(attrs.get((ns_uri, "attr")), None)
+        self.assertEquals(attrs.get((ns_uri, "attr"), 25), 25)
+        self.assertEquals(attrs.items(), [])
+        self.assertEquals(attrs.values(), [])
+
+    def verify_attrs_wattr(self, attrs):
+        self.assertEquals(attrs.getLength(), 1)
+        self.assertEquals(attrs.getNames(), ["attr"])
+        self.assertEquals(attrs.getQNames(), ["attr"])
+        self.assertEquals(len(attrs), 1)
+        self.assertTrue(attrs.has_key("attr"))
+        self.assertEquals(attrs.keys(), ["attr"])
+        self.assertEquals(attrs.get("attr"), "val")
+        self.assertEquals(attrs.get("attr", 25), "val")
+        self.assertEquals(attrs.items(), [("attr", "val")])
+        self.assertEquals(attrs.values(), ["val"])
+        self.assertEquals(attrs.getValue("attr"), "val")
+        self.assertEquals(attrs.getValueByQName("attr"), "val")
+        self.assertEquals(attrs.getNameByQName("attr"), "attr")
+        self.assertEquals(attrs["attr"], "val")
+        self.assertEquals(attrs.getQNameByName("attr"), "attr")
+    
+class MakeParserTest(unittest.TestCase):
+    def test_make_parser2(self):
         # Creating parsers several times in a row should succeed.
         # Testing this because there have been failures of this kind
         # before.
@@ -48,10 +88,6 @@
         p = make_parser()
         from xml.sax import make_parser
         p = make_parser()
-    except:
-        return 0
-    else:
-        return p
 
 
 # ===========================================================================
@@ -60,215 +96,214 @@
 #
 # ===========================================================================
 
-# ===== escape
-
-def test_escape_basic():
-    return escape("Donald Duck & Co") == "Donald Duck &amp; Co"
-
-def test_escape_all():
-    return escape("<Donald Duck & Co>") == "&lt;Donald Duck &amp; Co&gt;"
-
-def test_escape_extra():
-    return escape("Hei på deg", {"å" : "&aring;"}) == "Hei p&aring; deg"
-
-# ===== unescape
-
-def test_unescape_basic():
-    return unescape("Donald Duck &amp; Co") == "Donald Duck & Co"
-
-def test_unescape_all():
-    return unescape("&lt;Donald Duck &amp; Co&gt;") == "<Donald Duck & Co>"
-
-def test_unescape_extra():
-    return unescape("Hei på deg", {"å" : "&aring;"}) == "Hei p&aring; deg"
-
-def test_unescape_amp_extra():
-    return unescape("&amp;foo;", {"&foo;": "splat"}) == "&foo;"
-
-# ===== quoteattr
-
-def test_quoteattr_basic():
-    return quoteattr("Donald Duck & Co") == '"Donald Duck &amp; Co"'
-
-def test_single_quoteattr():
-    return (quoteattr('Includes "double" quotes')
-            == '\'Includes "double" quotes\'')
-
-def test_double_quoteattr():
-    return (quoteattr("Includes 'single' quotes")
-            == "\"Includes 'single' quotes\"")
-
-def test_single_double_quoteattr():
-    return (quoteattr("Includes 'single' and \"double\" quotes")
-            == "\"Includes 'single' and &quot;double&quot; quotes\"")
-
-# ===== make_parser
-
-def test_make_parser():
-    try:
+class SaxutilsTest(unittest.TestCase):
+    # ===== escape
+    def test_escape_basic(self):
+        self.assertEquals(escape("Donald Duck & Co"), "Donald Duck &amp; Co")
+    
+    def test_escape_all(self):
+        self.assertEquals(escape("<Donald Duck & Co>"),
+                          "&lt;Donald Duck &amp; Co&gt;")
+    
+    def test_escape_extra(self):
+        self.assertEquals(escape("Hei på deg", {"å" : "&aring;"}),
+                          "Hei p&aring; deg")
+
+    # ===== unescape
+    def test_unescape_basic(self):
+        self.assertEquals(unescape("Donald Duck &amp; Co"), "Donald Duck & Co")
+    
+    def test_unescape_all(self):
+        self.assertEquals(unescape("&lt;Donald Duck &amp; Co&gt;"), 
+                          "<Donald Duck & Co>")
+    
+    def test_unescape_extra(self):
+        self.assertEquals(unescape("Hei på deg", {"å" : "&aring;"}), 
+                          "Hei p&aring; deg")
+    
+    def test_unescape_amp_extra(self):
+        self.assertEquals(unescape("&amp;foo;", {"&foo;": "splat"}), "&foo;")
+
+    # ===== quoteattr
+    def test_quoteattr_basic(self):
+        self.assertEquals(quoteattr("Donald Duck & Co"), 
+                          '"Donald Duck &amp; Co"')
+    
+    def test_single_quoteattr(self):
+        self.assertEquals(quoteattr('Includes "double" quotes'),
+                          '\'Includes "double" quotes\'')
+    
+    def test_double_quoteattr(self):
+        self.assertEquals(quoteattr("Includes 'single' quotes"),
+                          "\"Includes 'single' quotes\"")
+    
+    def test_single_double_quoteattr(self):
+        self.assertEquals(quoteattr("Includes 'single' and \"double\" quotes"),
+                    "\"Includes 'single' and &quot;double&quot; quotes\"")
+    
+    # ===== make_parser
+    def test_make_parser(self):
         # Creating a parser should succeed - it should fall back
         # to the expatreader
         p = make_parser(['xml.parsers.no_such_parser'])
-    except:
-        return 0
-    else:
-        return p
 
 
 # ===== XMLGenerator
 
 start = '<?xml version="1.0" encoding="iso-8859-1"?>\n'
 
-def test_xmlgen_basic():
-    result = StringIO()
-    gen = XMLGenerator(result)
-    gen.startDocument()
-    gen.startElement("doc", {})
-    gen.endElement("doc")
-    gen.endDocument()
-
-    return result.getvalue() == start + "<doc></doc>"
-
-def test_xmlgen_content():
-    result = StringIO()
-    gen = XMLGenerator(result)
-
-    gen.startDocument()
-    gen.startElement("doc", {})
-    gen.characters("huhei")
-    gen.endElement("doc")
-    gen.endDocument()
-
-    return result.getvalue() == start + "<doc>huhei</doc>"
-
-def test_xmlgen_pi():
-    result = StringIO()
-    gen = XMLGenerator(result)
-
-    gen.startDocument()
-    gen.processingInstruction("test", "data")
-    gen.startElement("doc", {})
-    gen.endElement("doc")
-    gen.endDocument()
-
-    return result.getvalue() == start + "<?test data?><doc></doc>"
-
-def test_xmlgen_content_escape():
-    result = StringIO()
-    gen = XMLGenerator(result)
-
-    gen.startDocument()
-    gen.startElement("doc", {})
-    gen.characters("<huhei&")
-    gen.endElement("doc")
-    gen.endDocument()
-
-    return result.getvalue() == start + "<doc>&lt;huhei&amp;</doc>"
-
-def test_xmlgen_attr_escape():
-    result = StringIO()
-    gen = XMLGenerator(result)
-
-    gen.startDocument()
-    gen.startElement("doc", {"a": '"'})
-    gen.startElement("e", {"a": "'"})
-    gen.endElement("e")
-    gen.startElement("e", {"a": "'\""})
-    gen.endElement("e")
-    gen.startElement("e", {"a": "\n\r\t"})
-    gen.endElement("e")
-    gen.endElement("doc")
-    gen.endDocument()
-
-    return result.getvalue() == start + ("<doc a='\"'><e a=\"'\"></e>"
-                                         "<e a=\"'&quot;\"></e>"
-                                         "<e a=\"&#10;&#13;&#9;\"></e></doc>")
-
-def test_xmlgen_ignorable():
-    result = StringIO()
-    gen = XMLGenerator(result)
-
-    gen.startDocument()
-    gen.startElement("doc", {})
-    gen.ignorableWhitespace(" ")
-    gen.endElement("doc")
-    gen.endDocument()
+class XmlgenTest(unittest.TestCase):
+    def test_xmlgen_basic(self):
+        result = StringIO()
+        gen = XMLGenerator(result)
+        gen.startDocument()
+        gen.startElement("doc", {})
+        gen.endElement("doc")
+        gen.endDocument()
+    
+        self.assertEquals(result.getvalue(), start + "<doc></doc>")
+    
+    def test_xmlgen_content(self):
+        result = StringIO()
+        gen = XMLGenerator(result)
+    
+        gen.startDocument()
+        gen.startElement("doc", {})
+        gen.characters("huhei")
+        gen.endElement("doc")
+        gen.endDocument()
+    
+        self.assertEquals(result.getvalue(), start + "<doc>huhei</doc>")
+
+    def test_xmlgen_pi(self):
+        result = StringIO()
+        gen = XMLGenerator(result)
+
+        gen.startDocument()
+        gen.processingInstruction("test", "data")
+        gen.startElement("doc", {})
+        gen.endElement("doc")
+        gen.endDocument()
+
+        self.assertEquals(result.getvalue(), start + "<?test data?><doc></doc>")
+
+    def test_xmlgen_content_escape(self):
+        result = StringIO()
+        gen = XMLGenerator(result)
+
+        gen.startDocument()
+        gen.startElement("doc", {})
+        gen.characters("<huhei&")
+        gen.endElement("doc")
+        gen.endDocument()
+
+        self.assertEquals(result.getvalue(), 
+            start + "<doc>&lt;huhei&amp;</doc>")
+
+    def test_xmlgen_attr_escape(self):
+        result = StringIO()
+        gen = XMLGenerator(result)
+
+        gen.startDocument()
+        gen.startElement("doc", {"a": '"'})
+        gen.startElement("e", {"a": "'"})
+        gen.endElement("e")
+        gen.startElement("e", {"a": "'\""})
+        gen.endElement("e")
+        gen.startElement("e", {"a": "\n\r\t"})
+        gen.endElement("e")
+        gen.endElement("doc")
+        gen.endDocument()
+
+        self.assertEquals(result.getvalue(), start + 
+            ("<doc a='\"'><e a=\"'\"></e>"
+             "<e a=\"'&quot;\"></e>"
+             "<e a=\"&#10;&#13;&#9;\"></e></doc>"))
+
+    def test_xmlgen_ignorable(self):
+        result = StringIO()
+        gen = XMLGenerator(result)
+
+        gen.startDocument()
+        gen.startElement("doc", {})
+        gen.ignorableWhitespace(" ")
+        gen.endElement("doc")
+        gen.endDocument()
+
+        self.assertEquals(result.getvalue(), start + "<doc> </doc>")
+
+    def test_xmlgen_ns(self):
+        result = StringIO()
+        gen = XMLGenerator(result)
+
+        gen.startDocument()
+        gen.startPrefixMapping("ns1", ns_uri)
+        gen.startElementNS((ns_uri, "doc"), "ns1:doc", {})
+        # add an unqualified name
+        gen.startElementNS((None, "udoc"), None, {})
+        gen.endElementNS((None, "udoc"), None)
+        gen.endElementNS((ns_uri, "doc"), "ns1:doc")
+        gen.endPrefixMapping("ns1")
+        gen.endDocument()
 
-    return result.getvalue() == start + "<doc> </doc>"
-
-ns_uri = "http://www.python.org/xml-ns/saxtest/"
-
-def test_xmlgen_ns():
-    result = StringIO()
-    gen = XMLGenerator(result)
-
-    gen.startDocument()
-    gen.startPrefixMapping("ns1", ns_uri)
-    gen.startElementNS((ns_uri, "doc"), "ns1:doc", {})
-    # add an unqualified name
-    gen.startElementNS((None, "udoc"), None, {})
-    gen.endElementNS((None, "udoc"), None)
-    gen.endElementNS((ns_uri, "doc"), "ns1:doc")
-    gen.endPrefixMapping("ns1")
-    gen.endDocument()
-
-    return result.getvalue() == start + \
+        self.assertEquals(result.getvalue(), start + \
            ('<ns1:doc xmlns:ns1="%s"><udoc></udoc></ns1:doc>' %
-                                         ns_uri)
+                                         ns_uri))
 
-def test_1463026_1():
-    result = StringIO()
-    gen = XMLGenerator(result)
-
-    gen.startDocument()
-    gen.startElementNS((None, 'a'), 'a', {(None, 'b'):'c'})
-    gen.endElementNS((None, 'a'), 'a')
-    gen.endDocument()
-
-    return result.getvalue() == start+'<a b="c"></a>'
-
-def test_1463026_2():
-    result = StringIO()
-    gen = XMLGenerator(result)
-
-    gen.startDocument()
-    gen.startPrefixMapping(None, 'qux')
-    gen.startElementNS(('qux', 'a'), 'a', {})
-    gen.endElementNS(('qux', 'a'), 'a')
-    gen.endPrefixMapping(None)
-    gen.endDocument()
-
-    return result.getvalue() == start+'<a xmlns="qux"></a>'
-
-def test_1463026_3():
-    result = StringIO()
-    gen = XMLGenerator(result)
-
-    gen.startDocument()
-    gen.startPrefixMapping('my', 'qux')
-    gen.startElementNS(('qux', 'a'), 'a', {(None, 'b'):'c'})
-    gen.endElementNS(('qux', 'a'), 'a')
-    gen.endPrefixMapping('my')
-    gen.endDocument()
-
-    return result.getvalue() == start+'<my:a xmlns:my="qux" b="c"></my:a>'
-
-# ===== Xmlfilterbase
-
-def test_filter_basic():
-    result = StringIO()
-    gen = XMLGenerator(result)
-    filter = XMLFilterBase()
-    filter.setContentHandler(gen)
-
-    filter.startDocument()
-    filter.startElement("doc", {})
-    filter.characters("content")
-    filter.ignorableWhitespace(" ")
-    filter.endElement("doc")
-    filter.endDocument()
+    def test_1463026_1(self):
+        result = StringIO()
+        gen = XMLGenerator(result)
+
+        gen.startDocument()
+        gen.startElementNS((None, 'a'), 'a', {(None, 'b'):'c'})
+        gen.endElementNS((None, 'a'), 'a')
+        gen.endDocument()
+
+        self.assertEquals(result.getvalue(), start+'<a b="c"></a>')
+
+    def test_1463026_2(self):
+        result = StringIO()
+        gen = XMLGenerator(result)
+
+        gen.startDocument()
+        gen.startPrefixMapping(None, 'qux')
+        gen.startElementNS(('qux', 'a'), 'a', {})
+        gen.endElementNS(('qux', 'a'), 'a')
+        gen.endPrefixMapping(None)
+        gen.endDocument()
+
+        self.assertEquals(result.getvalue(), start+'<a xmlns="qux"></a>')
+
+    def test_1463026_3(self):
+        result = StringIO()
+        gen = XMLGenerator(result)
+
+        gen.startDocument()
+        gen.startPrefixMapping('my', 'qux')
+        gen.startElementNS(('qux', 'a'), 'a', {(None, 'b'):'c'})
+        gen.endElementNS(('qux', 'a'), 'a')
+        gen.endPrefixMapping('my')
+        gen.endDocument()
+
+        self.assertEquals(result.getvalue(), 
+            start+'<my:a xmlns:my="qux" b="c"></my:a>')
+
+
+class XMLFilterBaseTest(unittest.TestCase):
+    def test_filter_basic(self):
+        result = StringIO()
+        gen = XMLGenerator(result)
+        filter = XMLFilterBase()
+        filter.setContentHandler(gen)
+
+        filter.startDocument()
+        filter.startElement("doc", {})
+        filter.characters("content")
+        filter.ignorableWhitespace(" ")
+        filter.endElement("doc")
+        filter.endDocument()
 
-    return result.getvalue() == start + "<doc>content </doc>"
+        self.assertEquals(result.getvalue(), start + "<doc>content </doc>")
 
 # ===========================================================================
 #
@@ -276,294 +311,294 @@
 #
 # ===========================================================================
 
-# ===== XMLReader support
-
-def test_expat_file():
-    parser = create_parser()
-    result = StringIO()
-    xmlgen = XMLGenerator(result)
-
-    parser.setContentHandler(xmlgen)
-    parser.parse(open(findfile("test"+os.extsep+"xml")))
-
-    return result.getvalue() == xml_test_out
-
-# ===== DTDHandler support
-
-class TestDTDHandler:
-
-    def __init__(self):
-        self._notations = []
-        self._entities  = []
-
-    def notationDecl(self, name, publicId, systemId):
-        self._notations.append((name, publicId, systemId))
-
-    def unparsedEntityDecl(self, name, publicId, systemId, ndata):
-        self._entities.append((name, publicId, systemId, ndata))
-
-def test_expat_dtdhandler():
-    parser = create_parser()
-    handler = TestDTDHandler()
-    parser.setDTDHandler(handler)
-
-    parser.feed('<!DOCTYPE doc [\n')
-    parser.feed('  <!ENTITY img SYSTEM "expat.gif" NDATA GIF>\n')
-    parser.feed('  <!NOTATION GIF PUBLIC "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN">\n')
-    parser.feed(']>\n')
-    parser.feed('<doc></doc>')
-    parser.close()
-
-    return handler._notations == [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)] and \
-           handler._entities == [("img", None, "expat.gif", "GIF")]
-
-# ===== EntityResolver support
-
-class TestEntityResolver:
-
-    def resolveEntity(self, publicId, systemId):
-        inpsrc = InputSource()
-        inpsrc.setByteStream(StringIO("<entity/>"))
-        return inpsrc
-
-def test_expat_entityresolver():
-    parser = create_parser()
-    parser.setEntityResolver(TestEntityResolver())
-    result = StringIO()
-    parser.setContentHandler(XMLGenerator(result))
-
-    parser.feed('<!DOCTYPE doc [\n')
-    parser.feed('  <!ENTITY test SYSTEM "whatever">\n')
-    parser.feed(']>\n')
-    parser.feed('<doc>&test;</doc>')
-    parser.close()
-
-    return result.getvalue() == start + "<doc><entity></entity></doc>"
-
-# ===== Attributes support
-
-class AttrGatherer(ContentHandler):
-
-    def startElement(self, name, attrs):
-        self._attrs = attrs
-
-    def startElementNS(self, name, qname, attrs):
-        self._attrs = attrs
-
-def test_expat_attrs_empty():
-    parser = create_parser()
-    gather = AttrGatherer()
-    parser.setContentHandler(gather)
-
-    parser.feed("<doc/>")
-    parser.close()
-
-    return verify_empty_attrs(gather._attrs)
-
-def test_expat_attrs_wattr():
-    parser = create_parser()
-    gather = AttrGatherer()
-    parser.setContentHandler(gather)
-
-    parser.feed("<doc attr='val'/>")
-    parser.close()
-
-    return verify_attrs_wattr(gather._attrs)
-
-def test_expat_nsattrs_empty():
-    parser = create_parser(1)
-    gather = AttrGatherer()
-    parser.setContentHandler(gather)
-
-    parser.feed("<doc/>")
-    parser.close()
-
-    return verify_empty_nsattrs(gather._attrs)
-
-def test_expat_nsattrs_wattr():
-    parser = create_parser(1)
-    gather = AttrGatherer()
-    parser.setContentHandler(gather)
-
-    parser.feed("<doc xmlns:ns='%s' ns:attr='val'/>" % ns_uri)
-    parser.close()
-
-    attrs = gather._attrs
-
-    return attrs.getLength() == 1 and \
-           attrs.getNames() == [(ns_uri, "attr")] and \
-           (attrs.getQNames() == [] or attrs.getQNames() == ["ns:attr"]) and \
-           len(attrs) == 1 and \
-           attrs.has_key((ns_uri, "attr")) and \
-           attrs.keys() == [(ns_uri, "attr")] and \
-           attrs.get((ns_uri, "attr")) == "val" and \
-           attrs.get((ns_uri, "attr"), 25) == "val" and \
-           attrs.items() == [((ns_uri, "attr"), "val")] and \
-           attrs.values() == ["val"] and \
-           attrs.getValue((ns_uri, "attr")) == "val" and \
-           attrs[(ns_uri, "attr")] == "val"
-
-# ===== InputSource support
-
 xml_test_out = open(findfile("test"+os.extsep+"xml"+os.extsep+"out")).read()
 
-def test_expat_inpsource_filename():
-    parser = create_parser()
-    result = StringIO()
-    xmlgen = XMLGenerator(result)
-
-    parser.setContentHandler(xmlgen)
-    parser.parse(findfile("test"+os.extsep+"xml"))
-
-    return result.getvalue() == xml_test_out
-
-def test_expat_inpsource_sysid():
-    parser = create_parser()
-    result = StringIO()
-    xmlgen = XMLGenerator(result)
-
-    parser.setContentHandler(xmlgen)
-    parser.parse(InputSource(findfile("test"+os.extsep+"xml")))
-
-    return result.getvalue() == xml_test_out
-
-def test_expat_inpsource_stream():
-    parser = create_parser()
-    result = StringIO()
-    xmlgen = XMLGenerator(result)
-
-    parser.setContentHandler(xmlgen)
-    inpsrc = InputSource()
-    inpsrc.setByteStream(open(findfile("test"+os.extsep+"xml")))
-    parser.parse(inpsrc)
-
-    return result.getvalue() == xml_test_out
-
-# ===== IncrementalParser support
-
-def test_expat_incremental():
-    result = StringIO()
-    xmlgen = XMLGenerator(result)
-    parser = create_parser()
-    parser.setContentHandler(xmlgen)
-
-    parser.feed("<doc>")
-    parser.feed("</doc>")
-    parser.close()
-
-    return result.getvalue() == start + "<doc></doc>"
-
-def test_expat_incremental_reset():
-    result = StringIO()
-    xmlgen = XMLGenerator(result)
-    parser = create_parser()
-    parser.setContentHandler(xmlgen)
-
-    parser.feed("<doc>")
-    parser.feed("text")
-
-    result = StringIO()
-    xmlgen = XMLGenerator(result)
-    parser.setContentHandler(xmlgen)
-    parser.reset()
-
-    parser.feed("<doc>")
-    parser.feed("text")
-    parser.feed("</doc>")
-    parser.close()
-
-    return result.getvalue() == start + "<doc>text</doc>"
-
-# ===== Locator support
-
-def test_expat_locator_noinfo():
-    result = StringIO()
-    xmlgen = XMLGenerator(result)
-    parser = create_parser()
-    parser.setContentHandler(xmlgen)
-
-    parser.feed("<doc>")
-    parser.feed("</doc>")
-    parser.close()
-
-    return parser.getSystemId() is None and \
-           parser.getPublicId() is None and \
-           parser.getLineNumber() == 1
-
-def test_expat_locator_withinfo():
-    result = StringIO()
-    xmlgen = XMLGenerator(result)
-    parser = create_parser()
-    parser.setContentHandler(xmlgen)
-    parser.parse(findfile("test.xml"))
-
-    return parser.getSystemId() == findfile("test.xml") and \
-           parser.getPublicId() is None
-
-
+class ExpatReaderTest(XmlTestBase):
+    
+    # ===== XMLReader support
+
+    def test_expat_file(self):
+        parser = create_parser()
+        result = StringIO()
+        xmlgen = XMLGenerator(result)
+
+        parser.setContentHandler(xmlgen)
+        parser.parse(open(findfile("test"+os.extsep+"xml")))
+
+        self.assertEquals(result.getvalue(), xml_test_out)
+
+    # ===== DTDHandler support
+
+    class TestDTDHandler:
+
+        def __init__(self):
+            self._notations = []
+            self._entities  = []
+
+        def notationDecl(self, name, publicId, systemId):
+            self._notations.append((name, publicId, systemId))
+
+        def unparsedEntityDecl(self, name, publicId, systemId, ndata):
+            self._entities.append((name, publicId, systemId, ndata))
+
+    def test_expat_dtdhandler(self):
+        parser = create_parser()
+        handler = self.TestDTDHandler()
+        parser.setDTDHandler(handler)
+
+        parser.feed('<!DOCTYPE doc [\n')
+        parser.feed('  <!ENTITY img SYSTEM "expat.gif" NDATA GIF>\n')
+        parser.feed('  <!NOTATION GIF PUBLIC "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN">\n')
+        parser.feed(']>\n')
+        parser.feed('<doc></doc>')
+        parser.close()
+
+        self.assertEquals(handler._notations, 
+            [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)])
+        self.assertEquals(handler._entities, [("img", None, "expat.gif", "GIF")])
+
+    # ===== EntityResolver support
+
+    class TestEntityResolver:
+
+        def resolveEntity(self, publicId, systemId):
+            inpsrc = InputSource()
+            inpsrc.setByteStream(StringIO("<entity/>"))
+            return inpsrc
+
+    def test_expat_entityresolver(self):
+        parser = create_parser()
+        parser.setEntityResolver(self.TestEntityResolver())
+        result = StringIO()
+        parser.setContentHandler(XMLGenerator(result))
+
+        parser.feed('<!DOCTYPE doc [\n')
+        parser.feed('  <!ENTITY test SYSTEM "whatever">\n')
+        parser.feed(']>\n')
+        parser.feed('<doc>&test;</doc>')
+        parser.close()
+
+        self.assertEquals(result.getvalue(), start + 
+                          "<doc><entity></entity></doc>")
+
+    # ===== Attributes support
+
+    class AttrGatherer(ContentHandler):
+
+        def startElement(self, name, attrs):
+            self._attrs = attrs
+
+        def startElementNS(self, name, qname, attrs):
+            self._attrs = attrs
+
+    def test_expat_attrs_empty(self):
+        parser = create_parser()
+        gather = self.AttrGatherer()
+        parser.setContentHandler(gather)
+
+        parser.feed("<doc/>")
+        parser.close()
+
+        self.verify_empty_attrs(gather._attrs)
+
+    def test_expat_attrs_wattr(self):
+        parser = create_parser()
+        gather = self.AttrGatherer()
+        parser.setContentHandler(gather)
+
+        parser.feed("<doc attr='val'/>")
+        parser.close()
+
+        self.verify_attrs_wattr(gather._attrs)
+
+    def test_expat_nsattrs_empty(self):
+        parser = create_parser(1)
+        gather = self.AttrGatherer()
+        parser.setContentHandler(gather)
+
+        parser.feed("<doc/>")
+        parser.close()
+
+        self.verify_empty_nsattrs(gather._attrs)
+
+    def test_expat_nsattrs_wattr(self):
+        parser = create_parser(1)
+        gather = self.AttrGatherer()
+        parser.setContentHandler(gather)
+
+        parser.feed("<doc xmlns:ns='%s' ns:attr='val'/>" % ns_uri)
+        parser.close()
+
+        attrs = gather._attrs
+
+        self.assertEquals(attrs.getLength(), 1)
+        self.assertEquals(attrs.getNames(), [(ns_uri, "attr")])
+        self.assertTrue((attrs.getQNames() == [] or 
+                         attrs.getQNames() == ["ns:attr"]))
+        self.assertEquals(len(attrs), 1)
+        self.assertTrue(attrs.has_key((ns_uri, "attr")))
+        self.assertEquals(attrs.get((ns_uri, "attr")), "val")
+        self.assertEquals(attrs.get((ns_uri, "attr"), 25), "val")
+        self.assertEquals(attrs.items(), [((ns_uri, "attr"), "val")])
+        self.assertEquals(attrs.values(), ["val"])
+        self.assertEquals(attrs.getValue((ns_uri, "attr")), "val")
+        self.assertEquals(attrs[(ns_uri, "attr")], "val")
+
+    # ===== InputSource support
+    
+    def test_expat_inpsource_filename(self):
+        parser = create_parser()
+        result = StringIO()
+        xmlgen = XMLGenerator(result)
+    
+        parser.setContentHandler(xmlgen)
+        parser.parse(findfile("test"+os.extsep+"xml"))
+
+        self.assertEquals(result.getvalue(), xml_test_out)
+    
+    def test_expat_inpsource_sysid(self):
+        parser = create_parser()
+        result = StringIO()
+        xmlgen = XMLGenerator(result)
+    
+        parser.setContentHandler(xmlgen)
+        parser.parse(InputSource(findfile("test"+os.extsep+"xml")))
+
+        self.assertEquals(result.getvalue(), xml_test_out)
+    
+    def test_expat_inpsource_stream(self):
+        parser = create_parser()
+        result = StringIO()
+        xmlgen = XMLGenerator(result)
+    
+        parser.setContentHandler(xmlgen)
+        inpsrc = InputSource()
+        inpsrc.setByteStream(open(findfile("test"+os.extsep+"xml")))
+        parser.parse(inpsrc)
+    
+        self.assertEquals(result.getvalue(), xml_test_out)
+    
+    # ===== IncrementalParser support
+    
+    def test_expat_incremental(self):
+        result = StringIO()
+        xmlgen = XMLGenerator(result)
+        parser = create_parser()
+        parser.setContentHandler(xmlgen)
+    
+        parser.feed("<doc>")
+        parser.feed("</doc>")
+        parser.close()
+    
+        self.assertEquals(result.getvalue(), start + "<doc></doc>")
+    
+    def test_expat_incremental_reset(self):
+        result = StringIO()
+        xmlgen = XMLGenerator(result)
+        parser = create_parser()
+        parser.setContentHandler(xmlgen)
+    
+        parser.feed("<doc>")
+        parser.feed("text")
+    
+        result = StringIO()
+        xmlgen = XMLGenerator(result)
+        parser.setContentHandler(xmlgen)
+        parser.reset()
+    
+        parser.feed("<doc>")
+        parser.feed("text")
+        parser.feed("</doc>")
+        parser.close()
+
+        self.assertEquals(result.getvalue(), start + "<doc>text</doc>")
+    
+    # ===== Locator support
+    
+    def test_expat_locator_noinfo(self):
+        result = StringIO()
+        xmlgen = XMLGenerator(result)
+        parser = create_parser()
+        parser.setContentHandler(xmlgen)
+    
+        parser.feed("<doc>")
+        parser.feed("</doc>")
+        parser.close()
+    
+        self.assertEquals(parser.getSystemId(), None)
+        self.assertEquals(parser.getPublicId(), None)
+        self.assertEquals(parser.getLineNumber(), 1)
+    
+    def test_expat_locator_withinfo(self):
+        result = StringIO()
+        xmlgen = XMLGenerator(result)
+        parser = create_parser()
+        parser.setContentHandler(xmlgen)
+        parser.parse(findfile("test.xml"))
+    
+        self.assertEquals(parser.getSystemId(), findfile("test.xml"))
+        self.assertEquals(parser.getPublicId(), None)
+    
+    
 # ===========================================================================
 #
 #   error reporting
 #
 # ===========================================================================
 
-def test_expat_inpsource_location():
-    parser = create_parser()
-    parser.setContentHandler(ContentHandler()) # do nothing
-    source = InputSource()
-    source.setByteStream(StringIO("<foo bar foobar>"))   #ill-formed
-    name = "a file name"
-    source.setSystemId(name)
-    try:
-        parser.parse(source)
-    except SAXException, e:
-        return e.getSystemId() == name
-
-def test_expat_incomplete():
-    parser = create_parser()
-    parser.setContentHandler(ContentHandler()) # do nothing
-    try:
-        parser.parse(StringIO("<foo>"))
-    except SAXParseException:
-        return 1 # ok, error found
-    else:
-        return 0
-
-def test_sax_parse_exception_str():
-    # pass various values from a locator to the SAXParseException to
-    # make sure that the __str__() doesn't fall apart when None is
-    # passed instead of an integer line and column number
-    #
-    # use "normal" values for the locator:
-    str(SAXParseException("message", None,
-                          DummyLocator(1, 1)))
-    # use None for the line number:
-    str(SAXParseException("message", None,
-                          DummyLocator(None, 1)))
-    # use None for the column number:
-    str(SAXParseException("message", None,
-                          DummyLocator(1, None)))
-    # use None for both:
-    str(SAXParseException("message", None,
-                          DummyLocator(None, None)))
-    return 1
-
-class DummyLocator:
-    def __init__(self, lineno, colno):
-        self._lineno = lineno
-        self._colno = colno
-
-    def getPublicId(self):
-        return "pubid"
-
-    def getSystemId(self):
-        return "sysid"
-
-    def getLineNumber(self):
-        return self._lineno
-
-    def getColumnNumber(self):
-        return self._colno
+class ErrorReportingTest(unittest.TestCase):
+    def test_expat_inpsource_location(self):
+        parser = create_parser()
+        parser.setContentHandler(ContentHandler()) # do nothing
+        source = InputSource()
+        source.setByteStream(StringIO("<foo bar foobar>"))   #ill-formed
+        name = "a file name"
+        source.setSystemId(name)
+        try:
+            parser.parse(source)
+            self.fail()
+        except SAXException, e:
+            self.assertEquals(e.getSystemId(), name)
+    
+    def test_expat_incomplete(self):
+        parser = create_parser()
+        parser.setContentHandler(ContentHandler()) # do nothing
+        self.assertRaises(SAXParseException, parser.parse, StringIO("<foo>"))
+    
+    def test_sax_parse_exception_str(self):
+        # pass various values from a locator to the SAXParseException to
+        # make sure that the __str__() doesn't fall apart when None is
+        # passed instead of an integer line and column number
+        #
+        # use "normal" values for the locator:
+        str(SAXParseException("message", None,
+                              self.DummyLocator(1, 1)))
+        # use None for the line number:
+        str(SAXParseException("message", None,
+                              self.DummyLocator(None, 1)))
+        # use None for the column number:
+        str(SAXParseException("message", None,
+                              self.DummyLocator(1, None)))
+        # use None for both:
+        str(SAXParseException("message", None,
+                              self.DummyLocator(None, None)))
+    
+    class DummyLocator:
+        def __init__(self, lineno, colno):
+            self._lineno = lineno
+            self._colno = colno
+    
+        def getPublicId(self):
+            return "pubid"
+    
+        def getSystemId(self):
+            return "sysid"
+    
+        def getLineNumber(self):
+            return self._lineno
+    
+        def getColumnNumber(self):
+            return self._colno
 
 # ===========================================================================
 #
@@ -571,218 +606,91 @@
 #
 # ===========================================================================
 
-# ===== AttributesImpl
+class XmlReaderTest(XmlTestBase):
+        
+    # ===== AttributesImpl
+    def test_attrs_empty(self):
+        self.verify_empty_attrs(AttributesImpl({}))
+    
+    def test_attrs_wattr(self):
+        self.verify_attrs_wattr(AttributesImpl({"attr" : "val"}))
+    
+    def test_nsattrs_empty(self):
+        self.verify_empty_nsattrs(AttributesNSImpl({}, {}))
+    
+    def test_nsattrs_wattr(self):
+        attrs = AttributesNSImpl({(ns_uri, "attr") : "val"},
+                                 {(ns_uri, "attr") : "ns:attr"})
+    
+        self.assertEquals(attrs.getLength(), 1)
+        self.assertEquals(attrs.getNames(), [(ns_uri, "attr")])
+        self.assertEquals(attrs.getQNames(), ["ns:attr"])
+        self.assertEquals(len(attrs), 1)
+        self.assertTrue(attrs.has_key((ns_uri, "attr")))
+        self.assertEquals(attrs.keys(), [(ns_uri, "attr")])
+        self.assertEquals(attrs.get((ns_uri, "attr")), "val")
+        self.assertEquals(attrs.get((ns_uri, "attr"), 25), "val")
+        self.assertEquals(attrs.items(), [((ns_uri, "attr"), "val")])
+        self.assertEquals(attrs.values(), ["val"])
+        self.assertEquals(attrs.getValue((ns_uri, "attr")), "val")
+        self.assertEquals(attrs.getValueByQName("ns:attr"), "val")
+        self.assertEquals(attrs.getNameByQName("ns:attr"), (ns_uri, "attr"))
+        self.assertEquals(attrs[(ns_uri, "attr")], "val")
+        self.assertEquals(attrs.getQNameByName((ns_uri, "attr")), "ns:attr")
+
+
+    # During the development of Python 2.5, an attempt to move the "xml"
+    # package implementation to a new package ("xmlcore") proved painful.
+    # The goal of this change was to allow applications to be able to
+    # obtain and rely on behavior in the standard library implementation
+    # of the XML support without needing to be concerned about the
+    # availability of the PyXML implementation.
+    #
+    # While the existing import hackery in Lib/xml/__init__.py can cause
+    # PyXML's _xmlpus package to supplant the "xml" package, that only
+    # works because either implementation uses the "xml" package name for
+    # imports.
+    #
+    # The move resulted in a number of problems related to the fact that
+    # the import machinery's "package context" is based on the name that's
+    # being imported rather than the __name__ of the actual package
+    # containment; it wasn't possible for the "xml" package to be replaced
+    # by a simple module that indirected imports to the "xmlcore" package.
+    #
+    # The following two tests exercised bugs that were introduced in that
+    # attempt.  Keeping these tests around will help detect problems with
+    # other attempts to provide reliable access to the standard library's
+    # implementation of the XML support.
+    
+    def test_sf_1511497(self):
+        # Bug report: http://www.python.org/sf/1511497
+        import sys
+        old_modules = sys.modules.copy()
+        for modname in sys.modules.keys():
+            if modname.startswith("xml."):
+                del sys.modules[modname]
+        try:
+            import xml.sax.expatreader
+            module = xml.sax.expatreader
+            self.assertEquals(module.__name__, "xml.sax.expatreader")
+        finally:
+            sys.modules.update(old_modules)
+    
+    def test_sf_1513611(self):
+        # Bug report: http://www.python.org/sf/1513611
+        sio = StringIO("invalid")
+        parser = make_parser()
+        from xml.sax import SAXParseException
+        self.assertRaises(SAXParseException, parser.parse, sio)
+
+
+def unittest_main():
+    run_unittest(MakeParserTest,
+                 SaxutilsTest,
+                 XmlgenTest,
+                 ExpatReaderTest,
+                 ErrorReportingTest,
+                 XmlReaderTest)
 
-def verify_empty_attrs(attrs):
-    try:
-        attrs.getValue("attr")
-        gvk = 0
-    except KeyError:
-        gvk = 1
-
-    try:
-        attrs.getValueByQName("attr")
-        gvqk = 0
-    except KeyError:
-        gvqk = 1
-
-    try:
-        attrs.getNameByQName("attr")
-        gnqk = 0
-    except KeyError:
-        gnqk = 1
-
-    try:
-        attrs.getQNameByName("attr")
-        gqnk = 0
-    except KeyError:
-        gqnk = 1
-
-    try:
-        attrs["attr"]
-        gik = 0
-    except KeyError:
-        gik = 1
-
-    return attrs.getLength() == 0 and \
-           attrs.getNames() == [] and \
-           attrs.getQNames() == [] and \
-           len(attrs) == 0 and \
-           not attrs.has_key("attr") and \
-           attrs.keys() == [] and \
-           attrs.get("attrs") is None and \
-           attrs.get("attrs", 25) == 25 and \
-           attrs.items() == [] and \
-           attrs.values() == [] and \
-           gvk and gvqk and gnqk and gik and gqnk
-
-def verify_attrs_wattr(attrs):
-    return attrs.getLength() == 1 and \
-           attrs.getNames() == ["attr"] and \
-           attrs.getQNames() == ["attr"] and \
-           len(attrs) == 1 and \
-           attrs.has_key("attr") and \
-           attrs.keys() == ["attr"] and \
-           attrs.get("attr") == "val" and \
-           attrs.get("attr", 25) == "val" and \
-           attrs.items() == [("attr", "val")] and \
-           attrs.values() == ["val"] and \
-           attrs.getValue("attr") == "val" and \
-           attrs.getValueByQName("attr") == "val" and \
-           attrs.getNameByQName("attr") == "attr" and \
-           attrs["attr"] == "val" and \
-           attrs.getQNameByName("attr") == "attr"
-
-def test_attrs_empty():
-    return verify_empty_attrs(AttributesImpl({}))
-
-def test_attrs_wattr():
-    return verify_attrs_wattr(AttributesImpl({"attr" : "val"}))
-
-# ===== AttributesImpl
-
-def verify_empty_nsattrs(attrs):
-    try:
-        attrs.getValue((ns_uri, "attr"))
-        gvk = 0
-    except KeyError:
-        gvk = 1
-
-    try:
-        attrs.getValueByQName("ns:attr")
-        gvqk = 0
-    except KeyError:
-        gvqk = 1
-
-    try:
-        attrs.getNameByQName("ns:attr")
-        gnqk = 0
-    except KeyError:
-        gnqk = 1
-
-    try:
-        attrs.getQNameByName((ns_uri, "attr"))
-        gqnk = 0
-    except KeyError:
-        gqnk = 1
-
-    try:
-        attrs[(ns_uri, "attr")]
-        gik = 0
-    except KeyError:
-        gik = 1
-
-    return attrs.getLength() == 0 and \
-           attrs.getNames() == [] and \
-           attrs.getQNames() == [] and \
-           len(attrs) == 0 and \
-           not attrs.has_key((ns_uri, "attr")) and \
-           attrs.keys() == [] and \
-           attrs.get((ns_uri, "attr")) is None and \
-           attrs.get((ns_uri, "attr"), 25) == 25 and \
-           attrs.items() == [] and \
-           attrs.values() == [] and \
-           gvk and gvqk and gnqk and gik and gqnk
-
-def test_nsattrs_empty():
-    return verify_empty_nsattrs(AttributesNSImpl({}, {}))
-
-def test_nsattrs_wattr():
-    attrs = AttributesNSImpl({(ns_uri, "attr") : "val"},
-                             {(ns_uri, "attr") : "ns:attr"})
-
-    return attrs.getLength() == 1 and \
-           attrs.getNames() == [(ns_uri, "attr")] and \
-           attrs.getQNames() == ["ns:attr"] and \
-           len(attrs) == 1 and \
-           attrs.has_key((ns_uri, "attr")) and \
-           attrs.keys() == [(ns_uri, "attr")] and \
-           attrs.get((ns_uri, "attr")) == "val" and \
-           attrs.get((ns_uri, "attr"), 25) == "val" and \
-           attrs.items() == [((ns_uri, "attr"), "val")] and \
-           attrs.values() == ["val"] and \
-           attrs.getValue((ns_uri, "attr")) == "val" and \
-           attrs.getValueByQName("ns:attr") == "val" and \
-           attrs.getNameByQName("ns:attr") == (ns_uri, "attr") and \
-           attrs[(ns_uri, "attr")] == "val" and \
-           attrs.getQNameByName((ns_uri, "attr")) == "ns:attr"
-
-
-# During the development of Python 2.5, an attempt to move the "xml"
-# package implementation to a new package ("xmlcore") proved painful.
-# The goal of this change was to allow applications to be able to
-# obtain and rely on behavior in the standard library implementation
-# of the XML support without needing to be concerned about the
-# availability of the PyXML implementation.
-#
-# While the existing import hackery in Lib/xml/__init__.py can cause
-# PyXML's _xmlpus package to supplant the "xml" package, that only
-# works because either implementation uses the "xml" package name for
-# imports.
-#
-# The move resulted in a number of problems related to the fact that
-# the import machinery's "package context" is based on the name that's
-# being imported rather than the __name__ of the actual package
-# containment; it wasn't possible for the "xml" package to be replaced
-# by a simple module that indirected imports to the "xmlcore" package.
-#
-# The following two tests exercised bugs that were introduced in that
-# attempt.  Keeping these tests around will help detect problems with
-# other attempts to provide reliable access to the standard library's
-# implementation of the XML support.
-
-def test_sf_1511497():
-    # Bug report: http://www.python.org/sf/1511497
-    import sys
-    old_modules = sys.modules.copy()
-    for modname in sys.modules.keys():
-        if modname.startswith("xml."):
-            del sys.modules[modname]
-    try:
-        import xml.sax.expatreader
-        module = xml.sax.expatreader
-        return module.__name__ == "xml.sax.expatreader"
-    finally:
-        sys.modules.update(old_modules)
-
-def test_sf_1513611():
-    # Bug report: http://www.python.org/sf/1513611
-    sio = StringIO("invalid")
-    parser = make_parser()
-    from xml.sax import SAXParseException
-    try:
-        parser.parse(sio)
-    except SAXParseException:
-        return True
-    else:
-        return False
-
-# ===== Main program
-
-def make_test_output():
-    parser = create_parser()
-    result = StringIO()
-    xmlgen = XMLGenerator(result)
-
-    parser.setContentHandler(xmlgen)
-    parser.parse(findfile("test"+os.extsep+"xml"))
-
-    outf = open(findfile("test"+os.extsep+"xml"+os.extsep+"out"), "w")
-    outf.write(result.getvalue())
-    outf.close()
-
-items = locals().items()
-items.sort()
-for (name, value) in items:
-    if name[ : 5] == "test_":
-        confirm(value(), name)
-# We delete the items variable so that the assignment to items above
-# doesn't pick up the old value of items (which messes with attempts
-# to find reference leaks).
-del items
-
-if verbose:
-    print "%d tests, %d failures" % (tests, len(failures))
-if failures:
-    raise TestFailed("%d of %d tests failed: %s"
-                     % (len(failures), tests, ", ".join(failures)))
+if __name__ == "__main__":
+     unittest_main()


More information about the Python-checkins mailing list