blob: af4c7dd8f41bf1251e7fcbd39197191eb073935c [file] [log] [blame]
Martin v. Löwisa729daf2002-08-04 17:28:33 +00001# regression test for SAX 2.0 -*- coding: iso-8859-1 -*-
Lars Gustäbel96753b32000-09-24 12:24:24 +00002# $Id$
3
Thomas Wouters0e3f5912006-08-11 14:57:12 +00004from xml.sax import make_parser, ContentHandler, \
5 SAXException, SAXReaderNotAvailable, SAXParseException
Martin v. Löwis962c9e72000-10-06 17:41:52 +00006try:
7 make_parser()
Martin v. Löwis80670bc2000-10-06 21:13:23 +00008except SAXReaderNotAvailable:
Martin v. Löwis962c9e72000-10-06 17:41:52 +00009 # don't try to test this module if we cannot create a parser
10 raise ImportError("no XML parsers available")
Thomas Wouters0e3f5912006-08-11 14:57:12 +000011from xml.sax.saxutils import XMLGenerator, escape, unescape, quoteattr, \
12 XMLFilterBase
13from xml.sax.expatreader import create_parser
14from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl
Lars Gustäbel96753b32000-09-24 12:24:24 +000015from cStringIO import StringIO
Barry Warsaw04f357c2002-07-23 19:04:11 +000016from test.test_support import verify, verbose, TestFailed, findfile
Guido van Rossume2ae77b2001-10-24 20:42:55 +000017import os
Lars Gustäbel96753b32000-09-24 12:24:24 +000018
19# ===== Utilities
20
21tests = 0
Fred Drake32f3add2002-10-28 17:58:48 +000022failures = []
Lars Gustäbel96753b32000-09-24 12:24:24 +000023
24def confirm(outcome, name):
Fred Drake32f3add2002-10-28 17:58:48 +000025 global tests
Lars Gustäbel96753b32000-09-24 12:24:24 +000026
27 tests = tests + 1
28 if outcome:
Fred Drake32f3add2002-10-28 17:58:48 +000029 if verbose:
Andrew M. Kuchling09e2cb02004-06-01 12:48:19 +000030 print "Passed", name
Lars Gustäbel96753b32000-09-24 12:24:24 +000031 else:
Fred Drake32f3add2002-10-28 17:58:48 +000032 failures.append(name)
Lars Gustäbel96753b32000-09-24 12:24:24 +000033
Lars Gustäbel2fc52942000-10-24 15:35:07 +000034def test_make_parser2():
Tim Petersd2bf3b72001-01-18 02:22:22 +000035 try:
Lars Gustäbel2fc52942000-10-24 15:35:07 +000036 # Creating parsers several times in a row should succeed.
37 # Testing this because there have been failures of this kind
38 # before.
Thomas Wouters0e3f5912006-08-11 14:57:12 +000039 from xml.sax import make_parser
Lars Gustäbel2fc52942000-10-24 15:35:07 +000040 p = make_parser()
Thomas Wouters0e3f5912006-08-11 14:57:12 +000041 from xml.sax import make_parser
Lars Gustäbel2fc52942000-10-24 15:35:07 +000042 p = make_parser()
Thomas Wouters0e3f5912006-08-11 14:57:12 +000043 from xml.sax import make_parser
Lars Gustäbel2fc52942000-10-24 15:35:07 +000044 p = make_parser()
Thomas Wouters0e3f5912006-08-11 14:57:12 +000045 from xml.sax import make_parser
Lars Gustäbel2fc52942000-10-24 15:35:07 +000046 p = make_parser()
Thomas Wouters0e3f5912006-08-11 14:57:12 +000047 from xml.sax import make_parser
Lars Gustäbel2fc52942000-10-24 15:35:07 +000048 p = make_parser()
Thomas Wouters0e3f5912006-08-11 14:57:12 +000049 from xml.sax import make_parser
Lars Gustäbel2fc52942000-10-24 15:35:07 +000050 p = make_parser()
51 except:
52 return 0
53 else:
54 return p
Tim Petersd2bf3b72001-01-18 02:22:22 +000055
56
Lars Gustäbel96753b32000-09-24 12:24:24 +000057# ===========================================================================
58#
59# saxutils tests
60#
61# ===========================================================================
62
63# ===== escape
64
65def test_escape_basic():
66 return escape("Donald Duck & Co") == "Donald Duck & Co"
67
68def test_escape_all():
69 return escape("<Donald Duck & Co>") == "&lt;Donald Duck &amp; Co&gt;"
70
71def test_escape_extra():
72 return escape("Hei på deg", {"å" : "&aring;"}) == "Hei p&aring; deg"
73
Martin v. Löwis74b51ac2002-10-26 14:50:45 +000074# ===== unescape
75
76def test_unescape_basic():
77 return unescape("Donald Duck &amp; Co") == "Donald Duck & Co"
78
79def test_unescape_all():
80 return unescape("&lt;Donald Duck &amp; Co&gt;") == "<Donald Duck & Co>"
81
82def test_unescape_extra():
83 return unescape("Hei på deg", {"å" : "&aring;"}) == "Hei p&aring; deg"
84
Fred Drake32f3add2002-10-28 17:58:48 +000085def test_unescape_amp_extra():
86 return unescape("&amp;foo;", {"&foo;": "splat"}) == "&foo;"
87
Fred Drakeacd32d32001-07-19 16:10:15 +000088# ===== quoteattr
89
90def test_quoteattr_basic():
91 return quoteattr("Donald Duck & Co") == '"Donald Duck &amp; Co"'
92
93def test_single_quoteattr():
94 return (quoteattr('Includes "double" quotes')
95 == '\'Includes "double" quotes\'')
96
97def test_double_quoteattr():
98 return (quoteattr("Includes 'single' quotes")
99 == "\"Includes 'single' quotes\"")
100
101def test_single_double_quoteattr():
102 return (quoteattr("Includes 'single' and \"double\" quotes")
103 == "\"Includes 'single' and &quot;double&quot; quotes\"")
104
105# ===== make_parser
106
Martin v. Löwis962c9e72000-10-06 17:41:52 +0000107def test_make_parser():
108 try:
109 # Creating a parser should succeed - it should fall back
110 # to the expatreader
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000111 p = make_parser(['xml.parsers.no_such_parser'])
Martin v. Löwis962c9e72000-10-06 17:41:52 +0000112 except:
113 return 0
114 else:
115 return p
116
117
Lars Gustäbel96753b32000-09-24 12:24:24 +0000118# ===== XMLGenerator
119
120start = '<?xml version="1.0" encoding="iso-8859-1"?>\n'
121
122def test_xmlgen_basic():
123 result = StringIO()
124 gen = XMLGenerator(result)
125 gen.startDocument()
126 gen.startElement("doc", {})
127 gen.endElement("doc")
128 gen.endDocument()
129
130 return result.getvalue() == start + "<doc></doc>"
131
132def test_xmlgen_content():
133 result = StringIO()
134 gen = XMLGenerator(result)
Fred Drake004d5e62000-10-23 17:22:08 +0000135
Lars Gustäbel96753b32000-09-24 12:24:24 +0000136 gen.startDocument()
137 gen.startElement("doc", {})
138 gen.characters("huhei")
139 gen.endElement("doc")
140 gen.endDocument()
141
142 return result.getvalue() == start + "<doc>huhei</doc>"
143
144def test_xmlgen_pi():
145 result = StringIO()
146 gen = XMLGenerator(result)
Fred Drake004d5e62000-10-23 17:22:08 +0000147
Lars Gustäbel96753b32000-09-24 12:24:24 +0000148 gen.startDocument()
149 gen.processingInstruction("test", "data")
150 gen.startElement("doc", {})
151 gen.endElement("doc")
152 gen.endDocument()
153
154 return result.getvalue() == start + "<?test data?><doc></doc>"
155
156def test_xmlgen_content_escape():
157 result = StringIO()
158 gen = XMLGenerator(result)
Fred Drake004d5e62000-10-23 17:22:08 +0000159
Lars Gustäbel96753b32000-09-24 12:24:24 +0000160 gen.startDocument()
161 gen.startElement("doc", {})
162 gen.characters("<huhei&")
163 gen.endElement("doc")
164 gen.endDocument()
165
166 return result.getvalue() == start + "<doc>&lt;huhei&amp;</doc>"
167
Fred Drakec9fadf92001-08-07 19:17:06 +0000168def test_xmlgen_attr_escape():
169 result = StringIO()
170 gen = XMLGenerator(result)
171
172 gen.startDocument()
173 gen.startElement("doc", {"a": '"'})
174 gen.startElement("e", {"a": "'"})
175 gen.endElement("e")
176 gen.startElement("e", {"a": "'\""})
177 gen.endElement("e")
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000178 gen.startElement("e", {"a": "\n\r\t"})
179 gen.endElement("e")
Fred Drakec9fadf92001-08-07 19:17:06 +0000180 gen.endElement("doc")
181 gen.endDocument()
182
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000183 return result.getvalue() == start + ("<doc a='\"'><e a=\"'\"></e>"
184 "<e a=\"'&quot;\"></e>"
185 "<e a=\"&#10;&#13;&#9;\"></e></doc>")
Fred Drakec9fadf92001-08-07 19:17:06 +0000186
Lars Gustäbel96753b32000-09-24 12:24:24 +0000187def test_xmlgen_ignorable():
188 result = StringIO()
189 gen = XMLGenerator(result)
Fred Drake004d5e62000-10-23 17:22:08 +0000190
Lars Gustäbel96753b32000-09-24 12:24:24 +0000191 gen.startDocument()
192 gen.startElement("doc", {})
193 gen.ignorableWhitespace(" ")
194 gen.endElement("doc")
195 gen.endDocument()
196
197 return result.getvalue() == start + "<doc> </doc>"
198
199ns_uri = "http://www.python.org/xml-ns/saxtest/"
200
201def test_xmlgen_ns():
202 result = StringIO()
203 gen = XMLGenerator(result)
Fred Drake004d5e62000-10-23 17:22:08 +0000204
Lars Gustäbel96753b32000-09-24 12:24:24 +0000205 gen.startDocument()
206 gen.startPrefixMapping("ns1", ns_uri)
Lars Gustäbel6a7768a2000-09-27 08:12:17 +0000207 gen.startElementNS((ns_uri, "doc"), "ns1:doc", {})
Martin v. Löwiscf0a1cc2000-10-03 22:35:29 +0000208 # add an unqualified name
209 gen.startElementNS((None, "udoc"), None, {})
210 gen.endElementNS((None, "udoc"), None)
Lars Gustäbel6a7768a2000-09-27 08:12:17 +0000211 gen.endElementNS((ns_uri, "doc"), "ns1:doc")
Lars Gustäbel96753b32000-09-24 12:24:24 +0000212 gen.endPrefixMapping("ns1")
213 gen.endDocument()
214
Martin v. Löwiscf0a1cc2000-10-03 22:35:29 +0000215 return result.getvalue() == start + \
216 ('<ns1:doc xmlns:ns1="%s"><udoc></udoc></ns1:doc>' %
Lars Gustäbel96753b32000-09-24 12:24:24 +0000217 ns_uri)
218
219# ===== XMLFilterBase
220
221def test_filter_basic():
222 result = StringIO()
223 gen = XMLGenerator(result)
224 filter = XMLFilterBase()
225 filter.setContentHandler(gen)
Fred Drake004d5e62000-10-23 17:22:08 +0000226
Lars Gustäbel96753b32000-09-24 12:24:24 +0000227 filter.startDocument()
228 filter.startElement("doc", {})
229 filter.characters("content")
230 filter.ignorableWhitespace(" ")
231 filter.endElement("doc")
232 filter.endDocument()
233
234 return result.getvalue() == start + "<doc>content </doc>"
235
236# ===========================================================================
237#
238# expatreader tests
239#
240# ===========================================================================
241
Lars Gustäbel07025072000-10-24 16:00:22 +0000242# ===== XMLReader support
243
244def test_expat_file():
245 parser = create_parser()
246 result = StringIO()
247 xmlgen = XMLGenerator(result)
248
249 parser.setContentHandler(xmlgen)
Guido van Rossume2ae77b2001-10-24 20:42:55 +0000250 parser.parse(open(findfile("test"+os.extsep+"xml")))
Lars Gustäbel07025072000-10-24 16:00:22 +0000251
252 return result.getvalue() == xml_test_out
253
Lars Gustäbel96753b32000-09-24 12:24:24 +0000254# ===== DTDHandler support
255
256class TestDTDHandler:
257
258 def __init__(self):
259 self._notations = []
260 self._entities = []
Fred Drake004d5e62000-10-23 17:22:08 +0000261
Lars Gustäbel96753b32000-09-24 12:24:24 +0000262 def notationDecl(self, name, publicId, systemId):
263 self._notations.append((name, publicId, systemId))
264
265 def unparsedEntityDecl(self, name, publicId, systemId, ndata):
266 self._entities.append((name, publicId, systemId, ndata))
267
Lars Gustäbele292a242000-09-24 20:19:45 +0000268def test_expat_dtdhandler():
269 parser = create_parser()
270 handler = TestDTDHandler()
271 parser.setDTDHandler(handler)
Lars Gustäbel96753b32000-09-24 12:24:24 +0000272
Lars Gustäbele292a242000-09-24 20:19:45 +0000273 parser.feed('<!DOCTYPE doc [\n')
274 parser.feed(' <!ENTITY img SYSTEM "expat.gif" NDATA GIF>\n')
275 parser.feed(' <!NOTATION GIF PUBLIC "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN">\n')
276 parser.feed(']>\n')
277 parser.feed('<doc></doc>')
278 parser.close()
Lars Gustäbel96753b32000-09-24 12:24:24 +0000279
Lars Gustäbele292a242000-09-24 20:19:45 +0000280 return handler._notations == [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)] and \
281 handler._entities == [("img", None, "expat.gif", "GIF")]
Lars Gustäbel96753b32000-09-24 12:24:24 +0000282
283# ===== EntityResolver support
284
Lars Gustäbele292a242000-09-24 20:19:45 +0000285class TestEntityResolver:
Lars Gustäbel96753b32000-09-24 12:24:24 +0000286
Lars Gustäbele292a242000-09-24 20:19:45 +0000287 def resolveEntity(self, publicId, systemId):
288 inpsrc = InputSource()
289 inpsrc.setByteStream(StringIO("<entity/>"))
290 return inpsrc
291
292def test_expat_entityresolver():
Lars Gustäbele292a242000-09-24 20:19:45 +0000293 parser = create_parser()
294 parser.setEntityResolver(TestEntityResolver())
295 result = StringIO()
296 parser.setContentHandler(XMLGenerator(result))
297
298 parser.feed('<!DOCTYPE doc [\n')
299 parser.feed(' <!ENTITY test SYSTEM "whatever">\n')
300 parser.feed(']>\n')
301 parser.feed('<doc>&test;</doc>')
302 parser.close()
303
304 return result.getvalue() == start + "<doc><entity></entity></doc>"
Fred Drake004d5e62000-10-23 17:22:08 +0000305
Lars Gustäbelab647872000-09-24 18:40:52 +0000306# ===== Attributes support
307
308class AttrGatherer(ContentHandler):
309
310 def startElement(self, name, attrs):
311 self._attrs = attrs
312
313 def startElementNS(self, name, qname, attrs):
314 self._attrs = attrs
Fred Drake004d5e62000-10-23 17:22:08 +0000315
Lars Gustäbelab647872000-09-24 18:40:52 +0000316def test_expat_attrs_empty():
317 parser = create_parser()
318 gather = AttrGatherer()
319 parser.setContentHandler(gather)
320
321 parser.feed("<doc/>")
322 parser.close()
323
324 return verify_empty_attrs(gather._attrs)
325
326def test_expat_attrs_wattr():
327 parser = create_parser()
328 gather = AttrGatherer()
329 parser.setContentHandler(gather)
330
331 parser.feed("<doc attr='val'/>")
332 parser.close()
333
334 return verify_attrs_wattr(gather._attrs)
335
336def test_expat_nsattrs_empty():
337 parser = create_parser(1)
338 gather = AttrGatherer()
339 parser.setContentHandler(gather)
340
341 parser.feed("<doc/>")
342 parser.close()
343
344 return verify_empty_nsattrs(gather._attrs)
345
346def test_expat_nsattrs_wattr():
347 parser = create_parser(1)
348 gather = AttrGatherer()
349 parser.setContentHandler(gather)
350
351 parser.feed("<doc xmlns:ns='%s' ns:attr='val'/>" % ns_uri)
352 parser.close()
353
354 attrs = gather._attrs
Fred Drake004d5e62000-10-23 17:22:08 +0000355
Lars Gustäbelab647872000-09-24 18:40:52 +0000356 return attrs.getLength() == 1 and \
357 attrs.getNames() == [(ns_uri, "attr")] and \
Fred Draked2909c92002-09-12 17:02:01 +0000358 (attrs.getQNames() == [] or attrs.getQNames() == ["ns:attr"]) and \
Lars Gustäbelab647872000-09-24 18:40:52 +0000359 len(attrs) == 1 and \
360 attrs.has_key((ns_uri, "attr")) and \
361 attrs.keys() == [(ns_uri, "attr")] and \
362 attrs.get((ns_uri, "attr")) == "val" and \
363 attrs.get((ns_uri, "attr"), 25) == "val" and \
364 attrs.items() == [((ns_uri, "attr"), "val")] and \
365 attrs.values() == ["val"] and \
366 attrs.getValue((ns_uri, "attr")) == "val" and \
367 attrs[(ns_uri, "attr")] == "val"
368
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000369# ===== InputSource support
370
Guido van Rossume2ae77b2001-10-24 20:42:55 +0000371xml_test_out = open(findfile("test"+os.extsep+"xml"+os.extsep+"out")).read()
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000372
373def test_expat_inpsource_filename():
374 parser = create_parser()
375 result = StringIO()
376 xmlgen = XMLGenerator(result)
377
378 parser.setContentHandler(xmlgen)
Guido van Rossume2ae77b2001-10-24 20:42:55 +0000379 parser.parse(findfile("test"+os.extsep+"xml"))
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000380
381 return result.getvalue() == xml_test_out
382
383def test_expat_inpsource_sysid():
384 parser = create_parser()
385 result = StringIO()
386 xmlgen = XMLGenerator(result)
387
388 parser.setContentHandler(xmlgen)
Guido van Rossume2ae77b2001-10-24 20:42:55 +0000389 parser.parse(InputSource(findfile("test"+os.extsep+"xml")))
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000390
391 return result.getvalue() == xml_test_out
392
393def test_expat_inpsource_stream():
394 parser = create_parser()
395 result = StringIO()
396 xmlgen = XMLGenerator(result)
397
398 parser.setContentHandler(xmlgen)
399 inpsrc = InputSource()
Guido van Rossume2ae77b2001-10-24 20:42:55 +0000400 inpsrc.setByteStream(open(findfile("test"+os.extsep+"xml")))
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000401 parser.parse(inpsrc)
402
403 return result.getvalue() == xml_test_out
404
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000405# ===== IncrementalParser support
406
407def test_expat_incremental():
408 result = StringIO()
409 xmlgen = XMLGenerator(result)
410 parser = create_parser()
411 parser.setContentHandler(xmlgen)
412
413 parser.feed("<doc>")
414 parser.feed("</doc>")
415 parser.close()
416
417 return result.getvalue() == start + "<doc></doc>"
418
419def test_expat_incremental_reset():
420 result = StringIO()
421 xmlgen = XMLGenerator(result)
422 parser = create_parser()
423 parser.setContentHandler(xmlgen)
424
425 parser.feed("<doc>")
426 parser.feed("text")
427
428 result = StringIO()
429 xmlgen = XMLGenerator(result)
430 parser.setContentHandler(xmlgen)
431 parser.reset()
432
433 parser.feed("<doc>")
434 parser.feed("text")
435 parser.feed("</doc>")
436 parser.close()
437
438 return result.getvalue() == start + "<doc>text</doc>"
439
440# ===== Locator support
441
442def test_expat_locator_noinfo():
443 result = StringIO()
444 xmlgen = XMLGenerator(result)
445 parser = create_parser()
446 parser.setContentHandler(xmlgen)
447
448 parser.feed("<doc>")
449 parser.feed("</doc>")
450 parser.close()
451
Fred Drake132dce22000-12-12 23:11:42 +0000452 return parser.getSystemId() is None and \
453 parser.getPublicId() is None and \
Tim Petersd2bf3b72001-01-18 02:22:22 +0000454 parser.getLineNumber() == 1
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000455
456def test_expat_locator_withinfo():
457 result = StringIO()
458 xmlgen = XMLGenerator(result)
459 parser = create_parser()
460 parser.setContentHandler(xmlgen)
461 parser.parse(findfile("test.xml"))
462
463 return parser.getSystemId() == findfile("test.xml") and \
Fred Drake132dce22000-12-12 23:11:42 +0000464 parser.getPublicId() is None
Lars Gustäbel2fc52942000-10-24 15:35:07 +0000465
Martin v. Löwis80670bc2000-10-06 21:13:23 +0000466
467# ===========================================================================
468#
469# error reporting
470#
471# ===========================================================================
472
473def test_expat_inpsource_location():
474 parser = create_parser()
475 parser.setContentHandler(ContentHandler()) # do nothing
476 source = InputSource()
477 source.setByteStream(StringIO("<foo bar foobar>")) #ill-formed
478 name = "a file name"
479 source.setSystemId(name)
480 try:
481 parser.parse(source)
482 except SAXException, e:
483 return e.getSystemId() == name
484
485def test_expat_incomplete():
486 parser = create_parser()
487 parser.setContentHandler(ContentHandler()) # do nothing
488 try:
489 parser.parse(StringIO("<foo>"))
490 except SAXParseException:
491 return 1 # ok, error found
492 else:
493 return 0
494
Fred Drake6fd0b0d2004-03-20 08:15:30 +0000495def test_sax_parse_exception_str():
496 # pass various values from a locator to the SAXParseException to
497 # make sure that the __str__() doesn't fall apart when None is
498 # passed instead of an integer line and column number
499 #
500 # use "normal" values for the locator:
501 str(SAXParseException("message", None,
502 DummyLocator(1, 1)))
503 # use None for the line number:
504 str(SAXParseException("message", None,
505 DummyLocator(None, 1)))
506 # use None for the column number:
507 str(SAXParseException("message", None,
508 DummyLocator(1, None)))
509 # use None for both:
510 str(SAXParseException("message", None,
511 DummyLocator(None, None)))
512 return 1
513
514class DummyLocator:
515 def __init__(self, lineno, colno):
516 self._lineno = lineno
517 self._colno = colno
518
519 def getPublicId(self):
520 return "pubid"
521
522 def getSystemId(self):
523 return "sysid"
524
525 def getLineNumber(self):
526 return self._lineno
527
528 def getColumnNumber(self):
529 return self._colno
Martin v. Löwis80670bc2000-10-06 21:13:23 +0000530
Lars Gustäbelab647872000-09-24 18:40:52 +0000531# ===========================================================================
532#
533# xmlreader tests
534#
535# ===========================================================================
536
537# ===== AttributesImpl
538
539def verify_empty_attrs(attrs):
540 try:
541 attrs.getValue("attr")
542 gvk = 0
543 except KeyError:
544 gvk = 1
545
546 try:
547 attrs.getValueByQName("attr")
548 gvqk = 0
549 except KeyError:
550 gvqk = 1
551
552 try:
553 attrs.getNameByQName("attr")
554 gnqk = 0
555 except KeyError:
556 gnqk = 1
557
558 try:
559 attrs.getQNameByName("attr")
560 gqnk = 0
561 except KeyError:
562 gqnk = 1
Fred Drake004d5e62000-10-23 17:22:08 +0000563
Lars Gustäbelab647872000-09-24 18:40:52 +0000564 try:
565 attrs["attr"]
566 gik = 0
567 except KeyError:
568 gik = 1
Fred Drake004d5e62000-10-23 17:22:08 +0000569
Lars Gustäbelab647872000-09-24 18:40:52 +0000570 return attrs.getLength() == 0 and \
571 attrs.getNames() == [] and \
572 attrs.getQNames() == [] and \
573 len(attrs) == 0 and \
574 not attrs.has_key("attr") and \
575 attrs.keys() == [] and \
Fred Drake132dce22000-12-12 23:11:42 +0000576 attrs.get("attrs") is None and \
Lars Gustäbelab647872000-09-24 18:40:52 +0000577 attrs.get("attrs", 25) == 25 and \
578 attrs.items() == [] and \
579 attrs.values() == [] and \
580 gvk and gvqk and gnqk and gik and gqnk
581
582def verify_attrs_wattr(attrs):
583 return attrs.getLength() == 1 and \
584 attrs.getNames() == ["attr"] and \
585 attrs.getQNames() == ["attr"] and \
586 len(attrs) == 1 and \
587 attrs.has_key("attr") and \
588 attrs.keys() == ["attr"] and \
589 attrs.get("attr") == "val" and \
590 attrs.get("attr", 25) == "val" and \
591 attrs.items() == [("attr", "val")] and \
592 attrs.values() == ["val"] and \
593 attrs.getValue("attr") == "val" and \
594 attrs.getValueByQName("attr") == "val" and \
595 attrs.getNameByQName("attr") == "attr" and \
596 attrs["attr"] == "val" and \
597 attrs.getQNameByName("attr") == "attr"
598
599def test_attrs_empty():
600 return verify_empty_attrs(AttributesImpl({}))
601
602def test_attrs_wattr():
603 return verify_attrs_wattr(AttributesImpl({"attr" : "val"}))
604
605# ===== AttributesImpl
606
607def verify_empty_nsattrs(attrs):
608 try:
609 attrs.getValue((ns_uri, "attr"))
610 gvk = 0
611 except KeyError:
612 gvk = 1
613
614 try:
615 attrs.getValueByQName("ns:attr")
616 gvqk = 0
617 except KeyError:
618 gvqk = 1
619
620 try:
621 attrs.getNameByQName("ns:attr")
622 gnqk = 0
623 except KeyError:
624 gnqk = 1
625
626 try:
627 attrs.getQNameByName((ns_uri, "attr"))
628 gqnk = 0
629 except KeyError:
630 gqnk = 1
Fred Drake004d5e62000-10-23 17:22:08 +0000631
Lars Gustäbelab647872000-09-24 18:40:52 +0000632 try:
633 attrs[(ns_uri, "attr")]
634 gik = 0
635 except KeyError:
636 gik = 1
Fred Drake004d5e62000-10-23 17:22:08 +0000637
Lars Gustäbelab647872000-09-24 18:40:52 +0000638 return attrs.getLength() == 0 and \
639 attrs.getNames() == [] and \
640 attrs.getQNames() == [] and \
641 len(attrs) == 0 and \
642 not attrs.has_key((ns_uri, "attr")) and \
643 attrs.keys() == [] and \
Fred Drake132dce22000-12-12 23:11:42 +0000644 attrs.get((ns_uri, "attr")) is None and \
Lars Gustäbelab647872000-09-24 18:40:52 +0000645 attrs.get((ns_uri, "attr"), 25) == 25 and \
646 attrs.items() == [] and \
647 attrs.values() == [] and \
648 gvk and gvqk and gnqk and gik and gqnk
649
650def test_nsattrs_empty():
651 return verify_empty_nsattrs(AttributesNSImpl({}, {}))
652
653def test_nsattrs_wattr():
654 attrs = AttributesNSImpl({(ns_uri, "attr") : "val"},
655 {(ns_uri, "attr") : "ns:attr"})
Fred Drake004d5e62000-10-23 17:22:08 +0000656
Lars Gustäbelab647872000-09-24 18:40:52 +0000657 return attrs.getLength() == 1 and \
658 attrs.getNames() == [(ns_uri, "attr")] and \
659 attrs.getQNames() == ["ns:attr"] and \
660 len(attrs) == 1 and \
661 attrs.has_key((ns_uri, "attr")) and \
662 attrs.keys() == [(ns_uri, "attr")] and \
663 attrs.get((ns_uri, "attr")) == "val" and \
664 attrs.get((ns_uri, "attr"), 25) == "val" and \
665 attrs.items() == [((ns_uri, "attr"), "val")] and \
666 attrs.values() == ["val"] and \
667 attrs.getValue((ns_uri, "attr")) == "val" and \
668 attrs.getValueByQName("ns:attr") == "val" and \
669 attrs.getNameByQName("ns:attr") == (ns_uri, "attr") and \
670 attrs[(ns_uri, "attr")] == "val" and \
671 attrs.getQNameByName((ns_uri, "attr")) == "ns:attr"
Fred Drake004d5e62000-10-23 17:22:08 +0000672
Lars Gustäbelab647872000-09-24 18:40:52 +0000673
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000674# During the development of Python 2.5, an attempt to move the "xml"
675# package implementation to a new package ("xmlcore") proved painful.
676# The goal of this change was to allow applications to be able to
677# obtain and rely on behavior in the standard library implementation
678# of the XML support without needing to be concerned about the
679# availability of the PyXML implementation.
680#
681# While the existing import hackery in Lib/xml/__init__.py can cause
682# PyXML's _xmlpus package to supplant the "xml" package, that only
683# works because either implementation uses the "xml" package name for
684# imports.
685#
686# The move resulted in a number of problems related to the fact that
687# the import machinery's "package context" is based on the name that's
688# being imported rather than the __name__ of the actual package
689# containment; it wasn't possible for the "xml" package to be replaced
690# by a simple module that indirected imports to the "xmlcore" package.
691#
692# The following two tests exercised bugs that were introduced in that
693# attempt. Keeping these tests around will help detect problems with
694# other attempts to provide reliable access to the standard library's
695# implementation of the XML support.
696
697def test_sf_1511497():
698 # Bug report: http://www.python.org/sf/1511497
699 import sys
700 old_modules = sys.modules.copy()
701 for modname in sys.modules.keys():
702 if modname.startswith("xml."):
703 del sys.modules[modname]
704 try:
705 import xml.sax.expatreader
706 module = xml.sax.expatreader
707 return module.__name__ == "xml.sax.expatreader"
708 finally:
709 sys.modules.update(old_modules)
710
711def test_sf_1513611():
712 # Bug report: http://www.python.org/sf/1513611
713 sio = StringIO("invalid")
714 parser = make_parser()
715 from xml.sax import SAXParseException
716 try:
717 parser.parse(sio)
718 except SAXParseException:
719 return True
720 else:
721 return False
722
Lars Gustäbel96753b32000-09-24 12:24:24 +0000723# ===== Main program
724
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000725def make_test_output():
726 parser = create_parser()
727 result = StringIO()
728 xmlgen = XMLGenerator(result)
729
730 parser.setContentHandler(xmlgen)
Guido van Rossume2ae77b2001-10-24 20:42:55 +0000731 parser.parse(findfile("test"+os.extsep+"xml"))
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000732
Guido van Rossume2ae77b2001-10-24 20:42:55 +0000733 outf = open(findfile("test"+os.extsep+"xml"+os.extsep+"out"), "w")
Lars Gustäbelb7536d52000-09-24 18:53:56 +0000734 outf.write(result.getvalue())
735 outf.close()
736
Lars Gustäbel96753b32000-09-24 12:24:24 +0000737items = locals().items()
738items.sort()
739for (name, value) in items:
740 if name[ : 5] == "test_":
741 confirm(value(), name)
Michael W. Hudson3bfed9c2004-08-03 10:17:34 +0000742# We delete the items variable so that the assignment to items above
743# doesn't pick up the old value of items (which messes with attempts
744# to find reference leaks).
745del items
Lars Gustäbel96753b32000-09-24 12:24:24 +0000746
Fred Drake32f3add2002-10-28 17:58:48 +0000747if verbose:
748 print "%d tests, %d failures" % (tests, len(failures))
749if failures:
750 raise TestFailed("%d of %d tests failed: %s"
751 % (len(failures), tests, ", ".join(failures)))