diff --git a/Lib/test/output/test_sax b/Lib/test/output/test_sax
index 420287e59b5..873ed5108c7 100644
--- a/Lib/test/output/test_sax
+++ b/Lib/test/output/test_sax
@@ -1,12 +1,20 @@
test_sax
+Passed test_attrs_empty
+Passed test_attrs_wattr
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_nsattrs_empty
+Passed test_expat_nsattrs_wattr
Passed test_filter_basic
+Passed test_nsattrs_empty
+Passed test_nsattrs_wattr
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
-10 tests, 0 failures
+18 tests, 0 failures
diff --git a/Lib/test/test_sax.py b/Lib/test/test_sax.py
index 6c887ec9a83..1e7e0375855 100644
--- a/Lib/test/test_sax.py
+++ b/Lib/test/test_sax.py
@@ -4,6 +4,8 @@
from xml.sax.saxutils import XMLGenerator, escape, XMLFilterBase
from xml.sax.expatreader import create_parser
+from xml.sax.xmlreader import AttributesImpl, AttributesNSImpl
+from xml.sax.handler import ContentHandler
from cStringIO import StringIO
from test_support import verbose, TestFailed
@@ -173,6 +175,212 @@ class TestDTDHandler:
# can't test this until InputSource is in place
+# ===== 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() == [] 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"
+
+# ===========================================================================
+#
+# 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") == 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")) == 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"
+
+
# ===== Main program
items = locals().items()