| Home | Trees | Indices | Help |
|
|---|
|
|
1 # -*- coding: utf-8 -*-
2
3 """
4 Tests specific to the extended etree API
5
6 Tests that apply to the general ElementTree API should go into
7 test_elementtree
8 """
9
10 import os.path
11 import unittest
12 import copy
13 import sys
14 import re
15 import operator
16 import tempfile
17 import gzip
18
19 this_dir = os.path.dirname(__file__)
20 if this_dir not in sys.path:
21 sys.path.insert(0, this_dir) # needed for Py3
22
23 from common_imports import etree, StringIO, BytesIO, HelperTestCase, fileInTestDir, read_file
24 from common_imports import SillyFileLike, LargeFileLikeUnicode, doctest, make_doctest
25 from common_imports import canonicalize, sorted, _str, _bytes
26
27 print("")
28 print("TESTED VERSION: %s" % etree.__version__)
29 print(" Python: " + repr(sys.version_info))
30 print(" lxml.etree: " + repr(etree.LXML_VERSION))
31 print(" libxml used: " + repr(etree.LIBXML_VERSION))
32 print(" libxml compiled: " + repr(etree.LIBXML_COMPILED_VERSION))
33 print(" libxslt used: " + repr(etree.LIBXSLT_VERSION))
34 print(" libxslt compiled: " + repr(etree.LIBXSLT_COMPILED_VERSION))
35 print("")
36
37 try:
38 _unicode = unicode
39 except NameError:
40 # Python 3
41 _unicode = str
42
44 """Tests only for etree, not ElementTree"""
45 etree = etree
46
48 self.assert_(isinstance(etree.__version__, _unicode))
49 self.assert_(isinstance(etree.LXML_VERSION, tuple))
50 self.assertEqual(len(etree.LXML_VERSION), 4)
51 self.assert_(isinstance(etree.LXML_VERSION[0], int))
52 self.assert_(isinstance(etree.LXML_VERSION[1], int))
53 self.assert_(isinstance(etree.LXML_VERSION[2], int))
54 self.assert_(isinstance(etree.LXML_VERSION[3], int))
55 self.assert_(etree.__version__.startswith(
56 str(etree.LXML_VERSION[0])))
57
59 if hasattr(self.etree, '__pyx_capi__'):
60 # newer Pyrex compatible C-API
61 self.assert_(isinstance(self.etree.__pyx_capi__, dict))
62 self.assert_(len(self.etree.__pyx_capi__) > 0)
63 else:
64 # older C-API mechanism
65 self.assert_(hasattr(self.etree, '_import_c_api'))
66
68 Element = self.etree.Element
69 el = Element('name')
70 self.assertEquals(el.tag, 'name')
71 el = Element('{}name')
72 self.assertEquals(el.tag, 'name')
73
75 Element = self.etree.Element
76 el = Element('name')
77 self.assertRaises(ValueError, Element, '{}')
78 self.assertRaises(ValueError, setattr, el, 'tag', '{}')
79
80 self.assertRaises(ValueError, Element, '{test}')
81 self.assertRaises(ValueError, setattr, el, 'tag', '{test}')
82
84 Element = self.etree.Element
85 self.assertRaises(ValueError, Element, 'p:name')
86 self.assertRaises(ValueError, Element, '{test}p:name')
87
88 el = Element('name')
89 self.assertRaises(ValueError, setattr, el, 'tag', 'p:name')
90
92 Element = self.etree.Element
93 self.assertRaises(ValueError, Element, "p'name")
94 self.assertRaises(ValueError, Element, 'p"name')
95
96 self.assertRaises(ValueError, Element, "{test}p'name")
97 self.assertRaises(ValueError, Element, '{test}p"name')
98
99 el = Element('name')
100 self.assertRaises(ValueError, setattr, el, 'tag', "p'name")
101 self.assertRaises(ValueError, setattr, el, 'tag', 'p"name')
102
104 Element = self.etree.Element
105 self.assertRaises(ValueError, Element, ' name ')
106 self.assertRaises(ValueError, Element, 'na me')
107 self.assertRaises(ValueError, Element, '{test} name')
108
109 el = Element('name')
110 self.assertRaises(ValueError, setattr, el, 'tag', ' name ')
111
113 Element = self.etree.Element
114 SubElement = self.etree.SubElement
115
116 el = Element('name')
117 self.assertRaises(ValueError, SubElement, el, '{}')
118 self.assertRaises(ValueError, SubElement, el, '{test}')
119
121 Element = self.etree.Element
122 SubElement = self.etree.SubElement
123
124 el = Element('name')
125 self.assertRaises(ValueError, SubElement, el, 'p:name')
126 self.assertRaises(ValueError, SubElement, el, '{test}p:name')
127
129 Element = self.etree.Element
130 SubElement = self.etree.SubElement
131
132 el = Element('name')
133 self.assertRaises(ValueError, SubElement, el, "p'name")
134 self.assertRaises(ValueError, SubElement, el, "{test}p'name")
135
136 self.assertRaises(ValueError, SubElement, el, 'p"name')
137 self.assertRaises(ValueError, SubElement, el, '{test}p"name')
138
140 Element = self.etree.Element
141 SubElement = self.etree.SubElement
142
143 el = Element('name')
144 self.assertRaises(ValueError, SubElement, el, ' name ')
145 self.assertRaises(ValueError, SubElement, el, 'na me')
146 self.assertRaises(ValueError, SubElement, el, '{test} name')
147
149 Element = self.etree.Element
150 SubElement = self.etree.SubElement
151
152 el = Element('name')
153 self.assertRaises(ValueError, SubElement, el, 'name', {'a b c' : 'abc'})
154 self.assertRaises(ValueError, SubElement, el, 'name', {'a' : 'a\0\n'})
155 self.assertEquals(0, len(el))
156
158 QName = self.etree.QName
159 self.assertRaises(ValueError, QName, '')
160 self.assertRaises(ValueError, QName, 'test', '')
161
163 QName = self.etree.QName
164 self.assertRaises(ValueError, QName, 'p:name')
165 self.assertRaises(ValueError, QName, 'test', 'p:name')
166
168 QName = self.etree.QName
169 self.assertRaises(ValueError, QName, ' name ')
170 self.assertRaises(ValueError, QName, 'na me')
171 self.assertRaises(ValueError, QName, 'test', ' name')
172
174 # ET doesn't have namespace/localname properties on QNames
175 QName = self.etree.QName
176 namespace, localname = 'http://myns', 'a'
177 qname = QName(namespace, localname)
178 self.assertEquals(namespace, qname.namespace)
179 self.assertEquals(localname, qname.localname)
180
182 # ET doesn't have namespace/localname properties on QNames
183 QName = self.etree.QName
184 qname1 = QName('http://myns', 'a')
185 a = self.etree.Element(qname1, nsmap={'p' : 'http://myns'})
186
187 qname2 = QName(a)
188 self.assertEquals(a.tag, qname1.text)
189 self.assertEquals(qname1.text, qname2.text)
190 self.assertEquals(qname1, qname2)
191
193 # ET doesn't resove QNames as text values
194 etree = self.etree
195 qname = etree.QName('http://myns', 'a')
196 a = etree.Element(qname, nsmap={'p' : 'http://myns'})
197 a.text = qname
198
199 self.assertEquals("p:a", a.text)
200
202 etree = self.etree
203 self.assertRaises(ValueError,
204 etree.Element, "root", nsmap={'"' : 'testns'})
205 self.assertRaises(ValueError,
206 etree.Element, "root", nsmap={'&' : 'testns'})
207 self.assertRaises(ValueError,
208 etree.Element, "root", nsmap={'a:b' : 'testns'})
209
211 # ET in Py 3.x has no "attrib.has_key()" method
212 XML = self.etree.XML
213
214 root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
215 self.assertEquals(
216 True, root.attrib.has_key('bar'))
217 self.assertEquals(
218 False, root.attrib.has_key('baz'))
219 self.assertEquals(
220 False, root.attrib.has_key('hah'))
221 self.assertEquals(
222 True,
223 root.attrib.has_key('{http://ns.codespeak.net/test}baz'))
224
226 Element = self.etree.Element
227 root = Element("root")
228 root.set("attr", "TEST")
229 self.assertEquals("TEST", root.get("attr"))
230
232 # ElementTree accepts arbitrary attribute values
233 # lxml.etree allows only strings
234 Element = self.etree.Element
235 root = Element("root")
236 self.assertRaises(TypeError, root.set, "newattr", 5)
237 self.assertRaises(TypeError, root.set, "newattr", None)
238
240 XML = self.etree.XML
241 xml = _bytes('<test a="5" b="10" c="20"><x a="4" b="2"/></test>')
242
243 root = XML(xml)
244 self.etree.strip_attributes(root, 'a')
245 self.assertEquals(_bytes('<test b="10" c="20"><x b="2"></x></test>'),
246 self._writeElement(root))
247
248 root = XML(xml)
249 self.etree.strip_attributes(root, 'b', 'c')
250 self.assertEquals(_bytes('<test a="5"><x a="4"></x></test>'),
251 self._writeElement(root))
252
254 XML = self.etree.XML
255 xml = _bytes('<test xmlns:n="http://test/ns" a="6" b="10" c="20" n:a="5"><x a="4" n:b="2"/></test>')
256
257 root = XML(xml)
258 self.etree.strip_attributes(root, 'a')
259 self.assertEquals(
260 _bytes('<test xmlns:n="http://test/ns" b="10" c="20" n:a="5"><x n:b="2"></x></test>'),
261 self._writeElement(root))
262
263 root = XML(xml)
264 self.etree.strip_attributes(root, '{http://test/ns}a', 'c')
265 self.assertEquals(
266 _bytes('<test xmlns:n="http://test/ns" a="6" b="10"><x a="4" n:b="2"></x></test>'),
267 self._writeElement(root))
268
269 root = XML(xml)
270 self.etree.strip_attributes(root, '{http://test/ns}*')
271 self.assertEquals(
272 _bytes('<test xmlns:n="http://test/ns" a="6" b="10" c="20"><x a="4"></x></test>'),
273 self._writeElement(root))
274
276 XML = self.etree.XML
277 xml = _bytes('<test><a><b><c/></b></a><x><a><b/><c/></a></x></test>')
278
279 root = XML(xml)
280 self.etree.strip_elements(root, 'a')
281 self.assertEquals(_bytes('<test><x></x></test>'),
282 self._writeElement(root))
283
284 root = XML(xml)
285 self.etree.strip_elements(root, 'b', 'c', 'X', 'Y', 'Z')
286 self.assertEquals(_bytes('<test><a></a><x><a></a></x></test>'),
287 self._writeElement(root))
288
289 root = XML(xml)
290 self.etree.strip_elements(root, 'c')
291 self.assertEquals(_bytes('<test><a><b></b></a><x><a><b></b></a></x></test>'),
292 self._writeElement(root))
293
295 XML = self.etree.XML
296 xml = _bytes('<test>TEST<n:a xmlns:n="urn:a">A<b>B<c xmlns="urn:c"/>C</b>BT</n:a>AT<x>X<a>A<b xmlns="urn:a"/>BT<c xmlns="urn:x"/>CT</a>AT</x>XT</test>')
297
298 root = XML(xml)
299 self.etree.strip_elements(root, 'a')
300 self.assertEquals(_bytes('<test>TEST<n:a xmlns:n="urn:a">A<b>B<c xmlns="urn:c"></c>C</b>BT</n:a>AT<x>X</x>XT</test>'),
301 self._writeElement(root))
302
303 root = XML(xml)
304 self.etree.strip_elements(root, '{urn:a}b', 'c')
305 self.assertEquals(_bytes('<test>TEST<n:a xmlns:n="urn:a">A<b>B<c xmlns="urn:c"></c>C</b>BT</n:a>AT<x>X<a>A<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
306 self._writeElement(root))
307
308 root = XML(xml)
309 self.etree.strip_elements(root, '{urn:a}*', 'c')
310 self.assertEquals(_bytes('<test>TEST<x>X<a>A<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
311 self._writeElement(root))
312
313 root = XML(xml)
314 self.etree.strip_elements(root, '{urn:a}*', 'c', with_tail=False)
315 self.assertEquals(_bytes('<test>TESTAT<x>X<a>ABT<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
316 self._writeElement(root))
317
336
362
389
415
434
447
449 # lxml.etree separates target and text
450 Element = self.etree.Element
451 SubElement = self.etree.SubElement
452 ProcessingInstruction = self.etree.ProcessingInstruction
453
454 a = Element('a')
455 a.append(ProcessingInstruction('foo', 'some more text'))
456 self.assertEquals(a[0].target, 'foo')
457 self.assertEquals(a[0].text, 'some more text')
458
460 XML = self.etree.XML
461 root = XML(_bytes("<test><?mypi my test ?></test>"))
462 self.assertEquals(root[0].target, "mypi")
463 self.assertEquals(root[0].text, "my test ")
464
466 XML = self.etree.XML
467 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>"))
468 self.assertEquals(root[0].target, "mypi")
469 self.assertEquals(root[0].get('my'), "1")
470 self.assertEquals(root[0].get('test'), " abc ")
471 self.assertEquals(root[0].get('quotes'), "' '")
472 self.assertEquals(root[0].get('only'), None)
473 self.assertEquals(root[0].get('names'), None)
474 self.assertEquals(root[0].get('nope'), None)
475
477 XML = self.etree.XML
478 root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>"))
479 self.assertEquals(root[0].target, "mypi")
480 self.assertEquals(root[0].attrib['my'], "1")
481 self.assertEquals(root[0].attrib['test'], " abc ")
482 self.assertEquals(root[0].attrib['quotes'], "' '")
483 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'only')
484 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'names')
485 self.assertRaises(KeyError, root[0].attrib.__getitem__, 'nope')
486
488 # previously caused a crash
489 ProcessingInstruction = self.etree.ProcessingInstruction
490
491 a = ProcessingInstruction("PI", "ONE")
492 b = copy.deepcopy(a)
493 b.text = "ANOTHER"
494
495 self.assertEquals('ONE', a.text)
496 self.assertEquals('ANOTHER', b.text)
497
499 XML = self.etree.XML
500 tostring = self.etree.tostring
501 root = XML(_bytes("<?mypi my test ?><test/><!--comment -->"))
502 tree1 = self.etree.ElementTree(root)
503 self.assertEquals(_bytes("<?mypi my test ?><test/><!--comment -->"),
504 tostring(tree1))
505
506 tree2 = copy.deepcopy(tree1)
507 self.assertEquals(_bytes("<?mypi my test ?><test/><!--comment -->"),
508 tostring(tree2))
509
510 root2 = copy.deepcopy(tree1.getroot())
511 self.assertEquals(_bytes("<test/>"),
512 tostring(root2))
513
515 XML = self.etree.XML
516 tostring = self.etree.tostring
517 xml = _bytes('<!DOCTYPE test [\n<!ENTITY entity "tasty">\n]>\n<test/>')
518 root = XML(xml)
519 tree1 = self.etree.ElementTree(root)
520 self.assertEquals(xml, tostring(tree1))
521
522 tree2 = copy.deepcopy(tree1)
523 self.assertEquals(xml, tostring(tree2))
524
525 root2 = copy.deepcopy(tree1.getroot())
526 self.assertEquals(_bytes("<test/>"),
527 tostring(root2))
528
530 # ElementTree accepts arbitrary attribute values
531 # lxml.etree allows only strings
532 Element = self.etree.Element
533
534 root = Element("root")
535 root.set("attr", "TEST")
536 self.assertEquals("TEST", root.get("attr"))
537 self.assertRaises(TypeError, root.set, "newattr", 5)
538
540 fromstring = self.etree.fromstring
541 tostring = self.etree.tostring
542 XMLParser = self.etree.XMLParser
543
544 xml = _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
545 parser = XMLParser(remove_comments=True)
546 root = fromstring(xml, parser)
547 self.assertEquals(
548 _bytes('<a><b><c/></b></a>'),
549 tostring(root))
550
552 parse = self.etree.parse
553 tostring = self.etree.tostring
554 XMLParser = self.etree.XMLParser
555
556 xml = _bytes('<?test?><a><?A?><b><?B?><c/></b><?C?></a><?tail?>')
557
558 f = BytesIO(xml)
559 tree = parse(f)
560 self.assertEquals(
561 xml,
562 tostring(tree))
563
564 parser = XMLParser(remove_pis=True)
565 tree = parse(f, parser)
566 self.assertEquals(
567 _bytes('<a><b><c/></b></a>'),
568 tostring(tree))
569
571 # ET raises IOError only
572 parse = self.etree.parse
573 self.assertRaises(TypeError, parse, 'notthere.xml', object())
574
576 # ET removes comments
577 iterparse = self.etree.iterparse
578 tostring = self.etree.tostring
579
580 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
581 events = list(iterparse(f))
582 root = events[-1][1]
583 self.assertEquals(3, len(events))
584 self.assertEquals(
585 _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'),
586 tostring(root))
587
589 # ET removes comments
590 iterparse = self.etree.iterparse
591 tostring = self.etree.tostring
592
593 def name(event, el):
594 if event == 'comment':
595 return el.text
596 else:
597 return el.tag
598
599 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
600 events = list(iterparse(f, events=('end', 'comment')))
601 root = events[-1][1]
602 self.assertEquals(6, len(events))
603 self.assertEquals(['A', ' B ', 'c', 'b', 'C', 'a'],
604 [ name(*item) for item in events ])
605 self.assertEquals(
606 _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'),
607 tostring(root))
608
610 # ET removes pis
611 iterparse = self.etree.iterparse
612 tostring = self.etree.tostring
613 ElementTree = self.etree.ElementTree
614
615 def name(event, el):
616 if event == 'pi':
617 return (el.target, el.text)
618 else:
619 return el.tag
620
621 f = BytesIO('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>')
622 events = list(iterparse(f, events=('end', 'pi')))
623 root = events[-2][1]
624 self.assertEquals(8, len(events))
625 self.assertEquals([('pia','a'), ('pib','b'), ('pic','c'), 'c', 'b',
626 ('pid','d'), 'a', ('pie','e')],
627 [ name(*item) for item in events ])
628 self.assertEquals(
629 _bytes('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>'),
630 tostring(ElementTree(root)))
631
633 iterparse = self.etree.iterparse
634 tostring = self.etree.tostring
635
636 f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
637 events = list(iterparse(f, remove_comments=True,
638 events=('end', 'comment')))
639 root = events[-1][1]
640 self.assertEquals(3, len(events))
641 self.assertEquals(['c', 'b', 'a'],
642 [ el.tag for (event, el) in events ])
643 self.assertEquals(
644 _bytes('<a><b><c/></b></a>'),
645 tostring(root))
646
648 iterparse = self.etree.iterparse
649 f = BytesIO('<a><b><c/></a>')
650 # ET raises ExpatError, lxml raises XMLSyntaxError
651 self.assertRaises(self.etree.XMLSyntaxError, list, iterparse(f))
652
654 iterparse = self.etree.iterparse
655 f = BytesIO("""
656 <a> \n \n <b> b test </b> \n
657
658 \n\t <c> \n </c> </a> \n """)
659 iterator = iterparse(f, remove_blank_text=True)
660 text = [ (element.text, element.tail)
661 for event, element in iterator ]
662 self.assertEquals(
663 [(" b test ", None), (" \n ", None), (None, None)],
664 text)
665
667 iterparse = self.etree.iterparse
668 f = BytesIO('<a><b><d/></b><c/></a>')
669
670 iterator = iterparse(f, tag="b", events=('start', 'end'))
671 events = list(iterator)
672 root = iterator.root
673 self.assertEquals(
674 [('start', root[0]), ('end', root[0])],
675 events)
676
678 iterparse = self.etree.iterparse
679 f = BytesIO('<a><b><d/></b><c/></a>')
680
681 iterator = iterparse(f, tag="*", events=('start', 'end'))
682 events = list(iterator)
683 self.assertEquals(
684 8,
685 len(events))
686
688 iterparse = self.etree.iterparse
689 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
690
691 iterator = iterparse(f, tag="{urn:test:1}b", events=('start', 'end'))
692 events = list(iterator)
693 root = iterator.root
694 self.assertEquals(
695 [('start', root[0]), ('end', root[0])],
696 events)
697
699 iterparse = self.etree.iterparse
700 f = BytesIO('<a><b><d/></b><c/></a>')
701 iterator = iterparse(f, tag="{}b", events=('start', 'end'))
702 events = list(iterator)
703 root = iterator.root
704 self.assertEquals(
705 [('start', root[0]), ('end', root[0])],
706 events)
707
708 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
709 iterator = iterparse(f, tag="{}b", events=('start', 'end'))
710 events = list(iterator)
711 root = iterator.root
712 self.assertEquals([], events)
713
715 iterparse = self.etree.iterparse
716 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
717 iterator = iterparse(f, tag="{urn:test:1}*", events=('start', 'end'))
718 events = list(iterator)
719 self.assertEquals(8, len(events))
720
722 iterparse = self.etree.iterparse
723 f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
724 iterator = iterparse(f, tag="{}*", events=('start', 'end'))
725 events = list(iterator)
726 self.assertEquals([], events)
727
728 f = BytesIO('<a><b><d/></b><c/></a>')
729 iterator = iterparse(f, tag="{}*", events=('start', 'end'))
730 events = list(iterator)
731 self.assertEquals(8, len(events))
732
734 text = _str('Søk på nettet')
735 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>"
736 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
737 ).encode('iso-8859-1')
738
739 self.assertRaises(self.etree.ParseError,
740 list, self.etree.iterparse(BytesIO(xml_latin1)))
741
743 text = _str('Søk på nettet', encoding="UTF-8")
744 wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>"
745 xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
746 ).encode('iso-8859-1')
747
748 iterator = self.etree.iterparse(BytesIO(xml_latin1),
749 encoding="iso-8859-1")
750 self.assertEquals(1, len(list(iterator)))
751
752 a = iterator.root
753 self.assertEquals(a.text, text)
754
756 tostring = self.etree.tostring
757 f = BytesIO('<root><![CDATA[test]]></root>')
758 context = self.etree.iterparse(f, strip_cdata=False)
759 content = [ el.text for event,el in context ]
760
761 self.assertEquals(['test'], content)
762 self.assertEquals(_bytes('<root><![CDATA[test]]></root>'),
763 tostring(context.root))
764
768
770 self.etree.XMLParser(encoding="ascii")
771 self.etree.XMLParser(encoding="utf-8")
772 self.etree.XMLParser(encoding="iso-8859-1")
773
775 parser = self.etree.XMLParser(recover=True)
776
777 parser.feed('<?xml version=')
778 parser.feed('"1.0"?><ro')
779 parser.feed('ot><')
780 parser.feed('a test="works"')
781 parser.feed('><othertag/></root') # <a> not closed!
782 parser.feed('>')
783
784 root = parser.close()
785
786 self.assertEquals(root.tag, "root")
787 self.assertEquals(len(root), 1)
788 self.assertEquals(root[0].tag, "a")
789 self.assertEquals(root[0].get("test"), "works")
790 self.assertEquals(len(root[0]), 1)
791 self.assertEquals(root[0][0].tag, "othertag")
792 # FIXME: would be nice to get some errors logged ...
793 #self.assert_(len(parser.error_log) > 0, "error log is empty")
794
796 assertEquals = self.assertEquals
797 assertFalse = self.assertFalse
798
799 events = []
800 class Target(object):
801 def start(self, tag, attrib):
802 events.append("start")
803 assertFalse(attrib)
804 assertEquals("TAG", tag)
805 def end(self, tag):
806 events.append("end")
807 assertEquals("TAG", tag)
808 def close(self):
809 return "DONE" # no Element!
810
811 parser = self.etree.XMLParser(target=Target())
812 tree = self.etree.ElementTree()
813
814 self.assertRaises(TypeError,
815 tree.parse, BytesIO("<TAG/>"), parser=parser)
816 self.assertEquals(["start", "end"], events)
817
819 # ET doesn't call .close() on errors
820 events = []
821 class Target(object):
822 def start(self, tag, attrib):
823 events.append("start-" + tag)
824 def end(self, tag):
825 events.append("end-" + tag)
826 if tag == 'a':
827 raise ValueError("dead and gone")
828 def data(self, data):
829 events.append("data-" + data)
830 def close(self):
831 events.append("close")
832 return "DONE"
833
834 parser = self.etree.XMLParser(target=Target())
835
836 try:
837 parser.feed(_bytes('<root>A<a>ca</a>B</root>'))
838 done = parser.close()
839 self.fail("error expected, but parsing succeeded")
840 except ValueError:
841 done = 'value error received as expected'
842
843 self.assertEquals(["start-root", "data-A", "start-a",
844 "data-ca", "end-a", "close"],
845 events)
846
848 # ET doesn't call .close() on errors
849 events = []
850 class Target(object):
851 def start(self, tag, attrib):
852 events.append("start-" + tag)
853 def end(self, tag):
854 events.append("end-" + tag)
855 if tag == 'a':
856 raise ValueError("dead and gone")
857 def data(self, data):
858 events.append("data-" + data)
859 def close(self):
860 events.append("close")
861 return "DONE"
862
863 parser = self.etree.XMLParser(target=Target())
864
865 try:
866 done = self.etree.fromstring(_bytes('<root>A<a>ca</a>B</root>'),
867 parser=parser)
868 self.fail("error expected, but parsing succeeded")
869 except ValueError:
870 done = 'value error received as expected'
871
872 self.assertEquals(["start-root", "data-A", "start-a",
873 "data-ca", "end-a", "close"],
874 events)
875
877 events = []
878 class Target(object):
879 def start(self, tag, attrib):
880 events.append("start-" + tag)
881 def end(self, tag):
882 events.append("end-" + tag)
883 def data(self, data):
884 events.append("data-" + data)
885 def comment(self, text):
886 events.append("comment-" + text)
887 def close(self):
888 return "DONE"
889
890 parser = self.etree.XMLParser(target=Target())
891
892 parser.feed(_bytes('<!--a--><root>A<!--b--><sub/><!--c-->B</root><!--d-->'))
893 done = parser.close()
894
895 self.assertEquals("DONE", done)
896 self.assertEquals(["comment-a", "start-root", "data-A", "comment-b",
897 "start-sub", "end-sub", "comment-c", "data-B",
898 "end-root", "comment-d"],
899 events)
900
902 events = []
903 class Target(object):
904 def start(self, tag, attrib):
905 events.append("start-" + tag)
906 def end(self, tag):
907 events.append("end-" + tag)
908 def data(self, data):
909 events.append("data-" + data)
910 def pi(self, target, data):
911 events.append("pi-" + target + "-" + data)
912 def close(self):
913 return "DONE"
914
915 parser = self.etree.XMLParser(target=Target())
916
917 parser.feed(_bytes('<?test a?><root>A<?test b?>B</root><?test c?>'))
918 done = parser.close()
919
920 self.assertEquals("DONE", done)
921 self.assertEquals(["pi-test-a", "start-root", "data-A", "pi-test-b",
922 "data-B", "end-root", "pi-test-c"],
923 events)
924
926 events = []
927 class Target(object):
928 def start(self, tag, attrib):
929 events.append("start-" + tag)
930 def end(self, tag):
931 events.append("end-" + tag)
932 def data(self, data):
933 events.append("data-" + data)
934 def close(self):
935 return "DONE"
936
937 parser = self.etree.XMLParser(target=Target(),
938 strip_cdata=False)
939
940 parser.feed(_bytes('<root>A<a><![CDATA[ca]]></a>B</root>'))
941 done = parser.close()
942
943 self.assertEquals("DONE", done)
944 self.assertEquals(["start-root", "data-A", "start-a",
945 "data-ca", "end-a", "data-B", "end-root"],
946 events)
947
949 events = []
950 class Target(object):
951 def start(self, tag, attrib):
952 events.append("start-" + tag)
953 def end(self, tag):
954 events.append("end-" + tag)
955 def data(self, data):
956 events.append("data-" + data)
957 def close(self):
958 events.append("close")
959 return "DONE"
960
961 parser = self.etree.XMLParser(target=Target(),
962 recover=True)
963
964 parser.feed(_bytes('<root>A<a>ca</a>B</not-root>'))
965 done = parser.close()
966
967 self.assertEquals("DONE", done)
968 self.assertEquals(["start-root", "data-A", "start-a",
969 "data-ca", "end-a", "data-B",
970 "end-root", "close"],
971 events)
972
974 iterwalk = self.etree.iterwalk
975 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
976
977 iterator = iterwalk(root, tag="b", events=('start', 'end'))
978 events = list(iterator)
979 self.assertEquals(
980 [('start', root[0]), ('end', root[0])],
981 events)
982
984 iterwalk = self.etree.iterwalk
985 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
986
987 iterator = iterwalk(root, tag="*", events=('start', 'end'))
988 events = list(iterator)
989 self.assertEquals(
990 8,
991 len(events))
992
994 iterwalk = self.etree.iterwalk
995 root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
996
997 events = list(iterwalk(root))
998 self.assertEquals(
999 [('end', root[0]), ('end', root[1]), ('end', root)],
1000 events)
1001
1003 iterwalk = self.etree.iterwalk
1004 root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
1005
1006 iterator = iterwalk(root, events=('start',))
1007 events = list(iterator)
1008 self.assertEquals(
1009 [('start', root), ('start', root[0]), ('start', root[1])],
1010 events)
1011
1013 iterwalk = self.etree.iterwalk
1014 root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
1015
1016 iterator = iterwalk(root, events=('start','end'))
1017 events = list(iterator)
1018 self.assertEquals(
1019 [('start', root), ('start', root[0]), ('end', root[0]),
1020 ('start', root[1]), ('end', root[1]), ('end', root)],
1021 events)
1022
1024 iterwalk = self.etree.iterwalk
1025 root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
1026
1027 iterator = iterwalk(root)
1028 for event, elem in iterator:
1029 elem.clear()
1030
1031 self.assertEquals(0,
1032 len(root))
1033
1035 iterwalk = self.etree.iterwalk
1036 root = self.etree.XML(_bytes('<a xmlns="ns1"><b><c xmlns="ns2"/></b></a>'))
1037
1038 attr_name = '{testns}bla'
1039 events = []
1040 iterator = iterwalk(root, events=('start','end','start-ns','end-ns'))
1041 for event, elem in iterator:
1042 events.append(event)
1043 if event == 'start':
1044 if elem.tag != '{ns1}a':
1045 elem.set(attr_name, 'value')
1046
1047 self.assertEquals(
1048 ['start-ns', 'start', 'start', 'start-ns', 'start',
1049 'end', 'end-ns', 'end', 'end', 'end-ns'],
1050 events)
1051
1052 self.assertEquals(
1053 None,
1054 root.get(attr_name))
1055 self.assertEquals(
1056 'value',
1057 root[0].get(attr_name))
1058
1060 iterwalk = self.etree.iterwalk
1061 root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
1062
1063 counts = []
1064 for event, elem in iterwalk(root):
1065 counts.append(len(list(elem.getiterator())))
1066 self.assertEquals(
1067 [1,2,1,4],
1068 counts)
1069
1071 parse = self.etree.parse
1072 parser = self.etree.XMLParser(dtd_validation=True)
1073 assertEqual = self.assertEqual
1074 test_url = _str("__nosuch.dtd")
1075
1076 class MyResolver(self.etree.Resolver):
1077 def resolve(self, url, id, context):
1078 assertEqual(url, test_url)
1079 return self.resolve_string(
1080 _str('''<!ENTITY myentity "%s">
1081 <!ELEMENT doc ANY>''') % url, context)
1082
1083 parser.resolvers.add(MyResolver())
1084
1085 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1086 tree = parse(StringIO(xml), parser)
1087 root = tree.getroot()
1088 self.assertEquals(root.text, test_url)
1089
1091 parse = self.etree.parse
1092 parser = self.etree.XMLParser(dtd_validation=True)
1093 assertEqual = self.assertEqual
1094 test_url = _str("__nosuch.dtd")
1095
1096 class MyResolver(self.etree.Resolver):
1097 def resolve(self, url, id, context):
1098 assertEqual(url, test_url)
1099 return self.resolve_string(
1100 (_str('''<!ENTITY myentity "%s">
1101 <!ELEMENT doc ANY>''') % url).encode('utf-8'),
1102 context)
1103
1104 parser.resolvers.add(MyResolver())
1105
1106 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1107 tree = parse(StringIO(xml), parser)
1108 root = tree.getroot()
1109 self.assertEquals(root.text, test_url)
1110
1112 parse = self.etree.parse
1113 parser = self.etree.XMLParser(dtd_validation=True)
1114 assertEqual = self.assertEqual
1115 test_url = _str("__nosuch.dtd")
1116
1117 class MyResolver(self.etree.Resolver):
1118 def resolve(self, url, id, context):
1119 assertEqual(url, test_url)
1120 return self.resolve_file(
1121 SillyFileLike(
1122 _str('''<!ENTITY myentity "%s">
1123 <!ELEMENT doc ANY>''') % url), context)
1124
1125 parser.resolvers.add(MyResolver())
1126
1127 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1128 tree = parse(StringIO(xml), parser)
1129 root = tree.getroot()
1130 self.assertEquals(root.text, test_url)
1131
1133 parse = self.etree.parse
1134 parser = self.etree.XMLParser(attribute_defaults=True)
1135 assertEqual = self.assertEqual
1136 test_url = _str("__nosuch.dtd")
1137
1138 class MyResolver(self.etree.Resolver):
1139 def resolve(self, url, id, context):
1140 assertEqual(url, test_url)
1141 return self.resolve_filename(
1142 fileInTestDir('test.dtd'), context)
1143
1144 parser.resolvers.add(MyResolver())
1145
1146 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
1147 tree = parse(StringIO(xml), parser)
1148 root = tree.getroot()
1149 self.assertEquals(
1150 root.attrib, {'default': 'valueA'})
1151 self.assertEquals(
1152 root[0].attrib, {'default': 'valueB'})
1153
1155 parse = self.etree.parse
1156 parser = self.etree.XMLParser(attribute_defaults=True)
1157 assertEqual = self.assertEqual
1158 test_url = _str("__nosuch.dtd")
1159
1160 class MyResolver(self.etree.Resolver):
1161 def resolve(self, url, id, context):
1162 assertEqual(url, fileInTestDir(test_url))
1163 return self.resolve_filename(
1164 fileInTestDir('test.dtd'), context)
1165
1166 parser.resolvers.add(MyResolver())
1167
1168 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
1169 tree = parse(StringIO(xml), parser,
1170 base_url=fileInTestDir('__test.xml'))
1171 root = tree.getroot()
1172 self.assertEquals(
1173 root.attrib, {'default': 'valueA'})
1174 self.assertEquals(
1175 root[0].attrib, {'default': 'valueB'})
1176
1178 parse = self.etree.parse
1179 parser = self.etree.XMLParser(attribute_defaults=True)
1180 assertEqual = self.assertEqual
1181 test_url = _str("__nosuch.dtd")
1182
1183 class MyResolver(self.etree.Resolver):
1184 def resolve(self, url, id, context):
1185 assertEqual(url, test_url)
1186 return self.resolve_file(
1187 open(fileInTestDir('test.dtd'), 'rb'), context)
1188
1189 parser.resolvers.add(MyResolver())
1190
1191 xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
1192 tree = parse(StringIO(xml), parser)
1193 root = tree.getroot()
1194 self.assertEquals(
1195 root.attrib, {'default': 'valueA'})
1196 self.assertEquals(
1197 root[0].attrib, {'default': 'valueB'})
1198
1200 parse = self.etree.parse
1201 parser = self.etree.XMLParser(load_dtd=True)
1202 assertEqual = self.assertEqual
1203 test_url = _str("__nosuch.dtd")
1204
1205 class check(object):
1206 resolved = False
1207
1208 class MyResolver(self.etree.Resolver):
1209 def resolve(self, url, id, context):
1210 assertEqual(url, test_url)
1211 check.resolved = True
1212 return self.resolve_empty(context)
1213
1214 parser.resolvers.add(MyResolver())
1215
1216 xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
1217 self.assertRaises(etree.XMLSyntaxError, parse, StringIO(xml), parser)
1218 self.assert_(check.resolved)
1219
1221 parse = self.etree.parse
1222 parser = self.etree.XMLParser(dtd_validation=True)
1223
1224 class _LocalException(Exception):
1225 pass
1226
1227 class MyResolver(self.etree.Resolver):
1228 def resolve(self, url, id, context):
1229 raise _LocalException
1230
1231 parser.resolvers.add(MyResolver())
1232
1233 xml = '<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>'
1234 self.assertRaises(_LocalException, parse, BytesIO(xml), parser)
1235
1236 if etree.LIBXML_VERSION > (2,6,20):
1238 parse = self.etree.parse
1239 tostring = self.etree.tostring
1240 parser = self.etree.XMLParser(resolve_entities=False)
1241 Entity = self.etree.Entity
1242
1243 xml = _bytes('<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>')
1244 tree = parse(BytesIO(xml), parser)
1245 root = tree.getroot()
1246 self.assertEquals(root[0].tag, Entity)
1247 self.assertEquals(root[0].text, "&myentity;")
1248 self.assertEquals(root[0].tail, None)
1249 self.assertEquals(root[0].name, "myentity")
1250
1251 self.assertEquals(_bytes('<doc>&myentity;</doc>'),
1252 tostring(root))
1253
1255 xml = _bytes('''<!DOCTYPE root [ <!ENTITY nbsp " "> ]>
1256 <root>
1257 <child1/>
1258 <child2/>
1259 <child3> </child3>
1260 </root>''')
1261
1262 parser = self.etree.XMLParser(resolve_entities=False)
1263 root = etree.fromstring(xml, parser)
1264 self.assertEquals([ el.tag for el in root ],
1265 ['child1', 'child2', 'child3'])
1266
1267 root[0] = root[-1]
1268 self.assertEquals([ el.tag for el in root ],
1269 ['child3', 'child2'])
1270 self.assertEquals(root[0][0].text, ' ')
1271 self.assertEquals(root[0][0].name, 'nbsp')
1272
1274 Entity = self.etree.Entity
1275 Element = self.etree.Element
1276 tostring = self.etree.tostring
1277
1278 root = Element("root")
1279 root.append( Entity("test") )
1280
1281 self.assertEquals(root[0].tag, Entity)
1282 self.assertEquals(root[0].text, "&test;")
1283 self.assertEquals(root[0].tail, None)
1284 self.assertEquals(root[0].name, "test")
1285
1286 self.assertEquals(_bytes('<root>&test;</root>'),
1287 tostring(root))
1288
1290 Entity = self.etree.Entity
1291 self.assertEquals(Entity("test").text, '&test;')
1292 self.assertEquals(Entity("#17683").text, '䔓')
1293 self.assertEquals(Entity("#x1768").text, 'ᝨ')
1294 self.assertEquals(Entity("#x98AF").text, '颯')
1295
1297 Entity = self.etree.Entity
1298 self.assertRaises(ValueError, Entity, 'a b c')
1299 self.assertRaises(ValueError, Entity, 'a,b')
1300 self.assertRaises(ValueError, Entity, 'a\0b')
1301 self.assertRaises(ValueError, Entity, '#abc')
1302 self.assertRaises(ValueError, Entity, '#xxyz')
1303
1305 CDATA = self.etree.CDATA
1306 Element = self.etree.Element
1307 tostring = self.etree.tostring
1308
1309 root = Element("root")
1310 root.text = CDATA('test')
1311
1312 self.assertEquals('test',
1313 root.text)
1314 self.assertEquals(_bytes('<root><![CDATA[test]]></root>'),
1315 tostring(root))
1316
1318 CDATA = self.etree.CDATA
1319 Element = self.etree.Element
1320 root = Element("root")
1321
1322 root.text = CDATA("test")
1323 self.assertEquals('test', root.text)
1324
1325 root.text = CDATA(_str("test"))
1326 self.assertEquals('test', root.text)
1327
1328 self.assertRaises(TypeError, CDATA, 1)
1329
1331 CDATA = self.etree.CDATA
1332 Element = self.etree.Element
1333
1334 root = Element("root")
1335 cdata = CDATA('test')
1336
1337 self.assertRaises(TypeError,
1338 setattr, root, 'tail', cdata)
1339 self.assertRaises(TypeError,
1340 root.set, 'attr', cdata)
1341 self.assertRaises(TypeError,
1342 operator.setitem, root.attrib, 'attr', cdata)
1343
1345 tostring = self.etree.tostring
1346 parser = self.etree.XMLParser(strip_cdata=False)
1347 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser)
1348
1349 self.assertEquals('test', root.text)
1350 self.assertEquals(_bytes('<root><![CDATA[test]]></root>'),
1351 tostring(root))
1352
1354 tostring = self.etree.tostring
1355 parser = self.etree.XMLParser(strip_cdata=False)
1356 root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser)
1357 self.assertEquals(_bytes('<root><![CDATA[test]]></root>'),
1358 tostring(root))
1359
1360 self.assertEquals(['test'], root.xpath('//text()'))
1361
1362 # TypeError in etree, AssertionError in ElementTree;
1364 Element = self.etree.Element
1365 SubElement = self.etree.SubElement
1366
1367 a = Element('a')
1368 b = SubElement(a, 'b')
1369
1370 self.assertRaises(TypeError,
1371 a.__setitem__, 0, 'foo')
1372
1374 Element = self.etree.Element
1375 root = Element('root')
1376 # raises AssertionError in ElementTree
1377 self.assertRaises(TypeError, root.append, None)
1378 self.assertRaises(TypeError, root.extend, [None])
1379 self.assertRaises(TypeError, root.extend, [Element('one'), None])
1380 self.assertEquals('one', root[0].tag)
1381
1383 Element = self.etree.Element
1384 SubElement = self.etree.SubElement
1385 root = Element('root')
1386 SubElement(root, 'a')
1387 SubElement(root, 'b')
1388
1389 self.assertEquals(['a', 'b'],
1390 [c.tag for c in root])
1391 root[1].addnext(root[0])
1392 self.assertEquals(['b', 'a'],
1393 [c.tag for c in root])
1394
1396 Element = self.etree.Element
1397 SubElement = self.etree.SubElement
1398 root = Element('root')
1399 SubElement(root, 'a')
1400 SubElement(root, 'b')
1401
1402 self.assertEquals(['a', 'b'],
1403 [c.tag for c in root])
1404 root[0].addprevious(root[1])
1405 self.assertEquals(['b', 'a'],
1406 [c.tag for c in root])
1407
1409 Element = self.etree.Element
1410 a = Element('a')
1411 b = Element('b')
1412 self.assertRaises(TypeError, a.addnext, b)
1413
1415 Element = self.etree.Element
1416 a = Element('a')
1417 b = Element('b')
1418 self.assertRaises(TypeError, a.addnext, b)
1419
1421 Element = self.etree.Element
1422 SubElement = self.etree.SubElement
1423 PI = self.etree.PI
1424 root = Element('root')
1425 SubElement(root, 'a')
1426 pi = PI('TARGET', 'TEXT')
1427 pi.tail = "TAIL"
1428
1429 self.assertEquals(_bytes('<root><a></a></root>'),
1430 self._writeElement(root))
1431 root[0].addprevious(pi)
1432 self.assertEquals(_bytes('<root><?TARGET TEXT?>TAIL<a></a></root>'),
1433 self._writeElement(root))
1434
1436 Element = self.etree.Element
1437 PI = self.etree.PI
1438 root = Element('root')
1439 pi = PI('TARGET', 'TEXT')
1440 pi.tail = "TAIL"
1441
1442 self.assertEquals(_bytes('<root></root>'),
1443 self._writeElement(root))
1444 root.addprevious(pi)
1445 self.assertEquals(_bytes('<?TARGET TEXT?>\n<root></root>'),
1446 self._writeElement(root))
1447
1449 Element = self.etree.Element
1450 SubElement = self.etree.SubElement
1451 PI = self.etree.PI
1452 root = Element('root')
1453 SubElement(root, 'a')
1454 pi = PI('TARGET', 'TEXT')
1455 pi.tail = "TAIL"
1456
1457 self.assertEquals(_bytes('<root><a></a></root>'),
1458 self._writeElement(root))
1459 root[0].addnext(pi)
1460 self.assertEquals(_bytes('<root><a></a><?TARGET TEXT?>TAIL</root>'),
1461 self._writeElement(root))
1462
1464 Element = self.etree.Element
1465 PI = self.etree.PI
1466 root = Element('root')
1467 pi = PI('TARGET', 'TEXT')
1468 pi.tail = "TAIL"
1469
1470 self.assertEquals(_bytes('<root></root>'),
1471 self._writeElement(root))
1472 root.addnext(pi)
1473 self.assertEquals(_bytes('<root></root>\n<?TARGET TEXT?>'),
1474 self._writeElement(root))
1475
1477 Element = self.etree.Element
1478 SubElement = self.etree.SubElement
1479 Comment = self.etree.Comment
1480 root = Element('root')
1481 SubElement(root, 'a')
1482 comment = Comment('TEXT ')
1483 comment.tail = "TAIL"
1484
1485 self.assertEquals(_bytes('<root><a></a></root>'),
1486 self._writeElement(root))
1487 root[0].addnext(comment)
1488 self.assertEquals(_bytes('<root><a></a><!--TEXT -->TAIL</root>'),
1489 self._writeElement(root))
1490
1492 Element = self.etree.Element
1493 Comment = self.etree.Comment
1494 root = Element('root')
1495 comment = Comment('TEXT ')
1496 comment.tail = "TAIL"
1497
1498 self.assertEquals(_bytes('<root></root>'),
1499 self._writeElement(root))
1500 root.addnext(comment)
1501 self.assertEquals(_bytes('<root></root>\n<!--TEXT -->'),
1502 self._writeElement(root))
1503
1505 Element = self.etree.Element
1506 SubElement = self.etree.SubElement
1507 Comment = self.etree.Comment
1508 root = Element('root')
1509 SubElement(root, 'a')
1510 comment = Comment('TEXT ')
1511 comment.tail = "TAIL"
1512
1513 self.assertEquals(_bytes('<root><a></a></root>'),
1514 self._writeElement(root))
1515 root[0].addprevious(comment)
1516 self.assertEquals(_bytes('<root><!--TEXT -->TAIL<a></a></root>'),
1517 self._writeElement(root))
1518
1520 Element = self.etree.Element
1521 Comment = self.etree.Comment
1522 root = Element('root')
1523 comment = Comment('TEXT ')
1524 comment.tail = "TAIL"
1525
1526 self.assertEquals(_bytes('<root></root>'),
1527 self._writeElement(root))
1528 root.addprevious(comment)
1529 self.assertEquals(_bytes('<!--TEXT -->\n<root></root>'),
1530 self._writeElement(root))
1531
1532 # ET's Elements have items() and key(), but not values()
1534 XML = self.etree.XML
1535
1536 root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
1537 values = root.values()
1538 values.sort()
1539 self.assertEquals(['Alpha', 'Beta', 'Gamma'], values)
1540
1541 # gives error in ElementTree
1543 Element = self.etree.Element
1544 Comment = self.etree.Comment
1545
1546 a = Element('a')
1547 a.append(Comment())
1548 self.assertEquals(
1549 _bytes('<a><!----></a>'),
1550 self._writeElement(a))
1551
1552 # ElementTree ignores comments
1554 ElementTree = self.etree.ElementTree
1555 tostring = self.etree.tostring
1556
1557 xml = _bytes('<a><b/><!----><c/></a>')
1558 f = BytesIO(xml)
1559 doc = ElementTree(file=f)
1560 a = doc.getroot()
1561 self.assertEquals(
1562 '',
1563 a[1].text)
1564 self.assertEquals(
1565 xml,
1566 tostring(a))
1567
1568 # ElementTree ignores comments
1570 ElementTree = self.etree.ElementTree
1571
1572 f = BytesIO('<a><b></b><!-- hoi --><c></c></a>')
1573 doc = ElementTree(file=f)
1574 a = doc.getroot()
1575 self.assertEquals(
1576 ' hoi ',
1577 a[1].text)
1578
1579 # does not raise an exception in ElementTree
1581 Element = self.etree.Element
1582 Comment = self.etree.Comment
1583
1584 c = Comment()
1585 el = Element('myel')
1586
1587 self.assertRaises(TypeError, c.append, el)
1588 self.assertRaises(TypeError, c.insert, 0, el)
1589 self.assertRaises(TypeError, c.set, "myattr", "test")
1590
1591 # test passing 'None' to dump
1594
1596 ElementTree = self.etree.ElementTree
1597
1598 f = BytesIO('<a xmlns:foo="http://www.infrae.com/ns/1"><foo:b/></a>')
1599 doc = ElementTree(file=f)
1600 a = doc.getroot()
1601 self.assertEquals(
1602 None,
1603 a.prefix)
1604 self.assertEquals(
1605 'foo',
1606 a[0].prefix)
1607
1609 ElementTree = self.etree.ElementTree
1610
1611 f = BytesIO('<a xmlns="http://www.infrae.com/ns/1"><b/></a>')
1612 doc = ElementTree(file=f)
1613 a = doc.getroot()
1614 self.assertEquals(
1615 None,
1616 a.prefix)
1617 self.assertEquals(
1618 None,
1619 a[0].prefix)
1620
1622 Element = self.etree.Element
1623 SubElement = self.etree.SubElement
1624
1625 a = Element('a')
1626 b = SubElement(a, 'b')
1627 c = SubElement(a, 'c')
1628 d = SubElement(b, 'd')
1629 self.assertEquals(
1630 None,
1631 a.getparent())
1632 self.assertEquals(
1633 a,
1634 b.getparent())
1635 self.assertEquals(
1636 b.getparent(),
1637 c.getparent())
1638 self.assertEquals(
1639 b,
1640 d.getparent())
1641
1643 XML = self.etree.XML
1644
1645 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
1646 result = []
1647 for el in root.iterchildren():
1648 result.append(el.tag)
1649 self.assertEquals(['one', 'two', 'three'], result)
1650
1652 XML = self.etree.XML
1653
1654 root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
1655 result = []
1656 for el in root.iterchildren(reversed=True):
1657 result.append(el.tag)
1658 self.assertEquals(['three', 'two', 'one'], result)
1659
1661 XML = self.etree.XML
1662
1663 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
1664 result = []
1665 for el in root.iterchildren(tag='two'):
1666 result.append(el.text)
1667 self.assertEquals(['Two', 'Bla'], result)
1668
1670 XML = self.etree.XML
1671
1672 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
1673 result = []
1674 for el in root.iterchildren(reversed=True, tag='two'):
1675 result.append(el.text)
1676 self.assertEquals(['Bla', 'Two'], result)
1677
1679 XML = self.etree.XML
1680
1681 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
1682 result = []
1683 for el in root.iterchildren(tag=['two', 'three']):
1684 result.append(el.text)
1685 self.assertEquals(['Two', 'Bla', None], result)
1686
1688 XML = self.etree.XML
1689
1690 root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
1691 result = []
1692 for el in root.iterchildren(reversed=True, tag=['two', 'three']):
1693 result.append(el.text)
1694 self.assertEquals([None, 'Bla', 'Two'], result)
1695
1697 Element = self.etree.Element
1698 SubElement = self.etree.SubElement
1699
1700 a = Element('a')
1701 b = SubElement(a, 'b')
1702 c = SubElement(a, 'c')
1703 d = SubElement(b, 'd')
1704 self.assertEquals(
1705 [],
1706 list(a.iterancestors()))
1707 self.assertEquals(
1708 [a],
1709 list(b.iterancestors()))
1710 self.assertEquals(
1711 [a],
1712 list(c.iterancestors()))
1713 self.assertEquals(
1714 [b, a],
1715 list(d.iterancestors()))
1716
1718 Element = self.etree.Element
1719 SubElement = self.etree.SubElement
1720
1721 a = Element('a')
1722 b = SubElement(a, 'b')
1723 c = SubElement(a, 'c')
1724 d = SubElement(b, 'd')
1725 self.assertEquals(
1726 [a],
1727 list(d.iterancestors(tag='a')))
1728 self.assertEquals(
1729 [b, a],
1730 list(d.iterancestors(tag='*')))
1731
1733 Element = self.etree.Element
1734 SubElement = self.etree.SubElement
1735
1736 a = Element('a')
1737 b = SubElement(a, 'b')
1738 c = SubElement(a, 'c')
1739 d = SubElement(b, 'd')
1740 self.assertEquals(
1741 [b, a],
1742 list(d.iterancestors(tag=('a', 'b'))))
1743 self.assertEquals(
1744 [],
1745 list(d.iterancestors(tag=('w', 'x', 'y', 'z'))))
1746 self.assertEquals(
1747 [],
1748 list(d.iterancestors(tag=('d', 'x'))))
1749 self.assertEquals(
1750 [b, a],
1751 list(d.iterancestors(tag=('b', '*'))))
1752 self.assertEquals(
1753 [b],
1754 list(d.iterancestors(tag=('b', 'c'))))
1755
1757 Element = self.etree.Element
1758 SubElement = self.etree.SubElement
1759
1760 a = Element('a')
1761 b = SubElement(a, 'b')
1762 c = SubElement(a, 'c')
1763 d = SubElement(b, 'd')
1764 e = SubElement(c, 'e')
1765
1766 self.assertEquals(
1767 [b, d, c, e],
1768 list(a.iterdescendants()))
1769 self.assertEquals(
1770 [],
1771 list(d.iterdescendants()))
1772
1774 Element = self.etree.Element
1775 SubElement = self.etree.SubElement
1776
1777 a = Element('a')
1778 b = SubElement(a, 'b')
1779 c = SubElement(a, 'c')
1780 d = SubElement(b, 'd')
1781 e = SubElement(c, 'e')
1782
1783 self.assertEquals(
1784 [],
1785 list(a.iterdescendants('a')))
1786 a2 = SubElement(e, 'a')
1787 self.assertEquals(
1788 [a2],
1789 list(a.iterdescendants('a')))
1790 self.assertEquals(
1791 [a2],
1792 list(c.iterdescendants('a')))
1793
1795 Element = self.etree.Element
1796 SubElement = self.etree.SubElement
1797
1798 a = Element('a')
1799 b = SubElement(a, 'b')
1800 c = SubElement(a, 'c')
1801 d = SubElement(b, 'd')
1802 e = SubElement(c, 'e')
1803
1804 self.assertEquals(
1805 [b, e],
1806 list(a.iterdescendants(tag=('a', 'b', 'e'))))
1807 a2 = SubElement(e, 'a')
1808 self.assertEquals(
1809 [b, a2],
1810 list(a.iterdescendants(tag=('a', 'b'))))
1811 self.assertEquals(
1812 [],
1813 list(c.iterdescendants(tag=('x', 'y', 'z'))))
1814 self.assertEquals(
1815 [b, d, c, e, a2],
1816 list(a.iterdescendants(tag=('x', 'y', 'z', '*'))))
1817
1819 Element = self.etree.Element
1820 SubElement = self.etree.SubElement
1821
1822 a = Element('a')
1823 b = SubElement(a, 'b')
1824 c = SubElement(a, 'c')
1825 d = SubElement(b, 'd')
1826 self.assertEquals(
1827 a,
1828 a.getroottree().getroot())
1829 self.assertEquals(
1830 a,
1831 b.getroottree().getroot())
1832 self.assertEquals(
1833 a,
1834 d.getroottree().getroot())
1835
1837 Element = self.etree.Element
1838 SubElement = self.etree.SubElement
1839
1840 a = Element('a')
1841 b = SubElement(a, 'b')
1842 c = SubElement(a, 'c')
1843 self.assertEquals(
1844 None,
1845 a.getnext())
1846 self.assertEquals(
1847 c,
1848 b.getnext())
1849 self.assertEquals(
1850 None,
1851 c.getnext())
1852
1854 Element = self.etree.Element
1855 SubElement = self.etree.SubElement
1856
1857 a = Element('a')
1858 b = SubElement(a, 'b')
1859 c = SubElement(a, 'c')
1860 d = SubElement(b, 'd')
1861 self.assertEquals(
1862 None,
1863 a.getprevious())
1864 self.assertEquals(
1865 b,
1866 c.getprevious())
1867 self.assertEquals(
1868 None,
1869 b.getprevious())
1870
1872 Element = self.etree.Element
1873 SubElement = self.etree.SubElement
1874
1875 a = Element('a')
1876 b = SubElement(a, 'b')
1877 c = SubElement(a, 'c')
1878 d = SubElement(b, 'd')
1879 self.assertEquals(
1880 [],
1881 list(a.itersiblings()))
1882 self.assertEquals(
1883 [c],
1884 list(b.itersiblings()))
1885 self.assertEquals(
1886 [],
1887 list(c.itersiblings()))
1888 self.assertEquals(
1889 [b],
1890 list(c.itersiblings(preceding=True)))
1891 self.assertEquals(
1892 [],
1893 list(b.itersiblings(preceding=True)))
1894
1896 Element = self.etree.Element
1897 SubElement = self.etree.SubElement
1898
1899 a = Element('a')
1900 b = SubElement(a, 'b')
1901 c = SubElement(a, 'c')
1902 d = SubElement(b, 'd')
1903 self.assertEquals(
1904 [],
1905 list(a.itersiblings(tag='XXX')))
1906 self.assertEquals(
1907 [c],
1908 list(b.itersiblings(tag='c')))
1909 self.assertEquals(
1910 [c],
1911 list(b.itersiblings(tag='*')))
1912 self.assertEquals(
1913 [b],
1914 list(c.itersiblings(preceding=True, tag='b')))
1915 self.assertEquals(
1916 [],
1917 list(c.itersiblings(preceding=True, tag='c')))
1918
1920 Element = self.etree.Element
1921 SubElement = self.etree.SubElement
1922
1923 a = Element('a')
1924 b = SubElement(a, 'b')
1925 c = SubElement(a, 'c')
1926 d = SubElement(b, 'd')
1927 e = SubElement(a, 'e')
1928 self.assertEquals(
1929 [],
1930 list(a.itersiblings(tag=('XXX', 'YYY'))))
1931 self.assertEquals(
1932 [c, e],
1933 list(b.itersiblings(tag=('c', 'd', 'e'))))
1934 self.assertEquals(
1935 [b],
1936 list(c.itersiblings(preceding=True, tag=('b', 'b', 'c', 'd'))))
1937 self.assertEquals(
1938 [c, b],
1939 list(e.itersiblings(preceding=True, tag=('c', '*'))))
1940
1942 parseid = self.etree.parseid
1943 XML = self.etree.XML
1944 xml_text = _bytes('''
1945 <!DOCTYPE document [
1946 <!ELEMENT document (h1,p)*>
1947 <!ELEMENT h1 (#PCDATA)>
1948 <!ATTLIST h1 myid ID #REQUIRED>
1949 <!ELEMENT p (#PCDATA)>
1950 <!ATTLIST p someid ID #REQUIRED>
1951 ]>
1952 <document>
1953 <h1 myid="chapter1">...</h1>
1954 <p id="note1" class="note">...</p>
1955 <p>Regular paragraph.</p>
1956 <p xml:id="xmlid">XML:ID paragraph.</p>
1957 <p someid="warn1" class="warning">...</p>
1958 </document>
1959 ''')
1960
1961 tree, dic = parseid(BytesIO(xml_text))
1962 root = tree.getroot()
1963 root2 = XML(xml_text)
1964 self.assertEquals(self._writeElement(root),
1965 self._writeElement(root2))
1966 expected = {
1967 "chapter1" : root[0],
1968 "xmlid" : root[3],
1969 "warn1" : root[4]
1970 }
1971 self.assert_("chapter1" in dic)
1972 self.assert_("warn1" in dic)
1973 self.assert_("xmlid" in dic)
1974 self._checkIDDict(dic, expected)
1975
1977 XMLDTDID = self.etree.XMLDTDID
1978 XML = self.etree.XML
1979 xml_text = _bytes('''
1980 <!DOCTYPE document [
1981 <!ELEMENT document (h1,p)*>
1982 <!ELEMENT h1 (#PCDATA)>
1983 <!ATTLIST h1 myid ID #REQUIRED>
1984 <!ELEMENT p (#PCDATA)>
1985 <!ATTLIST p someid ID #REQUIRED>
1986 ]>
1987 <document>
1988 <h1 myid="chapter1">...</h1>
1989 <p id="note1" class="note">...</p>
1990 <p>Regular paragraph.</p>
1991 <p xml:id="xmlid">XML:ID paragraph.</p>
1992 <p someid="warn1" class="warning">...</p>
1993 </document>
1994 ''')
1995
1996 root, dic = XMLDTDID(xml_text)
1997 root2 = XML(xml_text)
1998 self.assertEquals(self._writeElement(root),
1999 self._writeElement(root2))
2000 expected = {
2001 "chapter1" : root[0],
2002 "xmlid" : root[3],
2003 "warn1" : root[4]
2004 }
2005 self.assert_("chapter1" in dic)
2006 self.assert_("warn1" in dic)
2007 self.assert_("xmlid" in dic)
2008 self._checkIDDict(dic, expected)
2009
2011 XMLDTDID = self.etree.XMLDTDID
2012 XML = self.etree.XML
2013 xml_text = _bytes('''
2014 <document>
2015 <h1 myid="chapter1">...</h1>
2016 <p id="note1" class="note">...</p>
2017 <p>Regular paragraph.</p>
2018 <p someid="warn1" class="warning">...</p>
2019 </document>
2020 ''')
2021
2022 root, dic = XMLDTDID(xml_text)
2023 root2 = XML(xml_text)
2024 self.assertEquals(self._writeElement(root),
2025 self._writeElement(root2))
2026 expected = {}
2027 self._checkIDDict(dic, expected)
2028
2030 self.assertEquals(len(dic),
2031 len(expected))
2032 self.assertEquals(sorted(dic.items()),
2033 sorted(expected.items()))
2034 if sys.version_info < (3,):
2035 self.assertEquals(sorted(dic.iteritems()),
2036 sorted(expected.iteritems()))
2037 self.assertEquals(sorted(dic.keys()),
2038 sorted(expected.keys()))
2039 if sys.version_info < (3,):
2040 self.assertEquals(sorted(dic.iterkeys()),
2041 sorted(expected.iterkeys()))
2042 if sys.version_info < (3,):
2043 self.assertEquals(sorted(dic.values()),
2044 sorted(expected.values()))
2045 self.assertEquals(sorted(dic.itervalues()),
2046 sorted(expected.itervalues()))
2047
2049 etree = self.etree
2050
2051 r = {'foo': 'http://ns.infrae.com/foo'}
2052 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2053 self.assertEquals(
2054 'foo',
2055 e.prefix)
2056 self.assertEquals(
2057 _bytes('<foo:bar xmlns:foo="http://ns.infrae.com/foo"></foo:bar>'),
2058 self._writeElement(e))
2059
2061 etree = self.etree
2062
2063 r = {None: 'http://ns.infrae.com/foo'}
2064 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2065 self.assertEquals(
2066 None,
2067 e.prefix)
2068 self.assertEquals(
2069 '{http://ns.infrae.com/foo}bar',
2070 e.tag)
2071 self.assertEquals(
2072 _bytes('<bar xmlns="http://ns.infrae.com/foo"></bar>'),
2073 self._writeElement(e))
2074
2076 etree = self.etree
2077
2078 r = {None: 'http://ns.infrae.com/foo',
2079 'hoi': 'http://ns.infrae.com/hoi'}
2080 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2081 e.set('{http://ns.infrae.com/hoi}test', 'value')
2082 self.assertEquals(
2083 _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi" hoi:test="value"></bar>'),
2084 self._writeElement(e))
2085
2087 etree = self.etree
2088 r = {None: 'http://ns.infrae.com/foo',
2089 'hoi': 'http://ns.infrae.com/hoi'}
2090 e = etree.Element('{http://ns.infrae.com/foo}z', nsmap=r)
2091 tree = etree.ElementTree(element=e)
2092 etree.SubElement(e, '{http://ns.infrae.com/hoi}x')
2093 self.assertEquals(
2094 _bytes('<z xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi"><hoi:x></hoi:x></z>'),
2095 self._writeElement(e))
2096
2098 etree = self.etree
2099
2100 r = {None: 'http://ns.infrae.com/foo'}
2101 e1 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2102 e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2103
2104 e1.append(e2)
2105
2106 self.assertEquals(
2107 None,
2108 e1.prefix)
2109 self.assertEquals(
2110 None,
2111 e1[0].prefix)
2112 self.assertEquals(
2113 '{http://ns.infrae.com/foo}bar',
2114 e1.tag)
2115 self.assertEquals(
2116 '{http://ns.infrae.com/foo}bar',
2117 e1[0].tag)
2118
2120 etree = self.etree
2121
2122 r = {None: 'http://ns.infrae.com/BAR'}
2123 e1 = etree.Element('{http://ns.infrae.com/BAR}bar', nsmap=r)
2124 e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2125
2126 e1.append(e2)
2127
2128 self.assertEquals(
2129 None,
2130 e1.prefix)
2131 self.assertNotEquals(
2132 None,
2133 e2.prefix)
2134 self.assertEquals(
2135 '{http://ns.infrae.com/BAR}bar',
2136 e1.tag)
2137 self.assertEquals(
2138 '{http://ns.infrae.com/foo}bar',
2139 e2.tag)
2140
2142 ns_href = "http://a.b.c"
2143 one = self.etree.fromstring(
2144 _bytes('<foo><bar xmlns:ns="%s"><ns:baz/></bar></foo>' % ns_href))
2145 baz = one[0][0]
2146
2147 two = self.etree.fromstring(
2148 _bytes('<root xmlns:ns="%s"/>' % ns_href))
2149 two.append(baz)
2150 del one # make sure the source document is deallocated
2151
2152 self.assertEquals('{%s}baz' % ns_href, baz.tag)
2153 self.assertEquals(
2154 _bytes('<root xmlns:ns="%s"><ns:baz/></root>' % ns_href),
2155 self.etree.tostring(two))
2156
2158 xml = _bytes('<foo xmlns="F" xmlns:x="x"><bar xmlns:ns="NS" xmlns:b="b" xmlns="B"><ns:baz/></bar></foo>')
2159 root = self.etree.fromstring(xml)
2160 self.assertEquals(xml,
2161 self.etree.tostring(root))
2162 self.etree.cleanup_namespaces(root)
2163 self.assertEquals(
2164 _bytes('<foo xmlns="F"><bar xmlns:ns="NS" xmlns="B"><ns:baz/></bar></foo>'),
2165 self.etree.tostring(root))
2166
2168 etree = self.etree
2169
2170 r = {None: 'http://ns.infrae.com/foo',
2171 'hoi': 'http://ns.infrae.com/hoi'}
2172 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
2173 self.assertEquals(
2174 r,
2175 e.nsmap)
2176
2178 etree = self.etree
2179
2180 re = {None: 'http://ns.infrae.com/foo',
2181 'hoi': 'http://ns.infrae.com/hoi'}
2182 e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=re)
2183
2184 rs = {None: 'http://ns.infrae.com/honk',
2185 'top': 'http://ns.infrae.com/top'}
2186 s = etree.SubElement(e, '{http://ns.infrae.com/honk}bar', nsmap=rs)
2187
2188 r = re.copy()
2189 r.update(rs)
2190 self.assertEquals(re, e.nsmap)
2191 self.assertEquals(r, s.nsmap)
2192
2194 etree = self.etree
2195 el = etree.HTML('<hha:page-description>aa</hha:page-description>').find('.//page-description')
2196 self.assertEquals({'hha': None}, el.nsmap)
2197
2199 Element = self.etree.Element
2200 SubElement = self.etree.SubElement
2201
2202 a = Element('a')
2203 b = SubElement(a, 'b')
2204 c = SubElement(a, 'c')
2205 d = SubElement(b, 'd')
2206 e = SubElement(c, 'e')
2207 f = SubElement(c, 'f')
2208
2209 self.assertEquals(
2210 [a, b],
2211 list(a.getiterator('a', 'b')))
2212 self.assertEquals(
2213 [],
2214 list(a.getiterator('x', 'y')))
2215 self.assertEquals(
2216 [a, f],
2217 list(a.getiterator('f', 'a')))
2218 self.assertEquals(
2219 [c, e, f],
2220 list(c.getiterator('c', '*', 'a')))
2221 self.assertEquals(
2222 [],
2223 list(a.getiterator( (), () )))
2224
2226 Element = self.etree.Element
2227 SubElement = self.etree.SubElement
2228
2229 a = Element('a')
2230 b = SubElement(a, 'b')
2231 c = SubElement(a, 'c')
2232 d = SubElement(b, 'd')
2233 e = SubElement(c, 'e')
2234 f = SubElement(c, 'f')
2235
2236 self.assertEquals(
2237 [a, b],
2238 list(a.getiterator( ('a', 'b') )))
2239 self.assertEquals(
2240 [],
2241 list(a.getiterator( ('x', 'y') )))
2242 self.assertEquals(
2243 [a, f],
2244 list(a.getiterator( ('f', 'a') )))
2245 self.assertEquals(
2246 [c, e, f],
2247 list(c.getiterator( ('c', '*', 'a') )))
2248 self.assertEquals(
2249 [],
2250 list(a.getiterator( () )))
2251
2253 Element = self.etree.Element
2254 SubElement = self.etree.SubElement
2255
2256 a = Element('{a}a')
2257 b = SubElement(a, '{a}b')
2258 c = SubElement(a, '{a}c')
2259 d = SubElement(b, '{b}d')
2260 e = SubElement(c, '{a}e')
2261 f = SubElement(c, '{b}f')
2262 g = SubElement(c, 'g')
2263
2264 self.assertEquals(
2265 [a],
2266 list(a.getiterator('{a}a')))
2267 self.assertEquals(
2268 [],
2269 list(a.getiterator('{b}a')))
2270 self.assertEquals(
2271 [],
2272 list(a.getiterator('a')))
2273 self.assertEquals(
2274 [a,b,d,c,e,f,g],
2275 list(a.getiterator('*')))
2276 self.assertEquals(
2277 [f],
2278 list(c.getiterator('{b}*')))
2279 self.assertEquals(
2280 [d, f],
2281 list(a.getiterator('{b}*')))
2282 self.assertEquals(
2283 [g],
2284 list(a.getiterator('g')))
2285 self.assertEquals(
2286 [g],
2287 list(a.getiterator('{}g')))
2288 self.assertEquals(
2289 [g],
2290 list(a.getiterator('{}*')))
2291
2293 Element = self.etree.Element
2294 SubElement = self.etree.SubElement
2295
2296 a = Element('{a}a')
2297 b = SubElement(a, '{nsA}b')
2298 c = SubElement(b, '{nsB}b')
2299 d = SubElement(a, 'b')
2300 e = SubElement(a, '{nsA}e')
2301 f = SubElement(e, '{nsB}e')
2302 g = SubElement(e, 'e')
2303
2304 self.assertEquals(
2305 [b, c, d],
2306 list(a.getiterator('{*}b')))
2307 self.assertEquals(
2308 [e, f, g],
2309 list(a.getiterator('{*}e')))
2310 self.assertEquals(
2311 [a, b, c, d, e, f, g],
2312 list(a.getiterator('{*}*')))
2313
2315 Element = self.etree.Element
2316 Entity = self.etree.Entity
2317 SubElement = self.etree.SubElement
2318
2319 a = Element('a')
2320 b = SubElement(a, 'b')
2321 entity_b = Entity("TEST-b")
2322 b.append(entity_b)
2323
2324 self.assertEquals(
2325 [entity_b],
2326 list(a.getiterator(Entity)))
2327
2328 entity_a = Entity("TEST-a")
2329 a.append(entity_a)
2330
2331 self.assertEquals(
2332 [entity_b, entity_a],
2333 list(a.getiterator(Entity)))
2334
2335 self.assertEquals(
2336 [entity_b],
2337 list(b.getiterator(Entity)))
2338
2340 Element = self.etree.Element
2341 Comment = self.etree.Comment
2342 PI = self.etree.PI
2343 SubElement = self.etree.SubElement
2344
2345 a = Element('a')
2346 b = SubElement(a, 'b')
2347 a.append(Comment("test"))
2348 a.append(PI("pi", "content"))
2349 c = SubElement(a, 'c')
2350
2351 self.assertEquals(
2352 [a, b, c],
2353 list(a.getiterator(Element)))
2354
2356 # ElementTree iterates over everything here
2357 Element = self.etree.Element
2358 Comment = self.etree.Comment
2359 PI = self.etree.PI
2360 SubElement = self.etree.SubElement
2361
2362 a = Element('a')
2363 b = SubElement(a, 'b')
2364 a.append(Comment("test"))
2365 a.append(PI("pi", "content"))
2366 c = SubElement(a, 'c')
2367
2368 self.assertEquals(
2369 [a, b, c],
2370 list(a.getiterator('*')))
2371
2373 XML = self.etree.XML
2374 ElementTree = self.etree.ElementTree
2375 QName = self.etree.QName
2376 tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>')))
2377 self.assertEquals(tree.find(QName("c")), tree.getroot()[2])
2378
2380 XML = self.etree.XML
2381 ElementTree = self.etree.ElementTree
2382 QName = self.etree.QName
2383 tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>')))
2384 self.assertEquals(len(list(tree.findall(QName("c")))), 1)
2385
2387 XML = self.etree.XML
2388 ElementTree = self.etree.ElementTree
2389 QName = self.etree.QName
2390 tree = ElementTree(XML(
2391 _bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>')))
2392 self.assertEquals(len(list(tree.findall(QName("b")))), 2)
2393 self.assertEquals(len(list(tree.findall(QName("X", "b")))), 1)
2394
2396 XML = self.etree.XML
2397 root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>'))
2398 self.assertEquals(len(root.findall(".//{X}b")), 2)
2399 self.assertEquals(len(root.findall(".//{X}*")), 2)
2400 self.assertEquals(len(root.findall(".//b")), 3)
2401
2403 XML = self.etree.XML
2404 root = XML(_bytes('<a><b><c/></b><b/><c><b/><b/></c><b/></a>'))
2405 self.assertRaises(SyntaxError, root.findall, '')
2406 self.assertRaises(SyntaxError, root.findall, '//') # absolute path on Element
2407 self.assertRaises(SyntaxError, root.findall, './//')
2408
2410 etree = self.etree
2411 e = etree.Element('foo')
2412 for i in range(10):
2413 etree.SubElement(e, 'a%s' % i)
2414 for i in range(10):
2415 self.assertEquals(
2416 i,
2417 e.index(e[i]))
2418 self.assertEquals(
2419 3, e.index(e[3], 3))
2420 self.assertRaises(
2421 ValueError, e.index, e[3], 4)
2422 self.assertRaises(
2423 ValueError, e.index, e[3], 0, 2)
2424 self.assertRaises(
2425 ValueError, e.index, e[8], 0, -3)
2426 self.assertRaises(
2427 ValueError, e.index, e[8], -5, -3)
2428 self.assertEquals(
2429 8, e.index(e[8], 0, -1))
2430 self.assertEquals(
2431 8, e.index(e[8], -12, -1))
2432 self.assertEquals(
2433 0, e.index(e[0], -12, -1))
2434
2436 etree = self.etree
2437 e = etree.Element('foo')
2438 for i in range(10):
2439 el = etree.SubElement(e, 'a%s' % i)
2440 el.text = "text%d" % i
2441 el.tail = "tail%d" % i
2442
2443 child0 = e[0]
2444 child1 = e[1]
2445 child2 = e[2]
2446
2447 e.replace(e[0], e[1])
2448 self.assertEquals(
2449 9, len(e))
2450 self.assertEquals(
2451 child1, e[0])
2452 self.assertEquals(
2453 child1.text, "text1")
2454 self.assertEquals(
2455 child1.tail, "tail1")
2456 self.assertEquals(
2457 child0.tail, "tail0")
2458 self.assertEquals(
2459 child2, e[1])
2460
2461 e.replace(e[-1], e[0])
2462 self.assertEquals(
2463 child1, e[-1])
2464 self.assertEquals(
2465 child1.text, "text1")
2466 self.assertEquals(
2467 child1.tail, "tail1")
2468 self.assertEquals(
2469 child2, e[0])
2470
2472 etree = self.etree
2473 e = etree.Element('foo')
2474 for i in range(10):
2475 etree.SubElement(e, 'a%s' % i)
2476
2477 new_element = etree.Element("test")
2478 new_element.text = "TESTTEXT"
2479 new_element.tail = "TESTTAIL"
2480 child1 = e[1]
2481 e.replace(e[0], new_element)
2482 self.assertEquals(
2483 new_element, e[0])
2484 self.assertEquals(
2485 "TESTTEXT",
2486 e[0].text)
2487 self.assertEquals(
2488 "TESTTAIL",
2489 e[0].tail)
2490 self.assertEquals(
2491 child1, e[1])
2492
2494 Element = self.etree.Element
2495 SubElement = self.etree.SubElement
2496
2497 a = Element('a')
2498
2499 e = Element('e')
2500 f = Element('f')
2501 g = Element('g')
2502
2503 s = [e, f, g]
2504 a[::-1] = s
2505 self.assertEquals(
2506 [g, f, e],
2507 list(a))
2508
2510 Element = self.etree.Element
2511 SubElement = self.etree.SubElement
2512
2513 a = Element('a')
2514 b = SubElement(a, 'b')
2515 c = SubElement(a, 'c')
2516 d = SubElement(a, 'd')
2517 e = SubElement(a, 'e')
2518
2519 x = Element('x')
2520 y = Element('y')
2521
2522 a[1::2] = [x, y]
2523 self.assertEquals(
2524 [b, x, d, y],
2525 list(a))
2526
2528 Element = self.etree.Element
2529 SubElement = self.etree.SubElement
2530
2531 a = Element('a')
2532 b = SubElement(a, 'b')
2533 c = SubElement(a, 'c')
2534 d = SubElement(a, 'd')
2535 e = SubElement(a, 'e')
2536
2537 x = Element('x')
2538 y = Element('y')
2539
2540 a[1::-1] = [x, y]
2541 self.assertEquals(
2542 [y, x, d, e],
2543 list(a))
2544
2546 Element = self.etree.Element
2547 SubElement = self.etree.SubElement
2548
2549 a = Element('a')
2550 b = SubElement(a, 'b')
2551 c = SubElement(a, 'c')
2552 d = SubElement(a, 'd')
2553 e = SubElement(a, 'e')
2554
2555 x = Element('x')
2556 y = Element('y')
2557
2558 a[::-2] = [x, y]
2559 self.assertEquals(
2560 [b, y, d, x],
2561 list(a))
2562
2564 Element = self.etree.Element
2565 SubElement = self.etree.SubElement
2566 try:
2567 slice
2568 except NameError:
2569 print("slice() not found")
2570 return
2571
2572 a = Element('a')
2573 b = SubElement(a, 'b')
2574 c = SubElement(a, 'c')
2575 d = SubElement(a, 'd')
2576 e = SubElement(a, 'e')
2577
2578 x = Element('x')
2579 y = Element('y')
2580 z = Element('z')
2581
2582 self.assertRaises(
2583 ValueError,
2584 operator.setitem, a, slice(1,None,2), [x, y, z])
2585
2586 self.assertEquals(
2587 [b, c, d, e],
2588 list(a))
2589
2591 XML = self.etree.XML
2592 root = XML(_bytes('''<?xml version="1.0"?>
2593 <root><test>
2594
2595 <bla/></test>
2596 </root>
2597 '''))
2598
2599 self.assertEquals(
2600 [2, 2, 4],
2601 [ el.sourceline for el in root.getiterator() ])
2602
2604 parse = self.etree.parse
2605 tree = parse(fileInTestDir('include/test_xinclude.xml'))
2606
2607 self.assertEquals(
2608 [1, 2, 3],
2609 [ el.sourceline for el in tree.getiterator() ])
2610
2612 iterparse = self.etree.iterparse
2613 lines = [ el.sourceline for (event, el) in
2614 iterparse(fileInTestDir('include/test_xinclude.xml')) ]
2615
2616 self.assertEquals(
2617 [2, 3, 1],
2618 lines)
2619
2621 iterparse = self.etree.iterparse
2622 lines = [ el.sourceline for (event, el) in
2623 iterparse(fileInTestDir('include/test_xinclude.xml'),
2624 events=("start",)) ]
2625
2626 self.assertEquals(
2627 [1, 2, 3],
2628 lines)
2629
2631 Element = self.etree.Element
2632 SubElement = self.etree.SubElement
2633 el = Element("test")
2634 self.assertEquals(None, el.sourceline)
2635
2636 child = SubElement(el, "test")
2637 self.assertEquals(None, el.sourceline)
2638 self.assertEquals(None, child.sourceline)
2639
2641 etree = self.etree
2642 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
2643 docinfo = root.getroottree().docinfo
2644 self.assertEquals(docinfo.URL, "http://no/such/url")
2645
2647 etree = self.etree
2648 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
2649 docinfo = root.getroottree().docinfo
2650 self.assertEquals(docinfo.URL, "http://no/such/url")
2651 docinfo.URL = "https://secret/url"
2652 self.assertEquals(docinfo.URL, "https://secret/url")
2653
2655 etree = self.etree
2656 tree = etree.parse(BytesIO("<root/>"), base_url="http://no/such/url")
2657 docinfo = tree.docinfo
2658 self.assertEquals(docinfo.URL, "http://no/such/url")
2659
2661 etree = self.etree
2662 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
2663 base_url="http://no/such/url")
2664 docinfo = tree.docinfo
2665 self.assertEquals(docinfo.URL, "http://no/such/url")
2666
2668 etree = self.etree
2669 root = etree.HTML(_bytes("<html/>"), base_url="http://no/such/url")
2670 docinfo = root.getroottree().docinfo
2671 self.assertEquals(docinfo.URL, "http://no/such/url")
2672
2674 etree = self.etree
2675 xml_header = '<?xml version="1.0" encoding="ascii"?>'
2676 pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
2677 sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
2678 doctype_string = '<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id)
2679
2680 xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
2681
2682 tree = etree.parse(BytesIO(xml))
2683 docinfo = tree.docinfo
2684 self.assertEquals(docinfo.encoding, "ascii")
2685 self.assertEquals(docinfo.xml_version, "1.0")
2686 self.assertEquals(docinfo.public_id, pub_id)
2687 self.assertEquals(docinfo.system_url, sys_id)
2688 self.assertEquals(docinfo.root_name, 'html')
2689 self.assertEquals(docinfo.doctype, doctype_string)
2690
2692 etree = self.etree
2693 xml_header = '<?xml version="1.0" encoding="UTF-8"?>'
2694 sys_id = "some.dtd"
2695 doctype_string = '<!DOCTYPE html SYSTEM "%s">' % sys_id
2696 xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
2697
2698 tree = etree.parse(BytesIO(xml))
2699 docinfo = tree.docinfo
2700 self.assertEquals(docinfo.encoding, "UTF-8")
2701 self.assertEquals(docinfo.xml_version, "1.0")
2702 self.assertEquals(docinfo.public_id, None)
2703 self.assertEquals(docinfo.system_url, sys_id)
2704 self.assertEquals(docinfo.root_name, 'html')
2705 self.assertEquals(docinfo.doctype, doctype_string)
2706
2708 etree = self.etree
2709 xml = _bytes('<html><body></body></html>')
2710 tree = etree.parse(BytesIO(xml))
2711 docinfo = tree.docinfo
2712 self.assertEquals(docinfo.encoding, "UTF-8")
2713 self.assertEquals(docinfo.xml_version, "1.0")
2714 self.assertEquals(docinfo.public_id, None)
2715 self.assertEquals(docinfo.system_url, None)
2716 self.assertEquals(docinfo.root_name, 'html')
2717 self.assertEquals(docinfo.doctype, '')
2718
2720 etree = self.etree
2721 xml = _bytes('<!DOCTYPE root><root></root>')
2722 tree = etree.parse(BytesIO(xml))
2723 docinfo = tree.docinfo
2724 self.assertEquals(docinfo.encoding, "UTF-8")
2725 self.assertEquals(docinfo.xml_version, "1.0")
2726 self.assertEquals(docinfo.public_id, None)
2727 self.assertEquals(docinfo.system_url, None)
2728 self.assertEquals(docinfo.root_name, 'root')
2729 self.assertEquals(docinfo.doctype, '<!DOCTYPE root>')
2730
2732 etree = self.etree
2733 xml = _bytes('<!DOCTYPE root>\n<root/>')
2734 tree = etree.parse(BytesIO(xml))
2735 self.assertEquals(xml, etree.tostring(tree))
2736
2738 etree = self.etree
2739 pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
2740 sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
2741 doctype_string = _bytes('<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id))
2742
2743 xml = _bytes('<!DOCTYPE root>\n<root/>')
2744 tree = etree.parse(BytesIO(xml))
2745 self.assertEquals(xml.replace(_bytes('<!DOCTYPE root>'), doctype_string),
2746 etree.tostring(tree, doctype=doctype_string))
2747
2749 etree = self.etree
2750 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
2751 self.assertEquals(root.base, "http://no/such/url")
2752 self.assertEquals(
2753 root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
2754 root.base = "https://secret/url"
2755 self.assertEquals(root.base, "https://secret/url")
2756 self.assertEquals(
2757 root.get('{http://www.w3.org/XML/1998/namespace}base'),
2758 "https://secret/url")
2759
2761 etree = self.etree
2762 root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
2763 self.assertEquals(root.base, "http://no/such/url")
2764 self.assertEquals(
2765 root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
2766 root.set('{http://www.w3.org/XML/1998/namespace}base',
2767 "https://secret/url")
2768 self.assertEquals(root.base, "https://secret/url")
2769 self.assertEquals(
2770 root.get('{http://www.w3.org/XML/1998/namespace}base'),
2771 "https://secret/url")
2772
2774 etree = self.etree
2775 root = etree.HTML(_bytes("<html><body></body></html>"),
2776 base_url="http://no/such/url")
2777 self.assertEquals(root.base, "http://no/such/url")
2778
2780 etree = self.etree
2781 root = etree.HTML(_bytes('<html><head><base href="http://no/such/url"></head></html>'))
2782 self.assertEquals(root.base, "http://no/such/url")
2783
2785 # parse from a file object that returns unicode strings
2786 f = LargeFileLikeUnicode()
2787 tree = self.etree.parse(f)
2788 root = tree.getroot()
2789 self.assert_(root.tag.endswith('root'))
2790
2792 # check that DTDs that go in also go back out
2793 xml = _bytes('''\
2794 <!DOCTYPE test SYSTEM "test.dtd" [
2795 <!ENTITY entity "tasty">
2796 <!ELEMENT test (a)>
2797 <!ELEMENT a (#PCDATA)>
2798 ]>
2799 <test><a>test-test</a></test>\
2800 ''')
2801 tree = self.etree.parse(BytesIO(xml))
2802 self.assertEqual(self.etree.tostring(tree).replace(_bytes(" "), _bytes("")),
2803 xml.replace(_bytes(" "), _bytes("")))
2804
2806 Element = self.etree.Element
2807
2808 a = Element('a')
2809 self.assertRaises(ValueError, setattr, a, "text", 'ha\0ho')
2810 self.assertRaises(ValueError, setattr, a, "tail", 'ha\0ho')
2811
2812 self.assertRaises(ValueError, Element, 'ha\0ho')
2813
2815 Element = self.etree.Element
2816
2817 a = Element('a')
2818 self.assertRaises(ValueError, setattr, a, "text",
2819 _str('ha\0ho'))
2820 self.assertRaises(ValueError, setattr, a, "tail",
2821 _str('ha\0ho'))
2822
2823 self.assertRaises(ValueError, Element,
2824 _str('ha\0ho'))
2825
2827 Element = self.etree.Element
2828
2829 a = Element('a')
2830 self.assertRaises(ValueError, setattr, a, "text", 'ha\x07ho')
2831 self.assertRaises(ValueError, setattr, a, "text", 'ha\x02ho')
2832
2833 self.assertRaises(ValueError, setattr, a, "tail", 'ha\x07ho')
2834 self.assertRaises(ValueError, setattr, a, "tail", 'ha\x02ho')
2835
2836 self.assertRaises(ValueError, Element, 'ha\x07ho')
2837 self.assertRaises(ValueError, Element, 'ha\x02ho')
2838
2840 Element = self.etree.Element
2841
2842 a = Element('a')
2843 self.assertRaises(ValueError, setattr, a, "text",
2844 _str('ha\x07ho'))
2845 self.assertRaises(ValueError, setattr, a, "text",
2846 _str('ha\x02ho'))
2847
2848 self.assertRaises(ValueError, setattr, a, "tail",
2849 _str('ha\x07ho'))
2850 self.assertRaises(ValueError, setattr, a, "tail",
2851 _str('ha\x02ho'))
2852
2853 self.assertRaises(ValueError, Element,
2854 _str('ha\x07ho'))
2855 self.assertRaises(ValueError, Element,
2856 _str('ha\x02ho'))
2857
2859 Element = self.etree.Element
2860
2861 a = Element('a')
2862 self.assertRaises(ValueError, setattr, a, "text",
2863 _str('ha\u1234\x07ho'))
2864 self.assertRaises(ValueError, setattr, a, "text",
2865 _str('ha\u1234\x02ho'))
2866
2867 self.assertRaises(ValueError, setattr, a, "tail",
2868 _str('ha\u1234\x07ho'))
2869 self.assertRaises(ValueError, setattr, a, "tail",
2870 _str('ha\u1234\x02ho'))
2871
2872 self.assertRaises(ValueError, Element,
2873 _str('ha\u1234\x07ho'))
2874 self.assertRaises(ValueError, Element,
2875 _str('ha\u1234\x02ho'))
2876
2878 # ElementTree fails to serialize this
2879 tostring = self.etree.tostring
2880 Element = self.etree.Element
2881 SubElement = self.etree.SubElement
2882
2883 a = Element('a')
2884 b = SubElement(a, 'b')
2885 c = SubElement(a, 'c')
2886
2887 result = tostring(a, encoding='UTF-16')
2888 self.assertEquals(_bytes('<a><b></b><c></c></a>'),
2889 canonicalize(result))
2890
2892 # ElementTree raises an AssertionError here
2893 tostring = self.etree.tostring
2894 self.assertRaises(TypeError, self.etree.tostring, None)
2895
2897 tostring = self.etree.tostring
2898 Element = self.etree.Element
2899 SubElement = self.etree.SubElement
2900
2901 a = Element('a')
2902 b = SubElement(a, 'b')
2903 c = SubElement(a, 'c')
2904
2905 result = tostring(a)
2906 self.assertEquals(result, _bytes("<a><b/><c/></a>"))
2907
2908 result = tostring(a, pretty_print=False)
2909 self.assertEquals(result, _bytes("<a><b/><c/></a>"))
2910
2911 result = tostring(a, pretty_print=True)
2912 self.assertEquals(result, _bytes("<a>\n <b/>\n <c/>\n</a>\n"))
2913
2915 tostring = self.etree.tostring
2916 Element = self.etree.Element
2917 SubElement = self.etree.SubElement
2918
2919 a = Element('a')
2920 a.tail = "aTAIL"
2921 b = SubElement(a, 'b')
2922 b.tail = "bTAIL"
2923 c = SubElement(a, 'c')
2924
2925 result = tostring(a)
2926 self.assertEquals(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
2927
2928 result = tostring(a, with_tail=False)
2929 self.assertEquals(result, _bytes("<a><b/>bTAIL<c/></a>"))
2930
2931 result = tostring(a, with_tail=True)
2932 self.assertEquals(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
2933
2935 tostring = self.etree.tostring
2936 XML = self.etree.XML
2937 ElementTree = self.etree.ElementTree
2938 Element = self.etree.Element
2939
2940 tree = Element("root").getroottree()
2941 self.assertEquals(None, tree.docinfo.standalone)
2942
2943 tree = XML(_bytes("<root/>")).getroottree()
2944 self.assertEquals(None, tree.docinfo.standalone)
2945
2946 tree = XML(_bytes(
2947 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"
2948 )).getroottree()
2949 self.assertEquals(True, tree.docinfo.standalone)
2950
2951 tree = XML(_bytes(
2952 "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>"
2953 )).getroottree()
2954 self.assertEquals(False, tree.docinfo.standalone)
2955
2957 tostring = self.etree.tostring
2958 XML = self.etree.XML
2959 ElementTree = self.etree.ElementTree
2960
2961 root = XML(_bytes("<root/>"))
2962
2963 tree = ElementTree(root)
2964 self.assertEquals(None, tree.docinfo.standalone)
2965
2966 result = tostring(root, xml_declaration=True, encoding="ASCII")
2967 self.assertEquals(result, _bytes(
2968 "<?xml version='1.0' encoding='ASCII'?>\n<root/>"))
2969
2970 result = tostring(root, xml_declaration=True, encoding="ASCII",
2971 standalone=True)
2972 self.assertEquals(result, _bytes(
2973 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"))
2974
2975 tree = ElementTree(XML(result))
2976 self.assertEquals(True, tree.docinfo.standalone)
2977
2978 result = tostring(root, xml_declaration=True, encoding="ASCII",
2979 standalone=False)
2980 self.assertEquals(result, _bytes(
2981 "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>"))
2982
2983 tree = ElementTree(XML(result))
2984 self.assertEquals(False, tree.docinfo.standalone)
2985
2987 tostring = self.etree.tostring
2988 XML = self.etree.XML
2989 ElementTree = self.etree.ElementTree
2990
2991 root = XML(_bytes(
2992 "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>\n<root/>"))
2993
2994 tree = ElementTree(root)
2995 self.assertEquals(True, tree.docinfo.standalone)
2996
2997 result = tostring(root, xml_declaration=True, encoding="ASCII")
2998 self.assertEquals(result, _bytes(
2999 "<?xml version='1.0' encoding='ASCII'?>\n<root/>"))
3000
3001 result = tostring(root, xml_declaration=True, encoding="ASCII",
3002 standalone=True)
3003 self.assertEquals(result, _bytes(
3004 "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"))
3005
3007 tostring = self.etree.tostring
3008 Element = self.etree.Element
3009 SubElement = self.etree.SubElement
3010
3011 a = Element('a')
3012 a.text = "A"
3013 a.tail = "tail"
3014 b = SubElement(a, 'b')
3015 b.text = "B"
3016 b.tail = _str("Søk på nettet")
3017 c = SubElement(a, 'c')
3018 c.text = "C"
3019
3020 result = tostring(a, method="text", encoding="UTF-16")
3021
3022 self.assertEquals(_str('ABSøk på nettetCtail').encode("UTF-16"),
3023 result)
3024
3026 tostring = self.etree.tostring
3027 Element = self.etree.Element
3028 SubElement = self.etree.SubElement
3029
3030 a = Element('a')
3031 a.text = _str('Søk på nettetA')
3032 a.tail = "tail"
3033 b = SubElement(a, 'b')
3034 b.text = "B"
3035 b.tail = _str('Søk på nettetB')
3036 c = SubElement(a, 'c')
3037 c.text = "C"
3038
3039 self.assertRaises(UnicodeEncodeError,
3040 tostring, a, method="text")
3041
3042 self.assertEquals(
3043 _str('Søk på nettetABSøk på nettetBCtail').encode('utf-8'),
3044 tostring(a, encoding="UTF-8", method="text"))
3045
3047 tounicode = self.etree.tounicode
3048 Element = self.etree.Element
3049 SubElement = self.etree.SubElement
3050
3051 a = Element('a')
3052 b = SubElement(a, 'b')
3053 c = SubElement(a, 'c')
3054
3055 self.assert_(isinstance(tounicode(a), _unicode))
3056 self.assertEquals(_bytes('<a><b></b><c></c></a>'),
3057 canonicalize(tounicode(a)))
3058
3060 tounicode = self.etree.tounicode
3061 Element = self.etree.Element
3062 SubElement = self.etree.SubElement
3063
3064 a = Element('a')
3065 b = SubElement(a, 'b')
3066 c = SubElement(a, 'c')
3067 d = SubElement(c, 'd')
3068 self.assert_(isinstance(tounicode(b), _unicode))
3069 self.assert_(isinstance(tounicode(c), _unicode))
3070 self.assertEquals(_bytes('<b></b>'),
3071 canonicalize(tounicode(b)))
3072 self.assertEquals(_bytes('<c><d></d></c>'),
3073 canonicalize(tounicode(c)))
3074
3078
3080 tounicode = self.etree.tounicode
3081 Element = self.etree.Element
3082 SubElement = self.etree.SubElement
3083
3084 a = Element('a')
3085 b = SubElement(a, 'b')
3086 c = SubElement(a, 'c')
3087 d = SubElement(c, 'd')
3088 b.tail = 'Foo'
3089
3090 self.assert_(isinstance(tounicode(b), _unicode))
3091 self.assert_(tounicode(b) == '<b/>Foo' or
3092 tounicode(b) == '<b />Foo')
3093
3095 tounicode = self.etree.tounicode
3096 Element = self.etree.Element
3097 SubElement = self.etree.SubElement
3098
3099 a = Element('a')
3100 b = SubElement(a, 'b')
3101 c = SubElement(a, 'c')
3102
3103 result = tounicode(a)
3104 self.assertEquals(result, "<a><b/><c/></a>")
3105
3106 result = tounicode(a, pretty_print=False)
3107 self.assertEquals(result, "<a><b/><c/></a>")
3108
3109 result = tounicode(a, pretty_print=True)
3110 self.assertEquals(result, "<a>\n <b/>\n <c/>\n</a>\n")
3111
3113 tostring = self.etree.tostring
3114 Element = self.etree.Element
3115 SubElement = self.etree.SubElement
3116
3117 a = Element('a')
3118 b = SubElement(a, 'b')
3119 c = SubElement(a, 'c')
3120
3121 self.assert_(isinstance(tostring(a, encoding=_unicode), _unicode))
3122 self.assertEquals(_bytes('<a><b></b><c></c></a>'),
3123 canonicalize(tostring(a, encoding=_unicode)))
3124
3126 tostring = self.etree.tostring
3127 Element = self.etree.Element
3128 SubElement = self.etree.SubElement
3129
3130 a = Element('a')
3131 b = SubElement(a, 'b')
3132 c = SubElement(a, 'c')
3133 d = SubElement(c, 'd')
3134 self.assert_(isinstance(tostring(b, encoding=_unicode), _unicode))
3135 self.assert_(isinstance(tostring(c, encoding=_unicode), _unicode))
3136 self.assertEquals(_bytes('<b></b>'),
3137 canonicalize(tostring(b, encoding=_unicode)))
3138 self.assertEquals(_bytes('<c><d></d></c>'),
3139 canonicalize(tostring(c, encoding=_unicode)))
3140
3142 tostring = self.etree.tostring
3143 self.assertRaises(TypeError, self.etree.tostring,
3144 None, encoding=_unicode)
3145
3147 tostring = self.etree.tostring
3148 Element = self.etree.Element
3149 SubElement = self.etree.SubElement
3150
3151 a = Element('a')
3152 b = SubElement(a, 'b')
3153 c = SubElement(a, 'c')
3154 d = SubElement(c, 'd')
3155 b.tail = 'Foo'
3156
3157 self.assert_(isinstance(tostring(b, encoding=_unicode), _unicode))
3158 self.assert_(tostring(b, encoding=_unicode) == '<b/>Foo' or
3159 tostring(b, encoding=_unicode) == '<b />Foo')
3160
3162 tostring = self.etree.tostring
3163 Element = self.etree.Element
3164 SubElement = self.etree.SubElement
3165
3166 a = Element('a')
3167 b = SubElement(a, 'b')
3168 c = SubElement(a, 'c')
3169
3170 result = tostring(a, encoding=_unicode)
3171 self.assertEquals(result, "<a><b/><c/></a>")
3172
3173 result = tostring(a, encoding=_unicode, pretty_print=False)
3174 self.assertEquals(result, "<a><b/><c/></a>")
3175
3176 result = tostring(a, encoding=_unicode, pretty_print=True)
3177 self.assertEquals(result, "<a>\n <b/>\n <c/>\n</a>\n")
3178
3179 # helper methods
3180
3182 """Write out element for comparison.
3183 """
3184 ElementTree = self.etree.ElementTree
3185 f = BytesIO()
3186 tree = ElementTree(element=element)
3187 tree.write(f, encoding=encoding, compression=compression)
3188 data = f.getvalue()
3189 if compression:
3190 data = zlib.decompress(data)
3191 return canonicalize(data)
3192
3193
3196 filename = fileInTestDir('test_broken.xml')
3197 root = etree.XML(_bytes('''\
3198 <doc xmlns:xi="http://www.w3.org/2001/XInclude">
3199 <xi:include href="%s" parse="text"/>
3200 </doc>
3201 ''' % filename))
3202 old_text = root.text
3203 content = read_file(filename)
3204 old_tail = root[0].tail
3205
3206 self.include( etree.ElementTree(root) )
3207 self.assertEquals(old_text + content + old_tail,
3208 root.text)
3209
3211 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'))
3212 self.assertNotEquals(
3213 'a',
3214 tree.getroot()[1].tag)
3215 # process xincludes
3216 self.include( tree )
3217 # check whether we find it replaced with included data
3218 self.assertEquals(
3219 'a',
3220 tree.getroot()[1].tag)
3221
3223 class res(etree.Resolver):
3224 include_text = read_file(fileInTestDir('test.xml'))
3225 called = {}
3226 def resolve(self, url, id, context):
3227 if url.endswith(".dtd"):
3228 self.called["dtd"] = True
3229 return self.resolve_filename(
3230 fileInTestDir('test.dtd'), context)
3231 elif url.endswith("test_xinclude.xml"):
3232 self.called["input"] = True
3233 return None # delegate to default resolver
3234 else:
3235 self.called["include"] = True
3236 return self.resolve_string(self.include_text, context)
3237
3238 res_instance = res()
3239 parser = etree.XMLParser(load_dtd = True)
3240 parser.resolvers.add(res_instance)
3241
3242 tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
3243 parser = parser)
3244
3245 self.include(tree)
3246
3247 called = list(res_instance.called.items())
3248 called.sort()
3249 self.assertEquals(
3250 [("dtd", True), ("include", True), ("input", True)],
3251 called)
3252
3256
3257
3262
3263
3266 tree = self.parse(_bytes('<a><b/></a>'))
3267 f = BytesIO()
3268 tree.write_c14n(f)
3269 s = f.getvalue()
3270 self.assertEquals(_bytes('<a><b></b></a>'),
3271 s)
3272
3274 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
3275 f = BytesIO()
3276 tree.write_c14n(f, compression=9)
3277 gzfile = gzip.GzipFile(fileobj=BytesIO(f.getvalue()))
3278 try:
3279 s = gzfile.read()
3280 finally:
3281 gzfile.close()
3282 self.assertEquals(_bytes('<a>'+'<b></b>'*200+'</a>'),
3283 s)
3284
3286 tree = self.parse(_bytes('<a><b/></a>'))
3287 handle, filename = tempfile.mkstemp()
3288 try:
3289 tree.write_c14n(filename)
3290 data = read_file(filename, 'rb')
3291 finally:
3292 os.close(handle)
3293 os.remove(filename)
3294 self.assertEquals(_bytes('<a><b></b></a>'),
3295 data)
3296
3298 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
3299 handle, filename = tempfile.mkstemp()
3300 try:
3301 tree.write_c14n(filename, compression=9)
3302 f = gzip.open(filename, 'rb')
3303 try:
3304 data = f.read()
3305 finally:
3306 f.close()
3307 finally:
3308 os.close(handle)
3309 os.remove(filename)
3310 self.assertEquals(_bytes('<a>'+'<b></b>'*200+'</a>'),
3311 data)
3312
3314 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
3315 f = BytesIO()
3316 tree.write_c14n(f)
3317 s = f.getvalue()
3318 self.assertEquals(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
3319 s)
3320 f = BytesIO()
3321 tree.write_c14n(f, with_comments=True)
3322 s = f.getvalue()
3323 self.assertEquals(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
3324 s)
3325 f = BytesIO()
3326 tree.write_c14n(f, with_comments=False)
3327 s = f.getvalue()
3328 self.assertEquals(_bytes('<a><b></b></a>'),
3329 s)
3330
3332 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
3333 s = etree.tostring(tree, method='c14n')
3334 self.assertEquals(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
3335 s)
3336 s = etree.tostring(tree, method='c14n', with_comments=True)
3337 self.assertEquals(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
3338 s)
3339 s = etree.tostring(tree, method='c14n', with_comments=False)
3340 self.assertEquals(_bytes('<a><b></b></a>'),
3341 s)
3342
3344 tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
3345 s = etree.tostring(tree.getroot(), method='c14n')
3346 self.assertEquals(_bytes('<a><!--ho--><b></b></a>'),
3347 s)
3348 s = etree.tostring(tree.getroot(), method='c14n', with_comments=True)
3349 self.assertEquals(_bytes('<a><!--ho--><b></b></a>'),
3350 s)
3351 s = etree.tostring(tree.getroot(), method='c14n', with_comments=False)
3352 self.assertEquals(_bytes('<a><b></b></a>'),
3353 s)
3354
3356 tree = self.parse(_bytes(
3357 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
3358 f = BytesIO()
3359 tree.write_c14n(f)
3360 s = f.getvalue()
3361 self.assertEquals(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
3362 s)
3363 f = BytesIO()
3364 tree.write_c14n(f, exclusive=False)
3365 s = f.getvalue()
3366 self.assertEquals(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
3367 s)
3368 f = BytesIO()
3369 tree.write_c14n(f, exclusive=True)
3370 s = f.getvalue()
3371 self.assertEquals(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
3372 s)
3373
3374 f = BytesIO()
3375 tree.write_c14n(f, exclusive=True, inclusive_ns_prefixes=['z'])
3376 s = f.getvalue()
3377 self.assertEquals(_bytes('<a xmlns="http://abc" xmlns:z="http://cde"><z:b></z:b></a>'),
3378 s)
3379
3381 tree = self.parse(_bytes(
3382 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
3383 s = etree.tostring(tree, method='c14n')
3384 self.assertEquals(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
3385 s)
3386 s = etree.tostring(tree, method='c14n', exclusive=False)
3387 self.assertEquals(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
3388 s)
3389 s = etree.tostring(tree, method='c14n', exclusive=True)
3390 self.assertEquals(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
3391 s)
3392
3393 s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['y'])
3394 self.assertEquals(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd"><z:b xmlns:z="http://cde"></z:b></a>'),
3395 s)
3396
3398 tree = self.parse(_bytes(
3399 '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
3400 s = etree.tostring(tree.getroot(), method='c14n')
3401 self.assertEquals(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
3402 s)
3403 s = etree.tostring(tree.getroot(), method='c14n', exclusive=False)
3404 self.assertEquals(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
3405 s)
3406 s = etree.tostring(tree.getroot(), method='c14n', exclusive=True)
3407 self.assertEquals(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
3408 s)
3409
3410 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=False)
3411 self.assertEquals(_bytes('<z:b xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'),
3412 s)
3413 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True)
3414 self.assertEquals(_bytes('<z:b xmlns:z="http://cde"></z:b>'),
3415 s)
3416
3417 s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True, inclusive_ns_prefixes=['y'])
3418 self.assertEquals(_bytes('<z:b xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'),
3419 s)
3420
3422 """ Regression test to fix memory allocation issues (use 3+ inclusive NS spaces)"""
3423 tree = self.parse(_bytes(
3424 '<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
3425
3426 s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['x', 'y', 'z'])
3427 self.assertEquals(_bytes('<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
3428 s)
3429
3430
3433 tree = self.parse(_bytes('<a><b/></a>'))
3434 f = BytesIO()
3435 tree.write(f)
3436 s = f.getvalue()
3437 self.assertEquals(_bytes('<a><b/></a>'),
3438 s)
3439
3441 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
3442 f = BytesIO()
3443 tree.write(f, compression=9)
3444 gzfile = gzip.GzipFile(fileobj=BytesIO(f.getvalue()))
3445 try:
3446 s = gzfile.read()
3447 finally:
3448 gzfile.close()
3449 self.assertEquals(_bytes('<a>'+'<b/>'*200+'</a>'),
3450 s)
3451
3453 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
3454 f = BytesIO()
3455 tree.write(f, compression=0)
3456 s0 = f.getvalue()
3457
3458 f = BytesIO()
3459 tree.write(f)
3460 self.assertEquals(f.getvalue(), s0)
3461
3462 f = BytesIO()
3463 tree.write(f, compression=1)
3464 s = f.getvalue()
3465 self.assert_(len(s) <= len(s0))
3466 gzfile = gzip.GzipFile(fileobj=BytesIO(s))
3467 try:
3468 s1 = gzfile.read()
3469 finally:
3470 gzfile.close()
3471
3472 f = BytesIO()
3473 tree.write(f, compression=9)
3474 s = f.getvalue()
3475 self.assert_(len(s) <= len(s0))
3476 gzfile = gzip.GzipFile(fileobj=BytesIO(s))
3477 try:
3478 s9 = gzfile.read()
3479 finally:
3480 gzfile.close()
3481
3482 self.assertEquals(_bytes('<a>'+'<b/>'*200+'</a>'),
3483 s0)
3484 self.assertEquals(_bytes('<a>'+'<b/>'*200+'</a>'),
3485 s1)
3486 self.assertEquals(_bytes('<a>'+'<b/>'*200+'</a>'),
3487 s9)
3488
3490 tree = self.parse(_bytes('<a><b/></a>'))
3491 handle, filename = tempfile.mkstemp()
3492 try:
3493 tree.write(filename)
3494 data = read_file(filename, 'rb')
3495 finally:
3496 os.close(handle)
3497 os.remove(filename)
3498 self.assertEquals(_bytes('<a><b/></a>'),
3499 data)
3500
3502 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
3503 handle, filename = tempfile.mkstemp()
3504 try:
3505 tree.write(filename, compression=9)
3506 f = gzip.open(filename, 'rb')
3507 try:
3508 data = f.read()
3509 finally:
3510 f.close()
3511 finally:
3512 os.close(handle)
3513 os.remove(filename)
3514 self.assertEquals(_bytes('<a>'+'<b/>'*200+'</a>'),
3515 data)
3516
3518 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
3519 handle, filename = tempfile.mkstemp()
3520 try:
3521 tree.write(filename, compression=9)
3522 data = etree.tostring(etree.parse(filename))
3523 finally:
3524 os.close(handle)
3525 os.remove(filename)
3526 self.assertEquals(_bytes('<a>'+'<b/>'*200+'</a>'),
3527 data)
3528
3530 tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
3531 handle, filename = tempfile.mkstemp()
3532 try:
3533 tree.write(filename, compression=9)
3534 data = etree.tostring(etree.parse(
3535 gzip.GzipFile(filename)))
3536 finally:
3537 os.close(handle)
3538 os.remove(filename)
3539 self.assertEquals(_bytes('<a>'+'<b/>'*200+'</a>'),
3540 data)
3541
3543 etree = etree
3544
3546 parse = self.etree.parse
3547 f = BytesIO('<a><b></c></b></a>')
3548 self.etree.clear_error_log()
3549 try:
3550 parse(f)
3551 logs = None
3552 except SyntaxError:
3553 e = sys.exc_info()[1]
3554 logs = e.error_log
3555 f.close()
3556 self.assert_([ log for log in logs
3557 if 'mismatch' in log.message ])
3558 self.assert_([ log for log in logs
3559 if 'PARSER' in log.domain_name])
3560 self.assert_([ log for log in logs
3561 if 'ERR_TAG_NAME_MISMATCH' in log.type_name ])
3562 self.assert_([ log for log in logs
3563 if 1 == log.line ])
3564 self.assert_([ log for log in logs
3565 if 15 == log.column ])
3566
3577
3578 self.etree.use_global_python_log(Logger())
3579 f = BytesIO('<a><b></c></b></a>')
3580 try:
3581 parse(f)
3582 except SyntaxError:
3583 pass
3584 f.close()
3585
3586 self.assert_([ message for message in messages
3587 if 'mismatch' in message ])
3588 self.assert_([ message for message in messages
3589 if ':PARSER:' in message])
3590 self.assert_([ message for message in messages
3591 if ':ERR_TAG_NAME_MISMATCH:' in message ])
3592 self.assert_([ message for message in messages
3593 if ':1:15:' in message ])
3594
3596 suite = unittest.TestSuite()
3597 suite.addTests([unittest.makeSuite(ETreeOnlyTestCase)])
3598 suite.addTests([unittest.makeSuite(ETreeXIncludeTestCase)])
3599 suite.addTests([unittest.makeSuite(ElementIncludeTestCase)])
3600 suite.addTests([unittest.makeSuite(ETreeC14NTestCase)])
3601 suite.addTests([unittest.makeSuite(ETreeWriteTestCase)])
3602 suite.addTests([unittest.makeSuite(ETreeErrorLogTest)])
3603 suite.addTests(
3604 [make_doctest('../../../doc/tutorial.txt')])
3605 suite.addTests(
3606 [make_doctest('../../../doc/api.txt')])
3607 suite.addTests(
3608 [make_doctest('../../../doc/FAQ.txt')])
3609 suite.addTests(
3610 [make_doctest('../../../doc/parsing.txt')])
3611 suite.addTests(
3612 [make_doctest('../../../doc/resolvers.txt')])
3613 return suite
3614
3615 if __name__ == '__main__':
3616 print('to test use test.py %s' % __file__)
3617
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Mon Oct 8 19:46:23 2012 | http://epydoc.sourceforge.net |