diff -r 000000000000 -r ae805ac0140d python-2.5.2/win32/Lib/test/test_sax.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python-2.5.2/win32/Lib/test/test_sax.py Fri Apr 03 17:19:34 2009 +0100 @@ -0,0 +1,788 @@ +# regression test for SAX 2.0 -*- coding: iso-8859-1 -*- +# $Id: test_sax.py 54954 2007-04-25 06:42:41Z neal.norwitz $ + +from xml.sax import make_parser, ContentHandler, \ + SAXException, SAXReaderNotAvailable, SAXParseException +try: + make_parser() +except SAXReaderNotAvailable: + # don't try to test this module if we cannot create a parser + raise ImportError("no XML parsers available") +from xml.sax.saxutils import XMLGenerator, escape, unescape, quoteattr, \ + XMLFilterBase +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 +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) + +def test_make_parser2(): + try: + # Creating parsers several times in a row should succeed. + # Testing this because there have been failures of this kind + # before. + from xml.sax import make_parser + p = make_parser() + from xml.sax import make_parser + p = make_parser() + from xml.sax import make_parser + p = make_parser() + from xml.sax import make_parser + p = make_parser() + from xml.sax import make_parser + p = make_parser() + from xml.sax import make_parser + p = make_parser() + except: + return 0 + else: + return p + + +# =========================================================================== +# +# saxutils tests +# +# =========================================================================== + +# ===== escape + +def test_escape_basic(): + return escape("Donald Duck & Co") == "Donald Duck & Co" + +def test_escape_all(): + return escape("") == "<Donald Duck & Co>" + +def test_escape_extra(): + return escape("Hei på deg", {"å" : "å"}) == "Hei på deg" + +# ===== unescape + +def test_unescape_basic(): + return unescape("Donald Duck & Co") == "Donald Duck & Co" + +def test_unescape_all(): + return unescape("<Donald Duck & Co>") == "" + +def test_unescape_extra(): + return unescape("Hei på deg", {"å" : "å"}) == "Hei på deg" + +def test_unescape_amp_extra(): + return unescape("&foo;", {"&foo;": "splat"}) == "&foo;" + +# ===== quoteattr + +def test_quoteattr_basic(): + return quoteattr("Donald Duck & Co") == '"Donald Duck & 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 "double" quotes\"") + +# ===== make_parser + +def test_make_parser(): + try: + # 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 = '\n' + +def test_xmlgen_basic(): + result = StringIO() + gen = XMLGenerator(result) + gen.startDocument() + gen.startElement("doc", {}) + gen.endElement("doc") + gen.endDocument() + + return result.getvalue() == start + "" + +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 + "huhei" + +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 + "" + +def test_xmlgen_content_escape(): + result = StringIO() + gen = XMLGenerator(result) + + gen.startDocument() + gen.startElement("doc", {}) + gen.characters("<huhei&" + +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 + ("" + "" + "") + +def test_xmlgen_ignorable(): + result = StringIO() + gen = XMLGenerator(result) + + gen.startDocument() + gen.startElement("doc", {}) + gen.ignorableWhitespace(" ") + gen.endElement("doc") + gen.endDocument() + + return result.getvalue() == start + " " + +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 + \ + ('' % + 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+'' + +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+'' + +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+'' + +# ===== 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() + + return result.getvalue() == start + "content " + +# =========================================================================== +# +# expatreader tests +# +# =========================================================================== + +# ===== 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('\n') + parser.feed(' \n') + parser.feed(']>\n') + parser.feed('') + 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("")) + return inpsrc + +def test_expat_entityresolver(): + parser = create_parser() + parser.setEntityResolver(TestEntityResolver()) + result = StringIO() + parser.setContentHandler(XMLGenerator(result)) + + parser.feed('\n') + parser.feed(']>\n') + parser.feed('&test;') + parser.close() + + return result.getvalue() == start + "" + +# ===== 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("") + parser.close() + + return verify_empty_attrs(gather._attrs) + +def test_expat_attrs_wattr(): + parser = create_parser() + gather = AttrGatherer() + parser.setContentHandler(gather) + + parser.feed("") + parser.close() + + return verify_attrs_wattr(gather._attrs) + +def test_expat_nsattrs_empty(): + parser = create_parser(1) + gather = AttrGatherer() + parser.setContentHandler(gather) + + parser.feed("") + parser.close() + + return verify_empty_nsattrs(gather._attrs) + +def test_expat_nsattrs_wattr(): + parser = create_parser(1) + gather = AttrGatherer() + parser.setContentHandler(gather) + + parser.feed("" % 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("") + parser.feed("") + parser.close() + + return result.getvalue() == start + "" + +def test_expat_incremental_reset(): + result = StringIO() + xmlgen = XMLGenerator(result) + parser = create_parser() + parser.setContentHandler(xmlgen) + + parser.feed("") + parser.feed("text") + + result = StringIO() + xmlgen = XMLGenerator(result) + parser.setContentHandler(xmlgen) + parser.reset() + + parser.feed("") + parser.feed("text") + parser.feed("") + parser.close() + + return result.getvalue() == start + "text" + +# ===== Locator support + +def test_expat_locator_noinfo(): + result = StringIO() + xmlgen = XMLGenerator(result) + parser = create_parser() + parser.setContentHandler(xmlgen) + + parser.feed("") + parser.feed("") + 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 + + +# =========================================================================== +# +# error reporting +# +# =========================================================================== + +def test_expat_inpsource_location(): + parser = create_parser() + parser.setContentHandler(ContentHandler()) # do nothing + source = InputSource() + source.setByteStream(StringIO("")) #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("")) + 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 + +# =========================================================================== +# +# xmlreader tests +# +# =========================================================================== + +# ===== AttributesImpl + +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)))