~ubuntu-branches/ubuntu/maverick/python3.1/maverick

« back to all changes in this revision

Viewing changes to Lib/test/test_sax.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-03-23 00:01:27 UTC
  • Revision ID: james.westby@ubuntu.com-20090323000127-5fstfxju4ufrhthq
Tags: upstream-3.1~a1+20090322
ImportĀ upstreamĀ versionĀ 3.1~a1+20090322

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# regression test for SAX 2.0            -*- coding: iso-8859-1 -*-
 
2
# $Id: test_sax.py 66203 2008-09-04 02:22:52Z benjamin.peterson $
 
3
 
 
4
from xml.sax import make_parser, ContentHandler, \
 
5
                    SAXException, SAXReaderNotAvailable, SAXParseException
 
6
try:
 
7
    make_parser()
 
8
except SAXReaderNotAvailable:
 
9
    # don't try to test this module if we cannot create a parser
 
10
    raise ImportError("no XML parsers available")
 
11
from xml.sax.saxutils import XMLGenerator, escape, unescape, quoteattr, \
 
12
                             XMLFilterBase
 
13
from xml.sax.expatreader import create_parser
 
14
from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl
 
15
from io import StringIO
 
16
from test.support import findfile, run_unittest
 
17
import unittest
 
18
import os
 
19
 
 
20
ns_uri = "http://www.python.org/xml-ns/saxtest/"
 
21
 
 
22
class XmlTestBase(unittest.TestCase):
 
23
    def verify_empty_attrs(self, attrs):
 
24
        self.assertRaises(KeyError, attrs.getValue, "attr")
 
25
        self.assertRaises(KeyError, attrs.getValueByQName, "attr")
 
26
        self.assertRaises(KeyError, attrs.getNameByQName, "attr")
 
27
        self.assertRaises(KeyError, attrs.getQNameByName, "attr")
 
28
        self.assertRaises(KeyError, attrs.__getitem__, "attr")
 
29
        self.assertEquals(attrs.getLength(), 0)
 
30
        self.assertEquals(attrs.getNames(), [])
 
31
        self.assertEquals(attrs.getQNames(), [])
 
32
        self.assertEquals(len(attrs), 0)
 
33
        self.assertFalse("attr" in attrs)
 
34
        self.assertEquals(list(attrs.keys()), [])
 
35
        self.assertEquals(attrs.get("attrs"), None)
 
36
        self.assertEquals(attrs.get("attrs", 25), 25)
 
37
        self.assertEquals(list(attrs.items()), [])
 
38
        self.assertEquals(list(attrs.values()), [])
 
39
 
 
40
    def verify_empty_nsattrs(self, attrs):
 
41
        self.assertRaises(KeyError, attrs.getValue, (ns_uri, "attr"))
 
42
        self.assertRaises(KeyError, attrs.getValueByQName, "ns:attr")
 
43
        self.assertRaises(KeyError, attrs.getNameByQName, "ns:attr")
 
44
        self.assertRaises(KeyError, attrs.getQNameByName, (ns_uri, "attr"))
 
45
        self.assertRaises(KeyError, attrs.__getitem__, (ns_uri, "attr"))
 
46
        self.assertEquals(attrs.getLength(), 0)
 
47
        self.assertEquals(attrs.getNames(), [])
 
48
        self.assertEquals(attrs.getQNames(), [])
 
49
        self.assertEquals(len(attrs), 0)
 
50
        self.assertFalse((ns_uri, "attr") in attrs)
 
51
        self.assertEquals(list(attrs.keys()), [])
 
52
        self.assertEquals(attrs.get((ns_uri, "attr")), None)
 
53
        self.assertEquals(attrs.get((ns_uri, "attr"), 25), 25)
 
54
        self.assertEquals(list(attrs.items()), [])
 
55
        self.assertEquals(list(attrs.values()), [])
 
56
 
 
57
    def verify_attrs_wattr(self, attrs):
 
58
        self.assertEquals(attrs.getLength(), 1)
 
59
        self.assertEquals(attrs.getNames(), ["attr"])
 
60
        self.assertEquals(attrs.getQNames(), ["attr"])
 
61
        self.assertEquals(len(attrs), 1)
 
62
        self.assertTrue("attr" in attrs)
 
63
        self.assertEquals(list(attrs.keys()), ["attr"])
 
64
        self.assertEquals(attrs.get("attr"), "val")
 
65
        self.assertEquals(attrs.get("attr", 25), "val")
 
66
        self.assertEquals(list(attrs.items()), [("attr", "val")])
 
67
        self.assertEquals(list(attrs.values()), ["val"])
 
68
        self.assertEquals(attrs.getValue("attr"), "val")
 
69
        self.assertEquals(attrs.getValueByQName("attr"), "val")
 
70
        self.assertEquals(attrs.getNameByQName("attr"), "attr")
 
71
        self.assertEquals(attrs["attr"], "val")
 
72
        self.assertEquals(attrs.getQNameByName("attr"), "attr")
 
73
 
 
74
class MakeParserTest(unittest.TestCase):
 
75
    def test_make_parser2(self):
 
76
        # Creating parsers several times in a row should succeed.
 
77
        # Testing this because there have been failures of this kind
 
78
        # before.
 
79
        from xml.sax import make_parser
 
80
        p = make_parser()
 
81
        from xml.sax import make_parser
 
82
        p = make_parser()
 
83
        from xml.sax import make_parser
 
84
        p = make_parser()
 
85
        from xml.sax import make_parser
 
86
        p = make_parser()
 
87
        from xml.sax import make_parser
 
88
        p = make_parser()
 
89
        from xml.sax import make_parser
 
90
        p = make_parser()
 
91
 
 
92
 
 
93
# ===========================================================================
 
94
#
 
95
#   saxutils tests
 
96
#
 
97
# ===========================================================================
 
98
 
 
99
class SaxutilsTest(unittest.TestCase):
 
100
    # ===== escape
 
101
    def test_escape_basic(self):
 
102
        self.assertEquals(escape("Donald Duck & Co"), "Donald Duck & Co")
 
103
 
 
104
    def test_escape_all(self):
 
105
        self.assertEquals(escape("<Donald Duck & Co>"),
 
106
                          "&lt;Donald Duck &amp; Co&gt;")
 
107
 
 
108
    def test_escape_extra(self):
 
109
        self.assertEquals(escape("Hei pļæ½ deg", {"ļæ½" : "&aring;"}),
 
110
                          "Hei p&aring; deg")
 
111
 
 
112
    # ===== unescape
 
113
    def test_unescape_basic(self):
 
114
        self.assertEquals(unescape("Donald Duck &amp; Co"), "Donald Duck & Co")
 
115
 
 
116
    def test_unescape_all(self):
 
117
        self.assertEquals(unescape("&lt;Donald Duck &amp; Co&gt;"),
 
118
                          "<Donald Duck & Co>")
 
119
 
 
120
    def test_unescape_extra(self):
 
121
        self.assertEquals(unescape("Hei pļæ½ deg", {"ļæ½" : "&aring;"}),
 
122
                          "Hei p&aring; deg")
 
123
 
 
124
    def test_unescape_amp_extra(self):
 
125
        self.assertEquals(unescape("&amp;foo;", {"&foo;": "splat"}), "&foo;")
 
126
 
 
127
    # ===== quoteattr
 
128
    def test_quoteattr_basic(self):
 
129
        self.assertEquals(quoteattr("Donald Duck & Co"),
 
130
                          '"Donald Duck &amp; Co"')
 
131
 
 
132
    def test_single_quoteattr(self):
 
133
        self.assertEquals(quoteattr('Includes "double" quotes'),
 
134
                          '\'Includes "double" quotes\'')
 
135
 
 
136
    def test_double_quoteattr(self):
 
137
        self.assertEquals(quoteattr("Includes 'single' quotes"),
 
138
                          "\"Includes 'single' quotes\"")
 
139
 
 
140
    def test_single_double_quoteattr(self):
 
141
        self.assertEquals(quoteattr("Includes 'single' and \"double\" quotes"),
 
142
                    "\"Includes 'single' and &quot;double&quot; quotes\"")
 
143
 
 
144
    # ===== make_parser
 
145
    def test_make_parser(self):
 
146
        # Creating a parser should succeed - it should fall back
 
147
        # to the expatreader
 
148
        p = make_parser(['xml.parsers.no_such_parser'])
 
149
 
 
150
 
 
151
# ===== XMLGenerator
 
152
 
 
153
start = '<?xml version="1.0" encoding="iso-8859-1"?>\n'
 
154
 
 
155
class XmlgenTest(unittest.TestCase):
 
156
    def test_xmlgen_basic(self):
 
157
        result = StringIO()
 
158
        gen = XMLGenerator(result)
 
159
        gen.startDocument()
 
160
        gen.startElement("doc", {})
 
161
        gen.endElement("doc")
 
162
        gen.endDocument()
 
163
 
 
164
        self.assertEquals(result.getvalue(), start + "<doc></doc>")
 
165
 
 
166
    def test_xmlgen_content(self):
 
167
        result = StringIO()
 
168
        gen = XMLGenerator(result)
 
169
 
 
170
        gen.startDocument()
 
171
        gen.startElement("doc", {})
 
172
        gen.characters("huhei")
 
173
        gen.endElement("doc")
 
174
        gen.endDocument()
 
175
 
 
176
        self.assertEquals(result.getvalue(), start + "<doc>huhei</doc>")
 
177
 
 
178
    def test_xmlgen_pi(self):
 
179
        result = StringIO()
 
180
        gen = XMLGenerator(result)
 
181
 
 
182
        gen.startDocument()
 
183
        gen.processingInstruction("test", "data")
 
184
        gen.startElement("doc", {})
 
185
        gen.endElement("doc")
 
186
        gen.endDocument()
 
187
 
 
188
        self.assertEquals(result.getvalue(), start + "<?test data?><doc></doc>")
 
189
 
 
190
    def test_xmlgen_content_escape(self):
 
191
        result = StringIO()
 
192
        gen = XMLGenerator(result)
 
193
 
 
194
        gen.startDocument()
 
195
        gen.startElement("doc", {})
 
196
        gen.characters("<huhei&")
 
197
        gen.endElement("doc")
 
198
        gen.endDocument()
 
199
 
 
200
        self.assertEquals(result.getvalue(),
 
201
            start + "<doc>&lt;huhei&amp;</doc>")
 
202
 
 
203
    def test_xmlgen_attr_escape(self):
 
204
        result = StringIO()
 
205
        gen = XMLGenerator(result)
 
206
 
 
207
        gen.startDocument()
 
208
        gen.startElement("doc", {"a": '"'})
 
209
        gen.startElement("e", {"a": "'"})
 
210
        gen.endElement("e")
 
211
        gen.startElement("e", {"a": "'\""})
 
212
        gen.endElement("e")
 
213
        gen.startElement("e", {"a": "\n\r\t"})
 
214
        gen.endElement("e")
 
215
        gen.endElement("doc")
 
216
        gen.endDocument()
 
217
 
 
218
        self.assertEquals(result.getvalue(), start +
 
219
            ("<doc a='\"'><e a=\"'\"></e>"
 
220
             "<e a=\"'&quot;\"></e>"
 
221
             "<e a=\"&#10;&#13;&#9;\"></e></doc>"))
 
222
 
 
223
    def test_xmlgen_ignorable(self):
 
224
        result = StringIO()
 
225
        gen = XMLGenerator(result)
 
226
 
 
227
        gen.startDocument()
 
228
        gen.startElement("doc", {})
 
229
        gen.ignorableWhitespace(" ")
 
230
        gen.endElement("doc")
 
231
        gen.endDocument()
 
232
 
 
233
        self.assertEquals(result.getvalue(), start + "<doc> </doc>")
 
234
 
 
235
    def test_xmlgen_ns(self):
 
236
        result = StringIO()
 
237
        gen = XMLGenerator(result)
 
238
 
 
239
        gen.startDocument()
 
240
        gen.startPrefixMapping("ns1", ns_uri)
 
241
        gen.startElementNS((ns_uri, "doc"), "ns1:doc", {})
 
242
        # add an unqualified name
 
243
        gen.startElementNS((None, "udoc"), None, {})
 
244
        gen.endElementNS((None, "udoc"), None)
 
245
        gen.endElementNS((ns_uri, "doc"), "ns1:doc")
 
246
        gen.endPrefixMapping("ns1")
 
247
        gen.endDocument()
 
248
 
 
249
        self.assertEquals(result.getvalue(), start + \
 
250
           ('<ns1:doc xmlns:ns1="%s"><udoc></udoc></ns1:doc>' %
 
251
                                         ns_uri))
 
252
 
 
253
    def test_1463026_1(self):
 
254
        result = StringIO()
 
255
        gen = XMLGenerator(result)
 
256
 
 
257
        gen.startDocument()
 
258
        gen.startElementNS((None, 'a'), 'a', {(None, 'b'):'c'})
 
259
        gen.endElementNS((None, 'a'), 'a')
 
260
        gen.endDocument()
 
261
 
 
262
        self.assertEquals(result.getvalue(), start+'<a b="c"></a>')
 
263
 
 
264
    def test_1463026_2(self):
 
265
        result = StringIO()
 
266
        gen = XMLGenerator(result)
 
267
 
 
268
        gen.startDocument()
 
269
        gen.startPrefixMapping(None, 'qux')
 
270
        gen.startElementNS(('qux', 'a'), 'a', {})
 
271
        gen.endElementNS(('qux', 'a'), 'a')
 
272
        gen.endPrefixMapping(None)
 
273
        gen.endDocument()
 
274
 
 
275
        self.assertEquals(result.getvalue(), start+'<a xmlns="qux"></a>')
 
276
 
 
277
    def test_1463026_3(self):
 
278
        result = StringIO()
 
279
        gen = XMLGenerator(result)
 
280
 
 
281
        gen.startDocument()
 
282
        gen.startPrefixMapping('my', 'qux')
 
283
        gen.startElementNS(('qux', 'a'), 'a', {(None, 'b'):'c'})
 
284
        gen.endElementNS(('qux', 'a'), 'a')
 
285
        gen.endPrefixMapping('my')
 
286
        gen.endDocument()
 
287
 
 
288
        self.assertEquals(result.getvalue(),
 
289
            start+'<my:a xmlns:my="qux" b="c"></my:a>')
 
290
 
 
291
 
 
292
class XMLFilterBaseTest(unittest.TestCase):
 
293
    def test_filter_basic(self):
 
294
        result = StringIO()
 
295
        gen = XMLGenerator(result)
 
296
        filter = XMLFilterBase()
 
297
        filter.setContentHandler(gen)
 
298
 
 
299
        filter.startDocument()
 
300
        filter.startElement("doc", {})
 
301
        filter.characters("content")
 
302
        filter.ignorableWhitespace(" ")
 
303
        filter.endElement("doc")
 
304
        filter.endDocument()
 
305
 
 
306
        self.assertEquals(result.getvalue(), start + "<doc>content </doc>")
 
307
 
 
308
# ===========================================================================
 
309
#
 
310
#   expatreader tests
 
311
#
 
312
# ===========================================================================
 
313
 
 
314
xml_test_out = open(findfile("test.xml.out")).read()
 
315
 
 
316
class ExpatReaderTest(XmlTestBase):
 
317
 
 
318
    # ===== XMLReader support
 
319
 
 
320
    def test_expat_file(self):
 
321
        parser = create_parser()
 
322
        result = StringIO()
 
323
        xmlgen = XMLGenerator(result)
 
324
 
 
325
        parser.setContentHandler(xmlgen)
 
326
        parser.parse(open(findfile("test.xml")))
 
327
 
 
328
        self.assertEquals(result.getvalue(), xml_test_out)
 
329
 
 
330
    # ===== DTDHandler support
 
331
 
 
332
    class TestDTDHandler:
 
333
 
 
334
        def __init__(self):
 
335
            self._notations = []
 
336
            self._entities  = []
 
337
 
 
338
        def notationDecl(self, name, publicId, systemId):
 
339
            self._notations.append((name, publicId, systemId))
 
340
 
 
341
        def unparsedEntityDecl(self, name, publicId, systemId, ndata):
 
342
            self._entities.append((name, publicId, systemId, ndata))
 
343
 
 
344
    def test_expat_dtdhandler(self):
 
345
        parser = create_parser()
 
346
        handler = self.TestDTDHandler()
 
347
        parser.setDTDHandler(handler)
 
348
 
 
349
        parser.feed('<!DOCTYPE doc [\n')
 
350
        parser.feed('  <!ENTITY img SYSTEM "expat.gif" NDATA GIF>\n')
 
351
        parser.feed('  <!NOTATION GIF PUBLIC "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN">\n')
 
352
        parser.feed(']>\n')
 
353
        parser.feed('<doc></doc>')
 
354
        parser.close()
 
355
 
 
356
        self.assertEquals(handler._notations,
 
357
            [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)])
 
358
        self.assertEquals(handler._entities, [("img", None, "expat.gif", "GIF")])
 
359
 
 
360
    # ===== EntityResolver support
 
361
 
 
362
    class TestEntityResolver:
 
363
 
 
364
        def resolveEntity(self, publicId, systemId):
 
365
            inpsrc = InputSource()
 
366
            inpsrc.setByteStream(StringIO("<entity/>"))
 
367
            return inpsrc
 
368
 
 
369
    def test_expat_entityresolver(self):
 
370
        parser = create_parser()
 
371
        parser.setEntityResolver(self.TestEntityResolver())
 
372
        result = StringIO()
 
373
        parser.setContentHandler(XMLGenerator(result))
 
374
 
 
375
        parser.feed('<!DOCTYPE doc [\n')
 
376
        parser.feed('  <!ENTITY test SYSTEM "whatever">\n')
 
377
        parser.feed(']>\n')
 
378
        parser.feed('<doc>&test;</doc>')
 
379
        parser.close()
 
380
 
 
381
        self.assertEquals(result.getvalue(), start +
 
382
                          "<doc><entity></entity></doc>")
 
383
 
 
384
    # ===== Attributes support
 
385
 
 
386
    class AttrGatherer(ContentHandler):
 
387
 
 
388
        def startElement(self, name, attrs):
 
389
            self._attrs = attrs
 
390
 
 
391
        def startElementNS(self, name, qname, attrs):
 
392
            self._attrs = attrs
 
393
 
 
394
    def test_expat_attrs_empty(self):
 
395
        parser = create_parser()
 
396
        gather = self.AttrGatherer()
 
397
        parser.setContentHandler(gather)
 
398
 
 
399
        parser.feed("<doc/>")
 
400
        parser.close()
 
401
 
 
402
        self.verify_empty_attrs(gather._attrs)
 
403
 
 
404
    def test_expat_attrs_wattr(self):
 
405
        parser = create_parser()
 
406
        gather = self.AttrGatherer()
 
407
        parser.setContentHandler(gather)
 
408
 
 
409
        parser.feed("<doc attr='val'/>")
 
410
        parser.close()
 
411
 
 
412
        self.verify_attrs_wattr(gather._attrs)
 
413
 
 
414
    def test_expat_nsattrs_empty(self):
 
415
        parser = create_parser(1)
 
416
        gather = self.AttrGatherer()
 
417
        parser.setContentHandler(gather)
 
418
 
 
419
        parser.feed("<doc/>")
 
420
        parser.close()
 
421
 
 
422
        self.verify_empty_nsattrs(gather._attrs)
 
423
 
 
424
    def test_expat_nsattrs_wattr(self):
 
425
        parser = create_parser(1)
 
426
        gather = self.AttrGatherer()
 
427
        parser.setContentHandler(gather)
 
428
 
 
429
        parser.feed("<doc xmlns:ns='%s' ns:attr='val'/>" % ns_uri)
 
430
        parser.close()
 
431
 
 
432
        attrs = gather._attrs
 
433
 
 
434
        self.assertEquals(attrs.getLength(), 1)
 
435
        self.assertEquals(attrs.getNames(), [(ns_uri, "attr")])
 
436
        self.assertTrue((attrs.getQNames() == [] or
 
437
                         attrs.getQNames() == ["ns:attr"]))
 
438
        self.assertEquals(len(attrs), 1)
 
439
        self.assertTrue((ns_uri, "attr") in attrs)
 
440
        self.assertEquals(attrs.get((ns_uri, "attr")), "val")
 
441
        self.assertEquals(attrs.get((ns_uri, "attr"), 25), "val")
 
442
        self.assertEquals(list(attrs.items()), [((ns_uri, "attr"), "val")])
 
443
        self.assertEquals(list(attrs.values()), ["val"])
 
444
        self.assertEquals(attrs.getValue((ns_uri, "attr")), "val")
 
445
        self.assertEquals(attrs[(ns_uri, "attr")], "val")
 
446
 
 
447
    # ===== InputSource support
 
448
 
 
449
    def test_expat_inpsource_filename(self):
 
450
        parser = create_parser()
 
451
        result = StringIO()
 
452
        xmlgen = XMLGenerator(result)
 
453
 
 
454
        parser.setContentHandler(xmlgen)
 
455
        parser.parse(findfile("test.xml"))
 
456
 
 
457
        self.assertEquals(result.getvalue(), xml_test_out)
 
458
 
 
459
    def test_expat_inpsource_sysid(self):
 
460
        parser = create_parser()
 
461
        result = StringIO()
 
462
        xmlgen = XMLGenerator(result)
 
463
 
 
464
        parser.setContentHandler(xmlgen)
 
465
        parser.parse(InputSource(findfile("test.xml")))
 
466
 
 
467
        self.assertEquals(result.getvalue(), xml_test_out)
 
468
 
 
469
    def test_expat_inpsource_stream(self):
 
470
        parser = create_parser()
 
471
        result = StringIO()
 
472
        xmlgen = XMLGenerator(result)
 
473
 
 
474
        parser.setContentHandler(xmlgen)
 
475
        inpsrc = InputSource()
 
476
        inpsrc.setByteStream(open(findfile("test.xml")))
 
477
        parser.parse(inpsrc)
 
478
 
 
479
        self.assertEquals(result.getvalue(), xml_test_out)
 
480
 
 
481
    # ===== IncrementalParser support
 
482
 
 
483
    def test_expat_incremental(self):
 
484
        result = StringIO()
 
485
        xmlgen = XMLGenerator(result)
 
486
        parser = create_parser()
 
487
        parser.setContentHandler(xmlgen)
 
488
 
 
489
        parser.feed("<doc>")
 
490
        parser.feed("</doc>")
 
491
        parser.close()
 
492
 
 
493
        self.assertEquals(result.getvalue(), start + "<doc></doc>")
 
494
 
 
495
    def test_expat_incremental_reset(self):
 
496
        result = StringIO()
 
497
        xmlgen = XMLGenerator(result)
 
498
        parser = create_parser()
 
499
        parser.setContentHandler(xmlgen)
 
500
 
 
501
        parser.feed("<doc>")
 
502
        parser.feed("text")
 
503
 
 
504
        result = StringIO()
 
505
        xmlgen = XMLGenerator(result)
 
506
        parser.setContentHandler(xmlgen)
 
507
        parser.reset()
 
508
 
 
509
        parser.feed("<doc>")
 
510
        parser.feed("text")
 
511
        parser.feed("</doc>")
 
512
        parser.close()
 
513
 
 
514
        self.assertEquals(result.getvalue(), start + "<doc>text</doc>")
 
515
 
 
516
    # ===== Locator support
 
517
 
 
518
    def test_expat_locator_noinfo(self):
 
519
        result = StringIO()
 
520
        xmlgen = XMLGenerator(result)
 
521
        parser = create_parser()
 
522
        parser.setContentHandler(xmlgen)
 
523
 
 
524
        parser.feed("<doc>")
 
525
        parser.feed("</doc>")
 
526
        parser.close()
 
527
 
 
528
        self.assertEquals(parser.getSystemId(), None)
 
529
        self.assertEquals(parser.getPublicId(), None)
 
530
        self.assertEquals(parser.getLineNumber(), 1)
 
531
 
 
532
    def test_expat_locator_withinfo(self):
 
533
        result = StringIO()
 
534
        xmlgen = XMLGenerator(result)
 
535
        parser = create_parser()
 
536
        parser.setContentHandler(xmlgen)
 
537
        parser.parse(findfile("test.xml"))
 
538
 
 
539
        self.assertEquals(parser.getSystemId(), findfile("test.xml"))
 
540
        self.assertEquals(parser.getPublicId(), None)
 
541
 
 
542
 
 
543
# ===========================================================================
 
544
#
 
545
#   error reporting
 
546
#
 
547
# ===========================================================================
 
548
 
 
549
class ErrorReportingTest(unittest.TestCase):
 
550
    def test_expat_inpsource_location(self):
 
551
        parser = create_parser()
 
552
        parser.setContentHandler(ContentHandler()) # do nothing
 
553
        source = InputSource()
 
554
        source.setByteStream(StringIO("<foo bar foobar>"))   #ill-formed
 
555
        name = "a file name"
 
556
        source.setSystemId(name)
 
557
        try:
 
558
            parser.parse(source)
 
559
            self.fail()
 
560
        except SAXException as e:
 
561
            self.assertEquals(e.getSystemId(), name)
 
562
 
 
563
    def test_expat_incomplete(self):
 
564
        parser = create_parser()
 
565
        parser.setContentHandler(ContentHandler()) # do nothing
 
566
        self.assertRaises(SAXParseException, parser.parse, StringIO("<foo>"))
 
567
 
 
568
    def test_sax_parse_exception_str(self):
 
569
        # pass various values from a locator to the SAXParseException to
 
570
        # make sure that the __str__() doesn't fall apart when None is
 
571
        # passed instead of an integer line and column number
 
572
        #
 
573
        # use "normal" values for the locator:
 
574
        str(SAXParseException("message", None,
 
575
                              self.DummyLocator(1, 1)))
 
576
        # use None for the line number:
 
577
        str(SAXParseException("message", None,
 
578
                              self.DummyLocator(None, 1)))
 
579
        # use None for the column number:
 
580
        str(SAXParseException("message", None,
 
581
                              self.DummyLocator(1, None)))
 
582
        # use None for both:
 
583
        str(SAXParseException("message", None,
 
584
                              self.DummyLocator(None, None)))
 
585
 
 
586
    class DummyLocator:
 
587
        def __init__(self, lineno, colno):
 
588
            self._lineno = lineno
 
589
            self._colno = colno
 
590
 
 
591
        def getPublicId(self):
 
592
            return "pubid"
 
593
 
 
594
        def getSystemId(self):
 
595
            return "sysid"
 
596
 
 
597
        def getLineNumber(self):
 
598
            return self._lineno
 
599
 
 
600
        def getColumnNumber(self):
 
601
            return self._colno
 
602
 
 
603
# ===========================================================================
 
604
#
 
605
#   xmlreader tests
 
606
#
 
607
# ===========================================================================
 
608
 
 
609
class XmlReaderTest(XmlTestBase):
 
610
 
 
611
    # ===== AttributesImpl
 
612
    def test_attrs_empty(self):
 
613
        self.verify_empty_attrs(AttributesImpl({}))
 
614
 
 
615
    def test_attrs_wattr(self):
 
616
        self.verify_attrs_wattr(AttributesImpl({"attr" : "val"}))
 
617
 
 
618
    def test_nsattrs_empty(self):
 
619
        self.verify_empty_nsattrs(AttributesNSImpl({}, {}))
 
620
 
 
621
    def test_nsattrs_wattr(self):
 
622
        attrs = AttributesNSImpl({(ns_uri, "attr") : "val"},
 
623
                                 {(ns_uri, "attr") : "ns:attr"})
 
624
 
 
625
        self.assertEquals(attrs.getLength(), 1)
 
626
        self.assertEquals(attrs.getNames(), [(ns_uri, "attr")])
 
627
        self.assertEquals(attrs.getQNames(), ["ns:attr"])
 
628
        self.assertEquals(len(attrs), 1)
 
629
        self.assertTrue((ns_uri, "attr") in attrs)
 
630
        self.assertEquals(list(attrs.keys()), [(ns_uri, "attr")])
 
631
        self.assertEquals(attrs.get((ns_uri, "attr")), "val")
 
632
        self.assertEquals(attrs.get((ns_uri, "attr"), 25), "val")
 
633
        self.assertEquals(list(attrs.items()), [((ns_uri, "attr"), "val")])
 
634
        self.assertEquals(list(attrs.values()), ["val"])
 
635
        self.assertEquals(attrs.getValue((ns_uri, "attr")), "val")
 
636
        self.assertEquals(attrs.getValueByQName("ns:attr"), "val")
 
637
        self.assertEquals(attrs.getNameByQName("ns:attr"), (ns_uri, "attr"))
 
638
        self.assertEquals(attrs[(ns_uri, "attr")], "val")
 
639
        self.assertEquals(attrs.getQNameByName((ns_uri, "attr")), "ns:attr")
 
640
 
 
641
 
 
642
    # During the development of Python 2.5, an attempt to move the "xml"
 
643
    # package implementation to a new package ("xmlcore") proved painful.
 
644
    # The goal of this change was to allow applications to be able to
 
645
    # obtain and rely on behavior in the standard library implementation
 
646
    # of the XML support without needing to be concerned about the
 
647
    # availability of the PyXML implementation.
 
648
    #
 
649
    # While the existing import hackery in Lib/xml/__init__.py can cause
 
650
    # PyXML's _xmlpus package to supplant the "xml" package, that only
 
651
    # works because either implementation uses the "xml" package name for
 
652
    # imports.
 
653
    #
 
654
    # The move resulted in a number of problems related to the fact that
 
655
    # the import machinery's "package context" is based on the name that's
 
656
    # being imported rather than the __name__ of the actual package
 
657
    # containment; it wasn't possible for the "xml" package to be replaced
 
658
    # by a simple module that indirected imports to the "xmlcore" package.
 
659
    #
 
660
    # The following two tests exercised bugs that were introduced in that
 
661
    # attempt.  Keeping these tests around will help detect problems with
 
662
    # other attempts to provide reliable access to the standard library's
 
663
    # implementation of the XML support.
 
664
 
 
665
    def test_sf_1511497(self):
 
666
        # Bug report: http://www.python.org/sf/1511497
 
667
        import sys
 
668
        old_modules = sys.modules.copy()
 
669
        for modname in list(sys.modules.keys()):
 
670
            if modname.startswith("xml."):
 
671
                del sys.modules[modname]
 
672
        try:
 
673
            import xml.sax.expatreader
 
674
            module = xml.sax.expatreader
 
675
            self.assertEquals(module.__name__, "xml.sax.expatreader")
 
676
        finally:
 
677
            sys.modules.update(old_modules)
 
678
 
 
679
    def test_sf_1513611(self):
 
680
        # Bug report: http://www.python.org/sf/1513611
 
681
        sio = StringIO("invalid")
 
682
        parser = make_parser()
 
683
        from xml.sax import SAXParseException
 
684
        self.assertRaises(SAXParseException, parser.parse, sio)
 
685
 
 
686
 
 
687
def test_main():
 
688
    run_unittest(MakeParserTest,
 
689
                 SaxutilsTest,
 
690
                 XmlgenTest,
 
691
                 ExpatReaderTest,
 
692
                 ErrorReportingTest,
 
693
                 XmlReaderTest)
 
694
 
 
695
if __name__ == "__main__":
 
696
    test_main()