Package lxml :: Package tests :: Module test_etree |
[hide private]
[frames] | no frames]

# Source Code for Module lxml.tests.test_etree

       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  from __future__ import absolute_import
      11
      12  import os.path
      13  import unittest
      14  import copy
      15  import sys
      16  import re
      17  import gc
      18  import operator
      19  import tempfile
      20  import textwrap
      21  import zlib
      22  import gzip
      23  from contextlib import closing, contextmanager
      24
      25  from .common_imports import etree, StringIO, BytesIO, HelperTestCase
      26  from .common_imports import fileInTestDir, fileUrlInTestDir, read_file, path2url
      27  from .common_imports import SillyFileLike, LargeFileLikeUnicode, doctest, make_doctest
      28  from .common_imports import canonicalize, _str, _bytes
      29
      30  print("")
      31  print("TESTED VERSION: %s" % etree.__version__)
      32  print("    Python:           " + repr(sys.version_info))
      33  print("    lxml.etree:       " + repr(etree.LXML_VERSION))
      34  print("    libxml used:      " + repr(etree.LIBXML_VERSION))
      35  print("    libxml compiled:  " + repr(etree.LIBXML_COMPILED_VERSION))
      36  print("    libxslt used:     " + repr(etree.LIBXSLT_VERSION))
      37  print("    libxslt compiled: " + repr(etree.LIBXSLT_COMPILED_VERSION))
      38  print("")
      39
      40  try:
      41      _unicode = unicode
      42  except NameError:
      43      # Python 3
      44      _unicode = str
      45
      46
      47  @contextmanager
      48 -def tmpfile():
      49      handle, filename = tempfile.mkstemp()
      50      try:
      51          yield filename
      52      finally:
      53          os.close(handle)
      54          os.remove(filename)
      55
      56
      57 -class ETreeOnlyTestCase(HelperTestCase):
      58      """Tests only for etree, not ElementTree"""
      59      etree = etree
      60
      61 -    def test_version(self):
      62          self.assertTrue(isinstance(etree.__version__, _unicode))
      63          self.assertTrue(isinstance(etree.LXML_VERSION, tuple))
      64          self.assertEqual(len(etree.LXML_VERSION), 4)
      65          self.assertTrue(isinstance(etree.LXML_VERSION[0], int))
      66          self.assertTrue(isinstance(etree.LXML_VERSION[1], int))
      67          self.assertTrue(isinstance(etree.LXML_VERSION[2], int))
      68          self.assertTrue(isinstance(etree.LXML_VERSION[3], int))
      69          self.assertTrue(etree.__version__.startswith(
      70              str(etree.LXML_VERSION[0])))
      71
      72 -    def test_c_api(self):
      73          if hasattr(self.etree, '__pyx_capi__'):
      74              # newer Pyrex compatible C-API
      75              self.assertTrue(isinstance(self.etree.__pyx_capi__, dict))
      76              self.assertTrue(len(self.etree.__pyx_capi__) > 0)
      77          else:
      78              # older C-API mechanism
      79              self.assertTrue(hasattr(self.etree, '_import_c_api'))
      80
      81 -    def test_include_paths(self):
      82          import lxml
      83          includes = lxml.get_include()
      84          self.assertTrue(includes)
      85          self.assertTrue(len(includes) >= 2)
      86          self.assertTrue(os.path.join(os.path.dirname(lxml.__file__), 'includes') in includes,
      87                          includes)
      88
      89 -    def test_element_names(self):
      90          Element = self.etree.Element
      91          el = Element('name')
      92          self.assertEqual(el.tag, 'name')
      93          el = Element('{}name')
      94          self.assertEqual(el.tag, 'name')
      95
      96 -    def test_element_name_empty(self):
      97          Element = self.etree.Element
      98          el = Element('name')
      99          self.assertRaises(ValueError, Element, '{}')
     100          self.assertRaises(ValueError, setattr, el, 'tag', '{}')
     101
     102          self.assertRaises(ValueError, Element, '{test}')
     103          self.assertRaises(ValueError, setattr, el, 'tag', '{test}')
     104
     105 -    def test_element_name_colon(self):
     106          Element = self.etree.Element
     107          self.assertRaises(ValueError, Element, 'p:name')
     108          self.assertRaises(ValueError, Element, '{test}p:name')
     109
     110          el = Element('name')
     111          self.assertRaises(ValueError, setattr, el, 'tag', 'p:name')
     112
     113 -    def test_element_name_quote(self):
     114          Element = self.etree.Element
     115          self.assertRaises(ValueError, Element, "p'name")
     116          self.assertRaises(ValueError, Element, 'p"name')
     117
     118          self.assertRaises(ValueError, Element, "{test}p'name")
     119          self.assertRaises(ValueError, Element, '{test}p"name')
     120
     121          el = Element('name')
     122          self.assertRaises(ValueError, setattr, el, 'tag', "p'name")
     123          self.assertRaises(ValueError, setattr, el, 'tag', 'p"name')
     124
     125 -    def test_element_name_space(self):
     126          Element = self.etree.Element
     127          self.assertRaises(ValueError, Element, ' name ')
     128          self.assertRaises(ValueError, Element, 'na me')
     129          self.assertRaises(ValueError, Element, '{test} name')
     130
     131          el = Element('name')
     132          self.assertRaises(ValueError, setattr, el, 'tag', ' name ')
     133
     134 -    def test_subelement_name_empty(self):
     135          Element = self.etree.Element
     136          SubElement = self.etree.SubElement
     137
     138          el = Element('name')
     139          self.assertRaises(ValueError, SubElement, el, '{}')
     140          self.assertRaises(ValueError, SubElement, el, '{test}')
     141
     142 -    def test_subelement_name_colon(self):
     143          Element = self.etree.Element
     144          SubElement = self.etree.SubElement
     145
     146          el = Element('name')
     147          self.assertRaises(ValueError, SubElement, el, 'p:name')
     148          self.assertRaises(ValueError, SubElement, el, '{test}p:name')
     149
     150 -    def test_subelement_name_quote(self):
     151          Element = self.etree.Element
     152          SubElement = self.etree.SubElement
     153
     154          el = Element('name')
     155          self.assertRaises(ValueError, SubElement, el, "p'name")
     156          self.assertRaises(ValueError, SubElement, el, "{test}p'name")
     157
     158          self.assertRaises(ValueError, SubElement, el, 'p"name')
     159          self.assertRaises(ValueError, SubElement, el, '{test}p"name')
     160
     161 -    def test_subelement_name_space(self):
     162          Element = self.etree.Element
     163          SubElement = self.etree.SubElement
     164
     165          el = Element('name')
     166          self.assertRaises(ValueError, SubElement, el, ' name ')
     167          self.assertRaises(ValueError, SubElement, el, 'na me')
     168          self.assertRaises(ValueError, SubElement, el, '{test} name')
     169
     170 -    def test_subelement_attribute_invalid(self):
     171          Element = self.etree.Element
     172          SubElement = self.etree.SubElement
     173
     174          el = Element('name')
     175          self.assertRaises(ValueError, SubElement, el, 'name', {'a b c' : 'abc'})
     176          self.assertRaises(ValueError, SubElement, el, 'name', {'a' : 'a\0\n'})
     177          self.assertEqual(0, len(el))
     178
     179 -    def test_qname_empty(self):
     180          QName = self.etree.QName
     181          self.assertRaises(ValueError, QName, '')
     182          self.assertRaises(ValueError, QName, 'test', '')
     183
     184 -    def test_qname_colon(self):
     185          QName = self.etree.QName
     186          self.assertRaises(ValueError, QName, 'p:name')
     187          self.assertRaises(ValueError, QName, 'test', 'p:name')
     188
     189 -    def test_qname_space(self):
     190          QName = self.etree.QName
     191          self.assertRaises(ValueError, QName, ' name ')
     192          self.assertRaises(ValueError, QName, 'na me')
     193          self.assertRaises(ValueError, QName, 'test', ' name')
     194
     195 -    def test_qname_namespace_localname(self):
     196          # ET doesn't have namespace/localname properties on QNames
     197          QName = self.etree.QName
     198          namespace, localname = 'http://myns', 'a'
     199          qname = QName(namespace, localname)
     200          self.assertEqual(namespace, qname.namespace)
     201          self.assertEqual(localname, qname.localname)
     202
     203 -    def test_qname_element(self):
     204          # ET doesn't have namespace/localname properties on QNames
     205          QName = self.etree.QName
     206          qname1 = QName('http://myns', 'a')
     207          a = self.etree.Element(qname1, nsmap={'p' : 'http://myns'})
     208
     209          qname2 = QName(a)
     210          self.assertEqual(a.tag, qname1.text)
     211          self.assertEqual(qname1.text, qname2.text)
     212          self.assertEqual(qname1, qname2)
     213
     214 -    def test_qname_text_resolve(self):
     215          # ET doesn't resove QNames as text values
     216          etree = self.etree
     217          qname = etree.QName('http://myns', 'a')
     218          a = etree.Element(qname, nsmap={'p' : 'http://myns'})
     219          a.text = qname
     220
     221          self.assertEqual("p:a", a.text)
     222
     223 -    def test_nsmap_prefix_invalid(self):
     224          etree = self.etree
     225          self.assertRaises(ValueError,
     226                            etree.Element, "root", nsmap={'"' : 'testns'})
     227          self.assertRaises(ValueError,
     228                            etree.Element, "root", nsmap={'&' : 'testns'})
     229          self.assertRaises(ValueError,
     230                            etree.Element, "root", nsmap={'a:b' : 'testns'})
     231
     232 -    def test_attribute_has_key(self):
     233          # ET in Py 3.x has no "attrib.has_key()" method
     234          XML = self.etree.XML
     235
     236          root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
     237          self.assertEqual(
     238              True, root.attrib.has_key('bar'))
     239          self.assertEqual(
     240              False, root.attrib.has_key('baz'))
     241          self.assertEqual(
     242              False, root.attrib.has_key('hah'))
     243          self.assertEqual(
     244              True,
     245              root.attrib.has_key('{http://ns.codespeak.net/test}baz'))
     246
     247 -    def test_attribute_set(self):
     248          Element = self.etree.Element
     249          root = Element("root")
     250          root.set("attr", "TEST")
     251          self.assertEqual("TEST", root.get("attr"))
     252
     253 -    def test_attribute_set_nonstring(self):
     254          # ElementTree accepts arbitrary attribute values
     255          # lxml.etree allows only strings
     256          Element = self.etree.Element
     257
     258          root = Element("root")
     259          root.set("attr", "TEST")
     260          self.assertEqual("TEST", root.get("attr"))
     261          self.assertRaises(TypeError, root.set, "newattr", 5)
     262
     263 -    def test_attrib_and_keywords(self):
     264          Element = self.etree.Element
     265
     266          root = Element("root")
     267          root.set("attr", "TEST")
     268          self.assertEqual("TEST", root.attrib["attr"])
     269
     270          root2 = Element("root2", root.attrib, attr2='TOAST')
     271          self.assertEqual("TEST", root2.attrib["attr"])
     272          self.assertEqual("TOAST", root2.attrib["attr2"])
     273          self.assertEqual(None, root.attrib.get("attr2"))
     274
     275 -    def test_attrib_order(self):
     276          Element = self.etree.Element
     277
     278          keys = ["attr%d" % i for i in range(10)]
     279          values = ["TEST-%d" % i for i in range(10)]
     280          items = list(zip(keys, values))
     281
     282          root = Element("root")
     283          for key, value in items:
     284              root.set(key, value)
     285          self.assertEqual(keys, root.attrib.keys())
     286          self.assertEqual(values, root.attrib.values())
     287
     288          root2 = Element("root2", root.attrib,
     289                          attr_99='TOAST-1', attr_98='TOAST-2')
     290          self.assertEqual(['attr_98', 'attr_99'] + keys,
     291                           root2.attrib.keys())
     292          self.assertEqual(['TOAST-2', 'TOAST-1'] + values,
     293                           root2.attrib.values())
     294
     295          self.assertEqual(keys, root.attrib.keys())
     296          self.assertEqual(values, root.attrib.values())
     297
     298 -    def test_attribute_set_invalid(self):
     299          # ElementTree accepts arbitrary attribute values
     300          # lxml.etree allows only strings, or None for (html5) boolean attributes
     301          Element = self.etree.Element
     302          root = Element("root")
     303          self.assertRaises(TypeError, root.set, "newattr", 5)
     304          self.assertRaises(TypeError, root.set, "newattr", object)
     305          self.assertRaises(TypeError, root.set, "newattr", None)
     306          self.assertRaises(TypeError, root.set, "newattr")
     307
     308 -    def test_strip_attributes(self):
     309          XML = self.etree.XML
     310          xml = _bytes('<test a="5" b="10" c="20"><x a="4" b="2"/></test>')
     311
     312          root = XML(xml)
     313          self.etree.strip_attributes(root, 'a')
     314          self.assertEqual(_bytes('<test b="10" c="20"><x b="2"></x></test>'),
     315                            self._writeElement(root))
     316
     317          root = XML(xml)
     318          self.etree.strip_attributes(root, 'b', 'c')
     319          self.assertEqual(_bytes('<test a="5"><x a="4"></x></test>'),
     320                            self._writeElement(root))
     321
     322 -    def test_strip_attributes_ns(self):
     323          XML = self.etree.XML
     324          xml = _bytes('<test xmlns:n="http://test/ns" a="6" b="10" c="20" n:a="5"><x a="4" n:b="2"/></test>')
     325
     326          root = XML(xml)
     327          self.etree.strip_attributes(root, 'a')
     328          self.assertEqual(
     329              _bytes('<test xmlns:n="http://test/ns" b="10" c="20" n:a="5"><x n:b="2"></x></test>'),
     330              self._writeElement(root))
     331
     332          root = XML(xml)
     333          self.etree.strip_attributes(root, '{http://test/ns}a', 'c')
     334          self.assertEqual(
     335              _bytes('<test xmlns:n="http://test/ns" a="6" b="10"><x a="4" n:b="2"></x></test>'),
     336              self._writeElement(root))
     337
     338          root = XML(xml)
     339          self.etree.strip_attributes(root, '{http://test/ns}*')
     340          self.assertEqual(
     341              _bytes('<test xmlns:n="http://test/ns" a="6" b="10" c="20"><x a="4"></x></test>'),
     342              self._writeElement(root))
     343
     344 -    def test_strip_elements(self):
     345          XML = self.etree.XML
     346          xml = _bytes('<test><a><b><c/></b></a><x><a><b/><c/></a></x></test>')
     347
     348          root = XML(xml)
     349          self.etree.strip_elements(root, 'a')
     350          self.assertEqual(_bytes('<test><x></x></test>'),
     351                            self._writeElement(root))
     352
     353          root = XML(xml)
     354          self.etree.strip_elements(root, 'b', 'c', 'X', 'Y', 'Z')
     355          self.assertEqual(_bytes('<test><a></a><x><a></a></x></test>'),
     356                            self._writeElement(root))
     357
     358          root = XML(xml)
     359          self.etree.strip_elements(root, 'c')
     360          self.assertEqual(_bytes('<test><a><b></b></a><x><a><b></b></a></x></test>'),
     361                            self._writeElement(root))
     362
     363 -    def test_strip_elements_ns(self):
     364          XML = self.etree.XML
     365          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>')
     366
     367          root = XML(xml)
     368          self.etree.strip_elements(root, 'a')
     369          self.assertEqual(_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>'),
     370                            self._writeElement(root))
     371
     372          root = XML(xml)
     373          self.etree.strip_elements(root, '{urn:a}b', 'c')
     374          self.assertEqual(_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>'),
     375                            self._writeElement(root))
     376
     377          root = XML(xml)
     378          self.etree.strip_elements(root, '{urn:a}*', 'c')
     379          self.assertEqual(_bytes('<test>TEST<x>X<a>A<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
     380                            self._writeElement(root))
     381
     382          root = XML(xml)
     383          self.etree.strip_elements(root, '{urn:a}*', 'c', with_tail=False)
     384          self.assertEqual(_bytes('<test>TESTAT<x>X<a>ABT<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
     385                            self._writeElement(root))
     386
     387 -    def test_strip_tags(self):
     388          XML = self.etree.XML
     389          xml = _bytes('<test>TEST<a>A<b>B<c/>CT</b>BT</a>AT<x>X<a>A<b/>BT<c/>CT</a>AT</x>XT</test>')
     390
     391          root = XML(xml)
     392          self.etree.strip_tags(root, 'a')
     393          self.assertEqual(_bytes('<test>TESTA<b>B<c></c>CT</b>BTAT<x>XA<b></b>BT<c></c>CTAT</x>XT</test>'),
     394                            self._writeElement(root))
     395
     396          root = XML(xml)
     397          self.etree.strip_tags(root, 'b', 'c', 'X', 'Y', 'Z')
     398          self.assertEqual(_bytes('<test>TEST<a>ABCTBT</a>AT<x>X<a>ABTCT</a>AT</x>XT</test>'),
     399                            self._writeElement(root))
     400
     401          root = XML(xml)
     402          self.etree.strip_tags(root, 'c')
     403          self.assertEqual(_bytes('<test>TEST<a>A<b>BCT</b>BT</a>AT<x>X<a>A<b></b>BTCT</a>AT</x>XT</test>'),
     404                            self._writeElement(root))
     405
     406 -    def test_strip_tags_pi_comment(self):
     407          XML = self.etree.XML
     408          PI = self.etree.ProcessingInstruction
     409          Comment = self.etree.Comment
     410          xml = _bytes('<!--comment1-->\n<?PI1?>\n<test>TEST<!--comment2-->XT<?PI2?></test>\n<!--comment3-->\n<?PI1?>')
     411
     412          root = XML(xml)
     413          self.etree.strip_tags(root, PI)
     414          self.assertEqual(_bytes('<!--comment1-->\n<?PI1?>\n<test>TEST<!--comment2-->XT</test>\n<!--comment3-->\n<?PI1?>'),
     415                            self._writeElement(root))
     416
     417          root = XML(xml)
     418          self.etree.strip_tags(root, Comment)
     419          self.assertEqual(_bytes('<!--comment1-->\n<?PI1?>\n<test>TESTXT<?PI2?></test>\n<!--comment3-->\n<?PI1?>'),
     420                            self._writeElement(root))
     421
     422          root = XML(xml)
     423          self.etree.strip_tags(root, PI, Comment)
     424          self.assertEqual(_bytes('<!--comment1-->\n<?PI1?>\n<test>TESTXT</test>\n<!--comment3-->\n<?PI1?>'),
     425                            self._writeElement(root))
     426
     427          root = XML(xml)
     428          self.etree.strip_tags(root, Comment, PI)
     429          self.assertEqual(_bytes('<!--comment1-->\n<?PI1?>\n<test>TESTXT</test>\n<!--comment3-->\n<?PI1?>'),
     430                            self._writeElement(root))
     431
     432 -    def test_strip_tags_pi_comment_all(self):
     433          XML = self.etree.XML
     434          ElementTree = self.etree.ElementTree
     435          PI = self.etree.ProcessingInstruction
     436          Comment = self.etree.Comment
     437          xml = _bytes('<!--comment1-->\n<?PI1?>\n<test>TEST<!--comment2-->XT<?PI2?></test>\n<!--comment3-->\n<?PI1?>')
     438
     439          root = XML(xml)
     440          self.etree.strip_tags(ElementTree(root), PI)
     441          self.assertEqual(_bytes('<!--comment1-->\n<test>TEST<!--comment2-->XT</test>\n<!--comment3-->'),
     442                            self._writeElement(root))
     443
     444          root = XML(xml)
     445          self.etree.strip_tags(ElementTree(root), Comment)
     446          self.assertEqual(_bytes('<?PI1?>\n<test>TESTXT<?PI2?></test>\n<?PI1?>'),
     447                            self._writeElement(root))
     448
     449          root = XML(xml)
     450          self.etree.strip_tags(ElementTree(root), PI, Comment)
     451          self.assertEqual(_bytes('<test>TESTXT</test>'),
     452                            self._writeElement(root))
     453
     454          root = XML(xml)
     455          self.etree.strip_tags(ElementTree(root), Comment, PI)
     456          self.assertEqual(_bytes('<test>TESTXT</test>'),
     457                            self._writeElement(root))
     458
     459 -    def test_strip_tags_doc_style(self):
     460          XML = self.etree.XML
     461          xml = _bytes('''
     462          <div>
     463              <div>
     464                  I like <strong>sheep</strong>.
     465                  <br/>
     466                  I like lots of <strong>sheep</strong>.
     467                  <br/>
     468                  Click <a href="http://www.sheep.com">here</a>
     469                   for <a href="http://www.sheep.com">those</a> sheep.
     470                  <br/>
     471              </div>
     472          </div>
     473          '''.strip())
     474
     475          root = XML(xml)
     476          self.etree.strip_tags(root, 'a')
     477          self.assertEqual(re.sub(_bytes('</?a[^>]*>'), _bytes(''), xml).replace(_bytes('<br/>'), _bytes('<br></br>')),
     478                            self._writeElement(root))
     479
     480          root = XML(xml)
     481          self.etree.strip_tags(root, 'a', 'br')
     482          self.assertEqual(re.sub(_bytes('</?a[^>]*>'), _bytes(''),
     483                                   re.sub(_bytes('<br[^>]*>'), _bytes(''), xml)),
     484                            self._writeElement(root))
     485
     486 -    def test_strip_tags_ns(self):
     487          XML = self.etree.XML
     488          xml = _bytes('<test>TEST<n:a xmlns:n="urn:a">A<b>B<c xmlns="urn:c"/>CT</b>BT</n:a>AT<x>X<a>A<b xmlns="urn:a"/>BT<c xmlns="urn:x"/>CT</a>AT</x>XT</test>')
     489
     490          root = XML(xml)
     491          self.etree.strip_tags(root, 'a')
     492          self.assertEqual(_bytes('<test>TEST<n:a xmlns:n="urn:a">A<b>B<c xmlns="urn:c"></c>CT</b>BT</n:a>AT<x>XA<b xmlns="urn:a"></b>BT<c xmlns="urn:x"></c>CTAT</x>XT</test>'),
     493                            self._writeElement(root))
     494
     495          root = XML(xml)
     496          self.etree.strip_tags(root, '{urn:a}b', 'c')
     497          self.assertEqual(_bytes('<test>TEST<n:a xmlns:n="urn:a">A<b>B<c xmlns="urn:c"></c>CT</b>BT</n:a>AT<x>X<a>ABT<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
     498                            self._writeElement(root))
     499
     500          root = XML(xml)
     501          self.etree.strip_tags(root, '{urn:a}*', 'c')
     502          self.assertEqual(_bytes('<test>TESTA<b>B<c xmlns="urn:c"></c>CT</b>BTAT<x>X<a>ABT<c xmlns="urn:x"></c>CT</a>AT</x>XT</test>'),
     503                            self._writeElement(root))
     504
     505 -    def test_strip_tags_and_remove(self):
     506          # previously crashed
     507          HTML = self.etree.HTML
     508          root = HTML(_bytes('<div><h1>title</h1> <b>foo</b> <p>boo</p></div>'))[0][0]
     509          self.assertEqual(_bytes('<div><h1>title</h1> <b>foo</b> <p>boo</p></div>'),
     510                            self.etree.tostring(root))
     511          self.etree.strip_tags(root, 'b')
     512          self.assertEqual(_bytes('<div><h1>title</h1> foo <p>boo</p></div>'),
     513                            self.etree.tostring(root))
     514          root.remove(root[0])
     515          self.assertEqual(_bytes('<div><p>boo</p></div>'),
     516                            self.etree.tostring(root))
     517
     518 -    def test_pi(self):
     519          # lxml.etree separates target and text
     520          Element = self.etree.Element
     521          SubElement = self.etree.SubElement
     522          ProcessingInstruction = self.etree.ProcessingInstruction
     523
     524          a = Element('a')
     525          a.append(ProcessingInstruction('foo', 'some more text'))
     526          self.assertEqual(a[0].target, 'foo')
     527          self.assertEqual(a[0].text, 'some more text')
     528
     529 -    def test_pi_parse(self):
     530          XML = self.etree.XML
     531          root = XML(_bytes("<test><?mypi my test ?></test>"))
     532          self.assertEqual(root[0].target, "mypi")
     533          self.assertEqual(root[0].text, "my test ")
     534
     535 -    def test_pi_pseudo_attributes_get(self):
     536          XML = self.etree.XML
     537          root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>"))
     538          self.assertEqual(root[0].target, "mypi")
     539          self.assertEqual(root[0].get('my'), "1")
     540          self.assertEqual(root[0].get('test'), " abc ")
     541          self.assertEqual(root[0].get('quotes'), "' '")
     542          self.assertEqual(root[0].get('only'), None)
     543          self.assertEqual(root[0].get('names'), None)
     544          self.assertEqual(root[0].get('nope'), None)
     545
     546 -    def test_pi_pseudo_attributes_attrib(self):
     547          XML = self.etree.XML
     548          root = XML(_bytes("<test><?mypi my='1' test=\" abc \" quotes=\"' '\" only names ?></test>"))
     549          self.assertEqual(root[0].target, "mypi")
     550          self.assertEqual(root[0].attrib['my'], "1")
     551          self.assertEqual(root[0].attrib['test'], " abc ")
     552          self.assertEqual(root[0].attrib['quotes'], "' '")
     553          self.assertRaises(KeyError, root[0].attrib.__getitem__, 'only')
     554          self.assertRaises(KeyError, root[0].attrib.__getitem__, 'names')
     555          self.assertRaises(KeyError, root[0].attrib.__getitem__, 'nope')
     556
     557 -    def test_deepcopy_pi(self):
     558          # previously caused a crash
     559          ProcessingInstruction = self.etree.ProcessingInstruction
     560
     561          a = ProcessingInstruction("PI", "ONE")
     562          b = copy.deepcopy(a)
     563          b.text = "ANOTHER"
     564
     565          self.assertEqual('ONE',     a.text)
     566          self.assertEqual('ANOTHER', b.text)
     567
     568 -    def test_deepcopy_elementtree_pi(self):
     569          XML = self.etree.XML
     570          tostring = self.etree.tostring
     571          root = XML(_bytes("<?mypi my test ?><test/><!--comment -->"))
     572          tree1 = self.etree.ElementTree(root)
     573          self.assertEqual(_bytes("<?mypi my test ?><test/><!--comment -->"),
     574                            tostring(tree1))
     575
     576          tree2 = copy.deepcopy(tree1)
     577          self.assertEqual(_bytes("<?mypi my test ?><test/><!--comment -->"),
     578                            tostring(tree2))
     579
     580          root2 = copy.deepcopy(tree1.getroot())
     581          self.assertEqual(_bytes("<test/>"),
     582                            tostring(root2))
     583
     584 -    def test_deepcopy_elementtree_dtd(self):
     585          XML = self.etree.XML
     586          tostring = self.etree.tostring
     587          xml = _bytes('<!DOCTYPE test [\n<!ENTITY entity "tasty">\n]>\n<test/>')
     588          root = XML(xml)
     589          tree1 = self.etree.ElementTree(root)
     590          self.assertEqual(xml, tostring(tree1))
     591
     592          tree2 = copy.deepcopy(tree1)
     593          self.assertEqual(xml, tostring(tree2))
     594
     595          root2 = copy.deepcopy(tree1.getroot())
     596          self.assertEqual(_bytes("<test/>"),
     597                            tostring(root2))
     598
     599 -    def test_deepcopy_pi_dtd(self):
     600          XML = self.etree.XML
     601          tostring = self.etree.tostring
     602          xml = _bytes('<!-- comment --><!DOCTYPE test [\n<!ENTITY entity "tasty">\n]>\n<test/>')
     603          root = XML(xml)
     604          tree1 = self.etree.ElementTree(root)
     605          self.assertEqual(xml, tostring(tree1))
     606
     607          tree2 = copy.deepcopy(tree1)
     608          self.assertEqual(xml, tostring(tree2))
     609
     610 -    def test_parse_remove_comments(self):
     611          fromstring = self.etree.fromstring
     612          tostring = self.etree.tostring
     613          XMLParser = self.etree.XMLParser
     614
     615          xml = _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
     616          parser = XMLParser(remove_comments=True)
     617          root = fromstring(xml, parser)
     618          self.assertEqual(
     619              _bytes('<a><b><c/></b></a>'),
     620              tostring(root))
     621
     622 -    def test_parse_remove_pis(self):
     623          parse = self.etree.parse
     624          tostring = self.etree.tostring
     625          XMLParser = self.etree.XMLParser
     626
     627          xml = _bytes('<?test?><a><?A?><b><?B?><c/></b><?C?></a><?tail?>')
     628
     629          f = BytesIO(xml)
     630          tree = parse(f)
     631          self.assertEqual(
     632              xml,
     633              tostring(tree))
     634
     635          parser = XMLParser(remove_pis=True)
     636          tree = parse(f, parser)
     637          self.assertEqual(
     638              _bytes('<a><b><c/></b></a>'),
     639              tostring(tree))
     640
     641 -    def test_parse_parser_type_error(self):
     642          # ET raises IOError only
     643          parse = self.etree.parse
     644          self.assertRaises(TypeError, parse, 'notthere.xml', object())
     645
     646 -    def test_iterparse_tree_comments(self):
     647          # ET removes comments
     648          iterparse = self.etree.iterparse
     649          tostring = self.etree.tostring
     650
     651          f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
     652          events = list(iterparse(f))
     653          root = events[-1][1]
     654          self.assertEqual(3, len(events))
     655          self.assertEqual(
     656              _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'),
     657              tostring(root))
     658
     659 -    def test_iterparse_comments(self):
     660          # ET removes comments
     661          iterparse = self.etree.iterparse
     662          tostring = self.etree.tostring
     663
     664          def name(event, el):
     665              if event == 'comment':
     666                  return el.text
     667              else:
     668                  return el.tag
     669
     670          f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
     671          events = list(iterparse(f, events=('end', 'comment')))
     672          root = events[-1][1]
     673          self.assertEqual(6, len(events))
     674          self.assertEqual(['A', ' B ', 'c', 'b', 'C', 'a'],
     675                            [ name(*item) for item in events ])
     676          self.assertEqual(
     677              _bytes('<a><!--A--><b><!-- B --><c/></b><!--C--></a>'),
     678              tostring(root))
     679
     680 -    def test_iterparse_pis(self):
     681          # ET removes pis
     682          iterparse = self.etree.iterparse
     683          tostring = self.etree.tostring
     684          ElementTree = self.etree.ElementTree
     685
     686          def name(event, el):
     687              if event == 'pi':
     688                  return (el.target, el.text)
     689              else:
     690                  return el.tag
     691
     692          f = BytesIO('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>')
     693          events = list(iterparse(f, events=('end', 'pi')))
     694          root = events[-2][1]
     695          self.assertEqual(8, len(events))
     696          self.assertEqual([('pia','a'), ('pib','b'), ('pic','c'), 'c', 'b',
     697                             ('pid','d'), 'a', ('pie','e')],
     698                            [ name(*item) for item in events ])
     699          self.assertEqual(
     700              _bytes('<?pia a?><a><?pib b?><b><?pic c?><c/></b><?pid d?></a><?pie e?>'),
     701              tostring(ElementTree(root)))
     702
     703 -    def test_iterparse_remove_comments(self):
     704          iterparse = self.etree.iterparse
     705          tostring = self.etree.tostring
     706
     707          f = BytesIO('<a><!--A--><b><!-- B --><c/></b><!--C--></a>')
     708          events = list(iterparse(f, remove_comments=True,
     709                                  events=('end', 'comment')))
     710          root = events[-1][1]
     711          self.assertEqual(3, len(events))
     712          self.assertEqual(['c', 'b', 'a'],
     713                            [ el.tag for (event, el) in events ])
     714          self.assertEqual(
     715              _bytes('<a><b><c/></b></a>'),
     716              tostring(root))
     717
     718 -    def test_iterparse_broken(self):
     719          iterparse = self.etree.iterparse
     720          f = BytesIO('<a><b><c/></a>')
     721          # ET raises ExpatError, lxml raises XMLSyntaxError
     722          self.assertRaises(self.etree.XMLSyntaxError, list, iterparse(f))
     723
     724 -    def test_iterparse_broken_recover(self):
     725          iterparse = self.etree.iterparse
     726          f = BytesIO('<a><b><c/></a>')
     727          it = iterparse(f, events=('start', 'end'), recover=True)
     728          events = [(ev, el.tag) for ev, el in it]
     729          root = it.root
     730          self.assertTrue(root is not None)
     731
     732          self.assertEqual(1, events.count(('start', 'a')))
     733          self.assertEqual(1, events.count(('end', 'a')))
     734
     735          self.assertEqual(1, events.count(('start', 'b')))
     736          self.assertEqual(1, events.count(('end', 'b')))
     737
     738          self.assertEqual(1, events.count(('start', 'c')))
     739          self.assertEqual(1, events.count(('end', 'c')))
     740
     741 -    def test_iterparse_broken_multi_recover(self):
     742          iterparse = self.etree.iterparse
     743          f = BytesIO('<a><b><c/></d><b><c/></a></b>')
     744          it = iterparse(f, events=('start', 'end'), recover=True)
     745          events = [(ev, el.tag) for ev, el in it]
     746          root = it.root
     747          self.assertTrue(root is not None)
     748
     749          self.assertEqual(1, events.count(('start', 'a')))
     750          self.assertEqual(1, events.count(('end', 'a')))
     751
     752          self.assertEqual(2, events.count(('start', 'b')))
     753          self.assertEqual(2, events.count(('end', 'b')))
     754
     755          self.assertEqual(2, events.count(('start', 'c')))
     756          self.assertEqual(2, events.count(('end', 'c')))
     757
     758 -    def test_iterparse_strip(self):
     759          iterparse = self.etree.iterparse
     760          f = BytesIO("""
     761                 <a>  \n \n  <b> b test </b>  \n
     762
     763                 \n\t <c> \n </c> </a>  \n """)
     764          iterator = iterparse(f, remove_blank_text=True)
     765          text = [ (element.text, element.tail)
     766                   for event, element in iterator ]
     767          self.assertEqual(
     768              [(" b test ", None), (" \n ", None), (None, None)],
     769              text)
     770
     771 -    def test_iterparse_tag(self):
     772          iterparse = self.etree.iterparse
     773          f = BytesIO('<a><b><d/></b><c/></a>')
     774
     775          iterator = iterparse(f, tag="b", events=('start', 'end'))
     776          events = list(iterator)
     777          root = iterator.root
     778          self.assertEqual(
     779              [('start', root[0]), ('end', root[0])],
     780              events)
     781
     782 -    def test_iterparse_tag_all(self):
     783          iterparse = self.etree.iterparse
     784          f = BytesIO('<a><b><d/></b><c/></a>')
     785
     786          iterator = iterparse(f, tag="*", events=('start', 'end'))
     787          events = list(iterator)
     788          self.assertEqual(
     789              8,
     790              len(events))
     791
     792 -    def test_iterparse_tag_ns(self):
     793          iterparse = self.etree.iterparse
     794          f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
     795
     796          iterator = iterparse(f, tag="{urn:test:1}b", events=('start', 'end'))
     797          events = list(iterator)
     798          root = iterator.root
     799          self.assertEqual(
     800              [('start', root[0]), ('end', root[0])],
     801              events)
     802
     803 -    def test_iterparse_tag_ns_empty(self):
     804          iterparse = self.etree.iterparse
     805          f = BytesIO('<a><b><d/></b><c/></a>')
     806          iterator = iterparse(f, tag="{}b", events=('start', 'end'))
     807          events = list(iterator)
     808          root = iterator.root
     809          self.assertEqual(
     810              [('start', root[0]), ('end', root[0])],
     811              events)
     812
     813          f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
     814          iterator = iterparse(f, tag="{}b", events=('start', 'end'))
     815          events = list(iterator)
     816          root = iterator.root
     817          self.assertEqual([], events)
     818
     819 -    def test_iterparse_tag_ns_all(self):
     820          iterparse = self.etree.iterparse
     821          f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
     822          iterator = iterparse(f, tag="{urn:test:1}*", events=('start', 'end'))
     823          events = list(iterator)
     824          self.assertEqual(8, len(events))
     825
     826 -    def test_iterparse_tag_ns_empty_all(self):
     827          iterparse = self.etree.iterparse
     828          f = BytesIO('<a xmlns="urn:test:1"><b><d/></b><c/></a>')
     829          iterator = iterparse(f, tag="{}*", events=('start', 'end'))
     830          events = list(iterator)
     831          self.assertEqual([], events)
     832
     833          f = BytesIO('<a><b><d/></b><c/></a>')
     834          iterator = iterparse(f, tag="{}*", events=('start', 'end'))
     835          events = list(iterator)
     836          self.assertEqual(8, len(events))
     837
     838 -    def test_iterparse_encoding_error(self):
     839          text = _str('Søk på nettet')
     840          wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>"
     841          xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
     842                        ).encode('iso-8859-1')
     843
     844          self.assertRaises(self.etree.ParseError,
     845                            list, self.etree.iterparse(BytesIO(xml_latin1)))
     846
     847 -    def test_iterparse_encoding_8bit_override(self):
     848          text = _str('Søk på nettet', encoding="UTF-8")
     849          wrong_declaration = "<?xml version='1.0' encoding='UTF-8'?>"
     850          xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
     851                        ).encode('iso-8859-1')
     852
     853          iterator = self.etree.iterparse(BytesIO(xml_latin1),
     854                                          encoding="iso-8859-1")
     855          self.assertEqual(1, len(list(iterator)))
     856
     857          a = iterator.root
     858          self.assertEqual(a.text, text)
     859
     860 -    def test_iterparse_keep_cdata(self):
     861          tostring = self.etree.tostring
     862          f = BytesIO('<root><![CDATA[test]]></root>')
     863          context = self.etree.iterparse(f, strip_cdata=False)
     864          content = [ el.text for event,el in context ]
     865
     866          self.assertEqual(['test'], content)
     867          self.assertEqual(_bytes('<root><![CDATA[test]]></root>'),
     868                            tostring(context.root))
     869
     870 -    def test_parser_encoding_unknown(self):
     871          self.assertRaises(
     872              LookupError, self.etree.XMLParser, encoding="hopefully unknown")
     873
     874 -    def test_parser_encoding(self):
     875          self.etree.XMLParser(encoding="ascii")
     876          self.etree.XMLParser(encoding="utf-8")
     877          self.etree.XMLParser(encoding="iso-8859-1")
     878
     879 -    def test_feed_parser_recover(self):
     880          parser = self.etree.XMLParser(recover=True)
     881
     882          parser.feed('<?xml version=')
     883          parser.feed('"1.0"?><ro')
     884          parser.feed('ot><')
     885          parser.feed('a test="works"')
     886          parser.feed('><othertag/></root') # <a> not closed!
     887          parser.feed('>')
     888
     889          root = parser.close()
     890
     891          self.assertEqual(root.tag, "root")
     892          self.assertEqual(len(root), 1)
     893          self.assertEqual(root[0].tag, "a")
     894          self.assertEqual(root[0].get("test"), "works")
     895          self.assertEqual(len(root[0]), 1)
     896          self.assertEqual(root[0][0].tag, "othertag")
     897          # FIXME: would be nice to get some errors logged ...
     898          #self.assertTrue(len(parser.error_log) > 0, "error log is empty")
     899
     900 -    def test_feed_parser_recover_no_id_dict(self):
     901          # test that recover mode plays nicely with the no-id-dict setup
     902          parser = self.etree.XMLParser(recover=True, collect_ids=False)
     903
     904          parser.feed('<?xml version=')
     905          parser.feed('"1.0"?><ro')
     906          parser.feed('ot xml:id="123"><')
     907          parser.feed('a test="works" xml:id=')
     908          parser.feed('"321"><othertag/></root') # <a> not closed!
     909          parser.feed('>')
     910
     911          root = parser.close()
     912
     913          self.assertEqual(root.tag, "root")
     914          self.assertEqual(len(root), 1)
     915          self.assertEqual(root[0].tag, "a")
     916          self.assertEqual(root[0].get("test"), "works")
     917          self.assertEqual(root[0].attrib, {
     918              'test': 'works',
     919              '{http://www.w3.org/XML/1998/namespace}id': '321'})
     920          self.assertEqual(len(root[0]), 1)
     921          self.assertEqual(root[0][0].tag, "othertag")
     922          # FIXME: would be nice to get some errors logged ...
     923          #self.assertTrue(len(parser.error_log) > 0, "error log is empty")
     924
     925 -    def test_elementtree_parser_target_type_error(self):
     926          assertEqual = self.assertEqual
     927          assertFalse  = self.assertFalse
     928
     929          events = []
     930          class Target(object):
     931              def start(self, tag, attrib):
     932                  events.append("start")
     933                  assertFalse(attrib)
     934                  assertEqual("TAG", tag)
     935              def end(self, tag):
     936                  events.append("end")
     937                  assertEqual("TAG", tag)
     938              def close(self):
     939                  return "DONE" # no Element!
     940
     941          parser = self.etree.XMLParser(target=Target())
     942          tree = self.etree.ElementTree()
     943
     944          self.assertRaises(TypeError,
     945                            tree.parse, BytesIO("<TAG/>"), parser=parser)
     946          self.assertEqual(["start", "end"], events)
     947
     948 -    def test_parser_target_feed_exception(self):
     949          # ET doesn't call .close() on errors
     950          events = []
     951          class Target(object):
     952              def start(self, tag, attrib):
     953                  events.append("start-" + tag)
     954              def end(self, tag):
     955                  events.append("end-" + tag)
     956                  if tag == 'a':
     957                      raise ValueError("dead and gone")
     958              def data(self, data):
     959                  events.append("data-" + data)
     960              def close(self):
     961                  events.append("close")
     962                  return "DONE"
     963
     964          parser = self.etree.XMLParser(target=Target())
     965
     966          try:
     967              parser.feed(_bytes('<root>A<a>ca</a>B</root>'))
     968              done = parser.close()
     969              self.fail("error expected, but parsing succeeded")
     970          except ValueError:
     971              done = 'value error received as expected'
     972
     973          self.assertEqual(["start-root", "data-A", "start-a",
     974                             "data-ca", "end-a", "close"],
     975                            events)
     976
     977 -    def test_parser_target_fromstring_exception(self):
     978          # ET doesn't call .close() on errors
     979          events = []
     980          class Target(object):
     981              def start(self, tag, attrib):
     982                  events.append("start-" + tag)
     983              def end(self, tag):
     984                  events.append("end-" + tag)
     985                  if tag == 'a':
     986                      raise ValueError("dead and gone")
     987              def data(self, data):
     988                  events.append("data-" + data)
     989              def close(self):
     990                  events.append("close")
     991                  return "DONE"
     992
     993          parser = self.etree.XMLParser(target=Target())
     994
     995          try:
     996              done = self.etree.fromstring(_bytes('<root>A<a>ca</a>B</root>'),
     997                                           parser=parser)
     998              self.fail("error expected, but parsing succeeded")
     999          except ValueError:
    1000              done = 'value error received as expected'
    1001
    1002          self.assertEqual(["start-root", "data-A", "start-a",
    1003                            "data-ca", "end-a", "close"],
    1004                           events)
    1005
    1006 -    def test_parser_target_feed_no_id_dict(self):
    1007          # test that target parsing works nicely with the no-id-hash setup
    1008          events = []
    1009          class Target(object):
    1010              def start(self, tag, attrib):
    1011                  events.append("start-" + tag)
    1012              def end(self, tag):
    1013                  events.append("end-" + tag)
    1014              def data(self, data):
    1015                  events.append("data-" + data)
    1016              def comment(self, text):
    1017                  events.append("comment-" + text)
    1018              def close(self):
    1019                  return "DONE"
    1020
    1021          parser = self.etree.XMLParser(target=Target(), collect_ids=False)
    1022
    1023          parser.feed(_bytes('<!--a--><root xml:id="123">A<!--b-->'))
    1024          parser.feed(_bytes('<sub xml:id="321"/>B</root>'))
    1025          done = parser.close()
    1026
    1027          self.assertEqual("DONE", done)
    1028          self.assertEqual(["comment-a", "start-root", "data-A", "comment-b",
    1029                            "start-sub", "end-sub", "data-B", "end-root"],
    1030                           events)
    1031
    1032 -    def test_parser_target_comment(self):
    1033          events = []
    1034          class Target(object):
    1035              def start(self, tag, attrib):
    1036                  events.append("start-" + tag)
    1037              def end(self, tag):
    1038                  events.append("end-" + tag)
    1039              def data(self, data):
    1040                  events.append("data-" + data)
    1041              def comment(self, text):
    1042                  events.append("comment-" + text)
    1043              def close(self):
    1044                  return "DONE"
    1045
    1046          parser = self.etree.XMLParser(target=Target())
    1047
    1048          parser.feed(_bytes('<!--a--><root>A<!--b--><sub/><!--c-->B</root><!--d-->'))
    1049          done = parser.close()
    1050
    1051          self.assertEqual("DONE", done)
    1052          self.assertEqual(["comment-a", "start-root", "data-A", "comment-b",
    1053                             "start-sub", "end-sub", "comment-c", "data-B",
    1054                             "end-root", "comment-d"],
    1055                            events)
    1056
    1057 -    def test_parser_target_pi(self):
    1058          events = []
    1059          class Target(object):
    1060              def start(self, tag, attrib):
    1061                  events.append("start-" + tag)
    1062              def end(self, tag):
    1063                  events.append("end-" + tag)
    1064              def data(self, data):
    1065                  events.append("data-" + data)
    1066              def pi(self, target, data):
    1067                  events.append("pi-" + target + "-" + data)
    1068              def close(self):
    1069                  return "DONE"
    1070
    1071          parser = self.etree.XMLParser(target=Target())
    1072
    1073          parser.feed(_bytes('<?test a?><root>A<?test b?>B</root><?test c?>'))
    1074          done = parser.close()
    1075
    1076          self.assertEqual("DONE", done)
    1077          self.assertEqual(["pi-test-a", "start-root", "data-A", "pi-test-b",
    1078                             "data-B", "end-root", "pi-test-c"],
    1079                            events)
    1080
    1081 -    def test_parser_target_cdata(self):
    1082          events = []
    1083          class Target(object):
    1084              def start(self, tag, attrib):
    1085                  events.append("start-" + tag)
    1086              def end(self, tag):
    1087                  events.append("end-" + tag)
    1088              def data(self, data):
    1089                  events.append("data-" + data)
    1090              def close(self):
    1091                  return "DONE"
    1092
    1093          parser = self.etree.XMLParser(target=Target(),
    1094                                        strip_cdata=False)
    1095
    1096          parser.feed(_bytes('<root>A<a><![CDATA[ca]]></a>B</root>'))
    1097          done = parser.close()
    1098
    1099          self.assertEqual("DONE", done)
    1100          self.assertEqual(["start-root", "data-A", "start-a",
    1101                             "data-ca", "end-a", "data-B", "end-root"],
    1102                            events)
    1103
    1104 -    def test_parser_target_recover(self):
    1105          events = []
    1106          class Target(object):
    1107              def start(self, tag, attrib):
    1108                  events.append("start-" + tag)
    1109              def end(self, tag):
    1110                  events.append("end-" + tag)
    1111              def data(self, data):
    1112                  events.append("data-" + data)
    1113              def close(self):
    1114                  events.append("close")
    1115                  return "DONE"
    1116
    1117          parser = self.etree.XMLParser(target=Target(),
    1118                                        recover=True)
    1119
    1120          parser.feed(_bytes('<root>A<a>ca</a>B</not-root>'))
    1121          done = parser.close()
    1122
    1123          self.assertEqual("DONE", done)
    1124          self.assertEqual(["start-root", "data-A", "start-a",
    1125                             "data-ca", "end-a", "data-B",
    1126                             "end-root", "close"],
    1127                            events)
    1128
    1129 -    def test_iterwalk_tag(self):
    1130          iterwalk = self.etree.iterwalk
    1131          root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
    1132
    1133          iterator = iterwalk(root, tag="b", events=('start', 'end'))
    1134          events = list(iterator)
    1135          self.assertEqual(
    1136              [('start', root[0]), ('end', root[0])],
    1137              events)
    1138
    1139 -    def test_iterwalk_tag_all(self):
    1140          iterwalk = self.etree.iterwalk
    1141          root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
    1142
    1143          iterator = iterwalk(root, tag="*", events=('start', 'end'))
    1144          events = list(iterator)
    1145          self.assertEqual(
    1146              8,
    1147              len(events))
    1148
    1149 -    def test_iterwalk(self):
    1150          iterwalk = self.etree.iterwalk
    1151          root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
    1152
    1153          events = list(iterwalk(root))
    1154          self.assertEqual(
    1155              [('end', root[0]), ('end', root[1]), ('end', root)],
    1156              events)
    1157
    1158 -    def test_iterwalk_start(self):
    1159          iterwalk = self.etree.iterwalk
    1160          root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
    1161
    1162          iterator = iterwalk(root, events=('start',))
    1163          events = list(iterator)
    1164          self.assertEqual(
    1165              [('start', root), ('start', root[0]), ('start', root[1])],
    1166              events)
    1167
    1168 -    def test_iterwalk_start_end(self):
    1169          iterwalk = self.etree.iterwalk
    1170          root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
    1171
    1172          iterator = iterwalk(root, events=('start','end'))
    1173          events = list(iterator)
    1174          self.assertEqual(
    1175              [('start', root), ('start', root[0]), ('end', root[0]),
    1176               ('start', root[1]), ('end', root[1]), ('end', root)],
    1177              events)
    1178
    1179 -    def test_iterwalk_clear(self):
    1180          iterwalk = self.etree.iterwalk
    1181          root = self.etree.XML(_bytes('<a><b></b><c/></a>'))
    1182
    1183          iterator = iterwalk(root)
    1184          for event, elem in iterator:
    1185              elem.clear()
    1186
    1187          self.assertEqual(0,
    1188                            len(root))
    1189
    1190 -    def test_iterwalk_attrib_ns(self):
    1191          iterwalk = self.etree.iterwalk
    1192          root = self.etree.XML(_bytes('<a xmlns="ns1"><b><c xmlns="ns2"/></b></a>'))
    1193
    1194          attr_name = '{testns}bla'
    1195          events = []
    1196          iterator = iterwalk(root, events=('start','end','start-ns','end-ns'))
    1197          for event, elem in iterator:
    1198              events.append(event)
    1199              if event == 'start':
    1200                  if elem.tag != '{ns1}a':
    1201                      elem.set(attr_name, 'value')
    1202
    1203          self.assertEqual(
    1204              ['start-ns', 'start', 'start', 'start-ns', 'start',
    1205               'end', 'end-ns', 'end', 'end', 'end-ns'],
    1206              events)
    1207
    1208          self.assertEqual(
    1209              None,
    1210              root.get(attr_name))
    1211          self.assertEqual(
    1212              'value',
    1213              root[0].get(attr_name))
    1214
    1215 -    def test_iterwalk_getiterator(self):
    1216          iterwalk = self.etree.iterwalk
    1217          root = self.etree.XML(_bytes('<a><b><d/></b><c/></a>'))
    1218
    1219          counts = []
    1220          for event, elem in iterwalk(root):
    1221              counts.append(len(list(elem.getiterator())))
    1222          self.assertEqual(
    1223              [1,2,1,4],
    1224              counts)
    1225
    1226 -    def test_resolve_string_dtd(self):
    1227          parse = self.etree.parse
    1228          parser = self.etree.XMLParser(dtd_validation=True)
    1229          assertEqual = self.assertEqual
    1230          test_url = _str("__nosuch.dtd")
    1231
    1232          class MyResolver(self.etree.Resolver):
    1233              def resolve(self, url, id, context):
    1234                  assertEqual(url, test_url)
    1235                  return self.resolve_string(
    1236                      _str('''<!ENTITY myentity "%s">
    1237                          <!ELEMENT doc ANY>''') % url, context)
    1238
    1239          parser.resolvers.add(MyResolver())
    1240
    1241          xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
    1242          tree = parse(StringIO(xml), parser)
    1243          root = tree.getroot()
    1244          self.assertEqual(root.text, test_url)
    1245
    1246 -    def test_resolve_bytes_dtd(self):
    1247          parse = self.etree.parse
    1248          parser = self.etree.XMLParser(dtd_validation=True)
    1249          assertEqual = self.assertEqual
    1250          test_url = _str("__nosuch.dtd")
    1251
    1252          class MyResolver(self.etree.Resolver):
    1253              def resolve(self, url, id, context):
    1254                  assertEqual(url, test_url)
    1255                  return self.resolve_string(
    1256                      (_str('''<!ENTITY myentity "%s">
    1257                               <!ELEMENT doc ANY>''') % url).encode('utf-8'),
    1258                      context)
    1259
    1260          parser.resolvers.add(MyResolver())
    1261
    1262          xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
    1263          tree = parse(StringIO(xml), parser)
    1264          root = tree.getroot()
    1265          self.assertEqual(root.text, test_url)
    1266
    1267 -    def test_resolve_filelike_dtd(self):
    1268          parse = self.etree.parse
    1269          parser = self.etree.XMLParser(dtd_validation=True)
    1270          assertEqual = self.assertEqual
    1271          test_url = _str("__nosuch.dtd")
    1272
    1273          class MyResolver(self.etree.Resolver):
    1274              def resolve(self, url, id, context):
    1275                  assertEqual(url, test_url)
    1276                  return self.resolve_file(
    1277                      SillyFileLike(
    1278                          _str('''<!ENTITY myentity "%s">
    1279                          <!ELEMENT doc ANY>''') % url), context)
    1280
    1281          parser.resolvers.add(MyResolver())
    1282
    1283          xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
    1284          tree = parse(StringIO(xml), parser)
    1285          root = tree.getroot()
    1286          self.assertEqual(root.text, test_url)
    1287
    1288 -    def test_resolve_filename_dtd(self):
    1289          parse = self.etree.parse
    1290          parser = self.etree.XMLParser(attribute_defaults=True)
    1291          assertEqual = self.assertEqual
    1292          test_url = _str("__nosuch.dtd")
    1293
    1294          class MyResolver(self.etree.Resolver):
    1295              def resolve(self, url, id, context):
    1296                  assertEqual(url, test_url)
    1297                  return self.resolve_filename(
    1298                      fileInTestDir('test.dtd'), context)
    1299
    1300          parser.resolvers.add(MyResolver())
    1301
    1302          xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
    1303          tree = parse(StringIO(xml), parser)
    1304          root = tree.getroot()
    1305          self.assertEqual(
    1306              root.attrib,    {'default': 'valueA'})
    1307          self.assertEqual(
    1308              root[0].attrib, {'default': 'valueB'})
    1309
    1310 -    def test_resolve_filename_dtd_relative(self):
    1311          parse = self.etree.parse
    1312          parser = self.etree.XMLParser(attribute_defaults=True)
    1313          assertEqual = self.assertEqual
    1314          test_url = _str("__nosuch.dtd")
    1315
    1316          class MyResolver(self.etree.Resolver):
    1317              def resolve(self, url, id, context):
    1318                  expected = fileUrlInTestDir(test_url)
    1319                  url = url.replace('file://', 'file:')  # depends on libxml2 version
    1320                  expected = expected.replace('file://', 'file:')
    1321                  assertEqual(url, expected)
    1322                  return self.resolve_filename(
    1323                      fileUrlInTestDir('test.dtd'), context)
    1324
    1325          parser.resolvers.add(MyResolver())
    1326
    1327          xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
    1328          tree = parse(StringIO(xml), parser,
    1329                       base_url=fileUrlInTestDir('__test.xml'))
    1330          root = tree.getroot()
    1331          self.assertEqual(
    1332              root.attrib,    {'default': 'valueA'})
    1333          self.assertEqual(
    1334              root[0].attrib, {'default': 'valueB'})
    1335
    1336 -    def test_resolve_file_dtd(self):
    1337          parse = self.etree.parse
    1338          parser = self.etree.XMLParser(attribute_defaults=True)
    1339          assertEqual = self.assertEqual
    1340          test_url = _str("__nosuch.dtd")
    1341
    1342          class MyResolver(self.etree.Resolver):
    1343              def resolve(self, url, id, context):
    1344                  assertEqual(url, test_url)
    1345                  return self.resolve_file(
    1346                      open(fileInTestDir('test.dtd'), 'rb'), context)
    1347
    1348          parser.resolvers.add(MyResolver())
    1349
    1350          xml = _str('<!DOCTYPE a SYSTEM "%s"><a><b/></a>') % test_url
    1351          tree = parse(StringIO(xml), parser)
    1352          root = tree.getroot()
    1353          self.assertEqual(
    1354              root.attrib,    {'default': 'valueA'})
    1355          self.assertEqual(
    1356              root[0].attrib, {'default': 'valueB'})
    1357
    1358 -    def test_resolve_empty(self):
    1359          parse = self.etree.parse
    1360          parser = self.etree.XMLParser(load_dtd=True)
    1361          assertEqual = self.assertEqual
    1362          test_url = _str("__nosuch.dtd")
    1363
    1364          class check(object):
    1365              resolved = False
    1366
    1367          class MyResolver(self.etree.Resolver):
    1368              def resolve(self, url, id, context):
    1369                  assertEqual(url, test_url)
    1370                  check.resolved = True
    1371                  return self.resolve_empty(context)
    1372
    1373          parser.resolvers.add(MyResolver())
    1374
    1375          xml = _str('<!DOCTYPE doc SYSTEM "%s"><doc>&myentity;</doc>') % test_url
    1376          self.assertRaises(etree.XMLSyntaxError, parse, StringIO(xml), parser)
    1377          self.assertTrue(check.resolved)
    1378
    1379 -    def test_resolve_error(self):
    1380          parse = self.etree.parse
    1381          parser = self.etree.XMLParser(dtd_validation=True)
    1382
    1383          class _LocalException(Exception):
    1384              pass
    1385
    1386          class MyResolver(self.etree.Resolver):
    1387              def resolve(self, url, id, context):
    1388                  raise _LocalException
    1389
    1390          parser.resolvers.add(MyResolver())
    1391
    1392          xml = '<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>'
    1393          self.assertRaises(_LocalException, parse, BytesIO(xml), parser)
    1394
    1395      if etree.LIBXML_VERSION > (2,6,20):
    1396 -        def test_entity_parse(self):
    1397              parse = self.etree.parse
    1398              tostring = self.etree.tostring
    1399              parser = self.etree.XMLParser(resolve_entities=False)
    1400              Entity = self.etree.Entity
    1401
    1402              xml = _bytes('<!DOCTYPE doc SYSTEM "test"><doc>&myentity;</doc>')
    1403              tree = parse(BytesIO(xml), parser)
    1404              root = tree.getroot()
    1405              self.assertEqual(root[0].tag, Entity)
    1406              self.assertEqual(root[0].text, "&myentity;")
    1407              self.assertEqual(root[0].tail, None)
    1408              self.assertEqual(root[0].name, "myentity")
    1409
    1410              self.assertEqual(_bytes('<doc>&myentity;</doc>'),
    1411                                tostring(root))
    1412
    1413 -        def test_entity_restructure(self):
    1414              xml = _bytes('''<!DOCTYPE root [ <!ENTITY nbsp "&#160;"> ]>
    1415                  <root>
    1416                    <child1/>
    1417                    <child2/>
    1418                    <child3>&nbsp;</child3>
    1419                  </root>''')
    1420
    1421              parser = self.etree.XMLParser(resolve_entities=False)
    1422              root = etree.fromstring(xml, parser)
    1423              self.assertEqual([ el.tag for el in root ],
    1424                                ['child1', 'child2', 'child3'])
    1425
    1426              root[0] = root[-1]
    1427              self.assertEqual([ el.tag for el in root ],
    1428                                ['child3', 'child2'])
    1429              self.assertEqual(root[0][0].text, '&nbsp;')
    1430              self.assertEqual(root[0][0].name, 'nbsp')
    1431
    1432 -    def test_entity_append(self):
    1433          Entity = self.etree.Entity
    1434          Element = self.etree.Element
    1435          tostring = self.etree.tostring
    1436
    1437          root = Element("root")
    1438          root.append( Entity("test") )
    1439
    1440          self.assertEqual(root[0].tag, Entity)
    1441          self.assertEqual(root[0].text, "&test;")
    1442          self.assertEqual(root[0].tail, None)
    1443          self.assertEqual(root[0].name, "test")
    1444
    1445          self.assertEqual(_bytes('<root>&test;</root>'),
    1446                            tostring(root))
    1447
    1448 -    def test_entity_values(self):
    1449          Entity = self.etree.Entity
    1450          self.assertEqual(Entity("test").text, '&test;')
    1451          self.assertEqual(Entity("#17683").text, '&#17683;')
    1452          self.assertEqual(Entity("#x1768").text, '&#x1768;')
    1453          self.assertEqual(Entity("#x98AF").text, '&#x98AF;')
    1454
    1455 -    def test_entity_error(self):
    1456          Entity = self.etree.Entity
    1457          self.assertRaises(ValueError, Entity, 'a b c')
    1458          self.assertRaises(ValueError, Entity, 'a,b')
    1459          self.assertRaises(ValueError, Entity, 'a\0b')
    1460          self.assertRaises(ValueError, Entity, '#abc')
    1461          self.assertRaises(ValueError, Entity, '#xxyz')
    1462
    1463 -    def test_cdata(self):
    1464          CDATA = self.etree.CDATA
    1465          Element = self.etree.Element
    1466          tostring = self.etree.tostring
    1467
    1468          root = Element("root")
    1469          root.text = CDATA('test')
    1470
    1471          self.assertEqual('test',
    1472                            root.text)
    1473          self.assertEqual(_bytes('<root><![CDATA[test]]></root>'),
    1474                            tostring(root))
    1475
    1476 -    def test_cdata_tail(self):
    1477          CDATA = self.etree.CDATA
    1478          Element = self.etree.Element
    1479          SubElement = self.etree.SubElement
    1480          tostring = self.etree.tostring
    1481
    1482          root = Element("root")
    1483          child = SubElement(root, 'child')
    1484          child.tail = CDATA('test')
    1485
    1486          self.assertEqual('test', child.tail)
    1487          self.assertEqual(_bytes('<root><child/><![CDATA[test]]></root>'),
    1488                           tostring(root))
    1489
    1490          root = Element("root")
    1491          root.tail = CDATA('test')
    1492
    1493          self.assertEqual('test', root.tail)
    1494          self.assertEqual(_bytes('<root/><![CDATA[test]]>'),
    1495                           tostring(root))
    1496
    1497 -    def test_cdata_type(self):
    1498          CDATA = self.etree.CDATA
    1499          Element = self.etree.Element
    1500          root = Element("root")
    1501
    1502          root.text = CDATA("test")
    1503          self.assertEqual('test', root.text)
    1504
    1505          root.text = CDATA(_str("test"))
    1506          self.assertEqual('test', root.text)
    1507
    1508          self.assertRaises(TypeError, CDATA, 1)
    1509
    1510 -    def test_cdata_errors(self):
    1511          CDATA = self.etree.CDATA
    1512          Element = self.etree.Element
    1513
    1514          root = Element("root")
    1515          cdata = CDATA('test')
    1516
    1517          self.assertRaises(TypeError,
    1518                            root.set, 'attr', cdata)
    1519          self.assertRaises(TypeError,
    1520                            operator.setitem, root.attrib, 'attr', cdata)
    1521
    1522 -    def test_cdata_parser(self):
    1523          tostring = self.etree.tostring
    1524          parser = self.etree.XMLParser(strip_cdata=False)
    1525          root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser)
    1526
    1527          self.assertEqual('test', root.text)
    1528          self.assertEqual(_bytes('<root><![CDATA[test]]></root>'),
    1529                            tostring(root))
    1530
    1531 -    def test_cdata_xpath(self):
    1532          tostring = self.etree.tostring
    1533          parser = self.etree.XMLParser(strip_cdata=False)
    1534          root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser)
    1535          self.assertEqual(_bytes('<root><![CDATA[test]]></root>'),
    1536                            tostring(root))
    1537
    1538          self.assertEqual(['test'], root.xpath('//text()'))
    1539
    1540      # TypeError in etree, AssertionError in ElementTree;
    1541 -    def test_setitem_assert(self):
    1542          Element = self.etree.Element
    1543          SubElement = self.etree.SubElement
    1544
    1545          a = Element('a')
    1546          b = SubElement(a, 'b')
    1547
    1548          self.assertRaises(TypeError,
    1549                            a.__setitem__, 0, 'foo')
    1550
    1551 -    def test_append_error(self):
    1552          Element = self.etree.Element
    1553          root = Element('root')
    1554          # raises AssertionError in ElementTree
    1555          self.assertRaises(TypeError, root.append, None)
    1556          self.assertRaises(TypeError, root.extend, [None])
    1557          self.assertRaises(TypeError, root.extend, [Element('one'), None])
    1558          self.assertEqual('one', root[0].tag)
    1559
    1560 -    def test_append_recursive_error(self):
    1561          Element = self.etree.Element
    1562          SubElement = self.etree.SubElement
    1563          root = Element('root')
    1564          self.assertRaises(ValueError, root.append, root)
    1565          child = SubElement(root, 'child')
    1566          self.assertRaises(ValueError, child.append, root)
    1567          child2 = SubElement(child, 'child2')
    1568          self.assertRaises(ValueError, child2.append, root)
    1569          self.assertRaises(ValueError, child2.append, child)
    1570          self.assertEqual('child2', root[0][0].tag)
    1571
    1572 -    def test_addnext(self):
    1573          Element = self.etree.Element
    1574          SubElement = self.etree.SubElement
    1575          root = Element('root')
    1576          SubElement(root, 'a')
    1577          SubElement(root, 'b')
    1578
    1579          self.assertEqual(['a', 'b'],
    1580                            [c.tag for c in root])
    1581          root[1].addnext(root[0])
    1582          self.assertEqual(['b', 'a'],
    1583                            [c.tag for c in root])
    1584
    1585 -    def test_addprevious(self):
    1586          Element = self.etree.Element
    1587          SubElement = self.etree.SubElement
    1588          root = Element('root')
    1589          SubElement(root, 'a')
    1590          SubElement(root, 'b')
    1591
    1592          self.assertEqual(['a', 'b'],
    1593                            [c.tag for c in root])
    1594          root[0].addprevious(root[1])
    1595          self.assertEqual(['b', 'a'],
    1596                            [c.tag for c in root])
    1597
    1598 -    def test_addnext_cycle(self):
    1599          Element = self.etree.Element
    1600          SubElement = self.etree.SubElement
    1601          root = Element('root')
    1602          a = SubElement(root, 'a')
    1603          b = SubElement(a, 'b')
    1604          # appending parent as sibling is forbidden
    1605          self.assertRaises(ValueError, b.addnext, a)
    1606          self.assertEqual(['a'], [c.tag for c in root])
    1607          self.assertEqual(['b'], [c.tag for c in a])
    1608
    1609 -    def test_addprevious_cycle(self):
    1610          Element = self.etree.Element
    1611          SubElement = self.etree.SubElement
    1612          root = Element('root')
    1613          a = SubElement(root, 'a')
    1614          b = SubElement(a, 'b')
    1615          # appending parent as sibling is forbidden
    1616          self.assertRaises(ValueError, b.addprevious, a)
    1617          self.assertEqual(['a'], [c.tag for c in root])
    1618          self.assertEqual(['b'], [c.tag for c in a])
    1619
    1620 -    def test_addnext_cycle_long(self):
    1621          Element = self.etree.Element
    1622          SubElement = self.etree.SubElement
    1623          root = Element('root')
    1624          a = SubElement(root, 'a')
    1625          b = SubElement(a, 'b')
    1626          c = SubElement(b, 'c')
    1627          # appending parent as sibling is forbidden
    1628          self.assertRaises(ValueError, c.addnext, a)
    1629
    1630 -    def test_addprevious_cycle_long(self):
    1631          Element = self.etree.Element
    1632          SubElement = self.etree.SubElement
    1633          root = Element('root')
    1634          a = SubElement(root, 'a')
    1635          b = SubElement(a, 'b')
    1636          c = SubElement(b, 'c')
    1637          # appending parent as sibling is forbidden
    1638          self.assertRaises(ValueError, c.addprevious, a)
    1639
    1640 -    def test_addprevious_noops(self):
    1641          Element = self.etree.Element
    1642          SubElement = self.etree.SubElement
    1643          root = Element('root')
    1644          a = SubElement(root, 'a')
    1645          b = SubElement(root, 'b')
    1646          a.addprevious(a)
    1647          self.assertEqual('a', root[0].tag)
    1648          self.assertEqual('b', root[1].tag)
    1649          b.addprevious(b)
    1650          self.assertEqual('a', root[0].tag)
    1651          self.assertEqual('b', root[1].tag)
    1652          b.addprevious(a)
    1653          self.assertEqual('a', root[0].tag)
    1654          self.assertEqual('b', root[1].tag)
    1655
    1656 -    def test_addnext_noops(self):
    1657          Element = self.etree.Element
    1658          SubElement = self.etree.SubElement
    1659          root = Element('root')
    1660          a = SubElement(root, 'a')
    1661          b = SubElement(root, 'b')
    1662          a.addnext(a)
    1663          self.assertEqual('a', root[0].tag)
    1664          self.assertEqual('b', root[1].tag)
    1665          b.addnext(b)
    1666          self.assertEqual('a', root[0].tag)
    1667          self.assertEqual('b', root[1].tag)
    1668          a.addnext(b)
    1669          self.assertEqual('a', root[0].tag)
    1670          self.assertEqual('b', root[1].tag)
    1671
    1672 -    def test_addnext_root(self):
    1673          Element = self.etree.Element
    1674          a = Element('a')
    1675          b = Element('b')
    1676          self.assertRaises(TypeError, a.addnext, b)
    1677
    1678 -    def test_addprevious_pi(self):
    1679          Element = self.etree.Element
    1680          SubElement = self.etree.SubElement
    1681          PI = self.etree.PI
    1682          root = Element('root')
    1683          SubElement(root, 'a')
    1684          pi = PI('TARGET', 'TEXT')
    1685          pi.tail = "TAIL"
    1686
    1687          self.assertEqual(_bytes('<root><a></a></root>'),
    1688                            self._writeElement(root))
    1689          root[0].addprevious(pi)
    1690          self.assertEqual(_bytes('<root><?TARGET TEXT?>TAIL<a></a></root>'),
    1691                            self._writeElement(root))
    1692
    1693 -    def test_addprevious_root_pi(self):
    1694          Element = self.etree.Element
    1695          PI = self.etree.PI
    1696          root = Element('root')
    1697          pi = PI('TARGET', 'TEXT')
    1698          pi.tail = "TAIL"
    1699
    1700          self.assertEqual(_bytes('<root></root>'),
    1701                            self._writeElement(root))
    1702          root.addprevious(pi)
    1703          self.assertEqual(_bytes('<?TARGET TEXT?>\n<root></root>'),
    1704                            self._writeElement(root))
    1705
    1706 -    def test_addnext_pi(self):
    1707          Element = self.etree.Element
    1708          SubElement = self.etree.SubElement
    1709          PI = self.etree.PI
    1710          root = Element('root')
    1711          SubElement(root, 'a')
    1712          pi = PI('TARGET', 'TEXT')
    1713          pi.tail = "TAIL"
    1714
    1715          self.assertEqual(_bytes('<root><a></a></root>'),
    1716                            self._writeElement(root))
    1717          root[0].addnext(pi)
    1718          self.assertEqual(_bytes('<root><a></a><?TARGET TEXT?>TAIL</root>'),
    1719                            self._writeElement(root))
    1720
    1721 -    def test_addnext_root_pi(self):
    1722          Element = self.etree.Element
    1723          PI = self.etree.PI
    1724          root = Element('root')
    1725          pi = PI('TARGET', 'TEXT')
    1726          pi.tail = "TAIL"
    1727
    1728          self.assertEqual(_bytes('<root></root>'),
    1729                            self._writeElement(root))
    1730          root.addnext(pi)
    1731          self.assertEqual(_bytes('<root></root>\n<?TARGET TEXT?>'),
    1732                            self._writeElement(root))
    1733
    1734 -    def test_addnext_comment(self):
    1735          Element = self.etree.Element
    1736          SubElement = self.etree.SubElement
    1737          Comment = self.etree.Comment
    1738          root = Element('root')
    1739          SubElement(root, 'a')
    1740          comment = Comment('TEXT ')
    1741          comment.tail = "TAIL"
    1742
    1743          self.assertEqual(_bytes('<root><a></a></root>'),
    1744                            self._writeElement(root))
    1745          root[0].addnext(comment)
    1746          self.assertEqual(_bytes('<root><a></a><!--TEXT -->TAIL</root>'),
    1747                            self._writeElement(root))
    1748
    1749 -    def test_addnext_root_comment(self):
    1750          Element = self.etree.Element
    1751          Comment = self.etree.Comment
    1752          root = Element('root')
    1753          comment = Comment('TEXT ')
    1754          comment.tail = "TAIL"
    1755
    1756          self.assertEqual(_bytes('<root></root>'),
    1757                            self._writeElement(root))
    1758          root.addnext(comment)
    1759          self.assertEqual(_bytes('<root></root>\n<!--TEXT -->'),
    1760                            self._writeElement(root))
    1761
    1762 -    def test_addprevious_comment(self):
    1763          Element = self.etree.Element
    1764          SubElement = self.etree.SubElement
    1765          Comment = self.etree.Comment
    1766          root = Element('root')
    1767          SubElement(root, 'a')
    1768          comment = Comment('TEXT ')
    1769          comment.tail = "TAIL"
    1770
    1771          self.assertEqual(_bytes('<root><a></a></root>'),
    1772                            self._writeElement(root))
    1773          root[0].addprevious(comment)
    1774          self.assertEqual(_bytes('<root><!--TEXT -->TAIL<a></a></root>'),
    1775                            self._writeElement(root))
    1776
    1777 -    def test_addprevious_root_comment(self):
    1778          Element = self.etree.Element
    1779          Comment = self.etree.Comment
    1780          root = Element('root')
    1781          comment = Comment('TEXT ')
    1782          comment.tail = "TAIL"
    1783
    1784          self.assertEqual(_bytes('<root></root>'),
    1785                            self._writeElement(root))
    1786          root.addprevious(comment)
    1787          self.assertEqual(_bytes('<!--TEXT -->\n<root></root>'),
    1788                            self._writeElement(root))
    1789
    1790      # ET's Elements have items() and key(), but not values()
    1791 -    def test_attribute_values(self):
    1792          XML = self.etree.XML
    1793
    1794          root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
    1795          values = root.values()
    1796          values.sort()
    1797          self.assertEqual(['Alpha', 'Beta', 'Gamma'], values)
    1798
    1799      # gives error in ElementTree
    1800 -    def test_comment_empty(self):
    1801          Element = self.etree.Element
    1802          Comment = self.etree.Comment
    1803
    1804          a = Element('a')
    1805          a.append(Comment())
    1806          self.assertEqual(
    1807              _bytes('<a><!----></a>'),
    1808              self._writeElement(a))
    1809
    1810      # ElementTree ignores comments
    1811 -    def test_comment_parse_empty(self):
    1812          ElementTree = self.etree.ElementTree
    1813          tostring = self.etree.tostring
    1814
    1815          xml = _bytes('<a><b/><!----><c/></a>')
    1816          f = BytesIO(xml)
    1817          doc = ElementTree(file=f)
    1818          a = doc.getroot()
    1819          self.assertEqual(
    1820              '',
    1821              a[1].text)
    1822          self.assertEqual(
    1823              xml,
    1824              tostring(a))
    1825
    1826      # ElementTree ignores comments
    1827 -    def test_comment_no_proxy_yet(self):
    1828          ElementTree = self.etree.ElementTree
    1829
    1830          f = BytesIO('<a><b></b><!-- hoi --><c></c></a>')
    1831          doc = ElementTree(file=f)
    1832          a = doc.getroot()
    1833          self.assertEqual(
    1834              ' hoi ',
    1835              a[1].text)
    1836
    1837      # does not raise an exception in ElementTree
    1838 -    def test_comment_immutable(self):
    1839          Element = self.etree.Element
    1840          Comment = self.etree.Comment
    1841
    1842          c = Comment()
    1843          el = Element('myel')
    1844
    1845          self.assertRaises(TypeError, c.append, el)
    1846          self.assertRaises(TypeError, c.insert, 0, el)
    1847          self.assertRaises(TypeError, c.set, "myattr", "test")
    1848
    1849 -    def test_comment_immutable_attrib(self):
    1850          c = self.etree.Comment()
    1851          self.assertEqual(0, len(c.attrib))
    1852
    1853          self.assertFalse(c.attrib.__contains__('nope'))
    1854          self.assertFalse('nope' in c.attrib)
    1855          self.assertFalse('nope' in c.attrib.keys())
    1856          self.assertFalse('nope' in c.attrib.values())
    1857          self.assertFalse(('nope', 'huhu') in c.attrib.items())
    1858
    1859          self.assertEqual([], list(c.attrib))
    1860          self.assertEqual([], list(c.attrib.keys()))
    1861          self.assertEqual([], list(c.attrib.items()))
    1862          self.assertEqual([], list(c.attrib.values()))
    1863          self.assertEqual([], list(c.attrib.iterkeys()))
    1864          self.assertEqual([], list(c.attrib.iteritems()))
    1865          self.assertEqual([], list(c.attrib.itervalues()))
    1866
    1867          self.assertEqual('HUHU', c.attrib.pop('nope', 'HUHU'))
    1868          self.assertRaises(KeyError, c.attrib.pop, 'nope')
    1869
    1870          self.assertRaises(KeyError, c.attrib.__getitem__, 'only')
    1871          self.assertRaises(KeyError, c.attrib.__getitem__, 'names')
    1872          self.assertRaises(KeyError, c.attrib.__getitem__, 'nope')
    1873          self.assertRaises(KeyError, c.attrib.__setitem__, 'nope', 'yep')
    1874          self.assertRaises(KeyError, c.attrib.__delitem__, 'nope')
    1875
    1876      # test passing 'None' to dump()
    1877 -    def test_dump_none(self):
    1878          self.assertRaises(TypeError, self.etree.dump, None)
    1879
    1880 -    def test_prefix(self):
    1881          ElementTree = self.etree.ElementTree
    1882
    1883          f = BytesIO('<a xmlns:foo="http://www.infrae.com/ns/1"><foo:b/></a>')
    1884          doc = ElementTree(file=f)
    1885          a = doc.getroot()
    1886          self.assertEqual(
    1887              None,
    1888              a.prefix)
    1889          self.assertEqual(
    1890              'foo',
    1891              a[0].prefix)
    1892
    1893 -    def test_prefix_default_ns(self):
    1894          ElementTree = self.etree.ElementTree
    1895
    1896          f = BytesIO('<a xmlns="http://www.infrae.com/ns/1"><b/></a>')
    1897          doc = ElementTree(file=f)
    1898          a = doc.getroot()
    1899          self.assertEqual(
    1900              None,
    1901              a.prefix)
    1902          self.assertEqual(
    1903              None,
    1904              a[0].prefix)
    1905
    1906 -    def test_getparent(self):
    1907          Element = self.etree.Element
    1908          SubElement = self.etree.SubElement
    1909
    1910          a = Element('a')
    1911          b = SubElement(a, 'b')
    1912          c = SubElement(a, 'c')
    1913          d = SubElement(b, 'd')
    1914          self.assertEqual(
    1915              None,
    1916              a.getparent())
    1917          self.assertEqual(
    1918              a,
    1919              b.getparent())
    1920          self.assertEqual(
    1921              b.getparent(),
    1922              c.getparent())
    1923          self.assertEqual(
    1924              b,
    1925              d.getparent())
    1926
    1927 -    def test_iterchildren(self):
    1928          XML = self.etree.XML
    1929
    1930          root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
    1931          result = []
    1932          for el in root.iterchildren():
    1933              result.append(el.tag)
    1934          self.assertEqual(['one', 'two', 'three'], result)
    1935
    1936 -    def test_iterchildren_reversed(self):
    1937          XML = self.etree.XML
    1938
    1939          root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
    1940          result = []
    1941          for el in root.iterchildren(reversed=True):
    1942              result.append(el.tag)
    1943          self.assertEqual(['three', 'two', 'one'], result)
    1944
    1945 -    def test_iterchildren_tag(self):
    1946          XML = self.etree.XML
    1947
    1948          root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
    1949          result = []
    1950          for el in root.iterchildren(tag='two'):
    1951              result.append(el.text)
    1952          self.assertEqual(['Two', 'Bla'], result)
    1953
    1954 -    def test_iterchildren_tag_posarg(self):
    1955          XML = self.etree.XML
    1956
    1957          root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
    1958          result = []
    1959          for el in root.iterchildren('two'):
    1960              result.append(el.text)
    1961          self.assertEqual(['Two', 'Bla'], result)
    1962
    1963 -    def test_iterchildren_tag_reversed(self):
    1964          XML = self.etree.XML
    1965
    1966          root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
    1967          result = []
    1968          for el in root.iterchildren(reversed=True, tag='two'):
    1969              result.append(el.text)
    1970          self.assertEqual(['Bla', 'Two'], result)
    1971
    1972 -    def test_iterchildren_tag_multiple(self):
    1973          XML = self.etree.XML
    1974
    1975          root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
    1976          result = []
    1977          for el in root.iterchildren(tag=['two', 'three']):
    1978              result.append(el.text)
    1979          self.assertEqual(['Two', 'Bla', None], result)
    1980
    1981 -    def test_iterchildren_tag_multiple_posarg(self):
    1982          XML = self.etree.XML
    1983
    1984          root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
    1985          result = []
    1986          for el in root.iterchildren('two', 'three'):
    1987              result.append(el.text)
    1988          self.assertEqual(['Two', 'Bla', None], result)
    1989
    1990 -    def test_iterchildren_tag_multiple_reversed(self):
    1991          XML = self.etree.XML
    1992
    1993          root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
    1994          result = []
    1995          for el in root.iterchildren(reversed=True, tag=['two', 'three']):
    1996              result.append(el.text)
    1997          self.assertEqual([None, 'Bla', 'Two'], result)
    1998
    1999 -    def test_iterancestors(self):
    2000          Element    = self.etree.Element
    2001          SubElement = self.etree.SubElement
    2002
    2003          a = Element('a')
    2004          b = SubElement(a, 'b')
    2005          c = SubElement(a, 'c')
    2006          d = SubElement(b, 'd')
    2007          self.assertEqual(
    2008              [],
    2009              list(a.iterancestors()))
    2010          self.assertEqual(
    2011              [a],
    2012              list(b.iterancestors()))
    2013          self.assertEqual(
    2014              [a],
    2015              list(c.iterancestors()))
    2016          self.assertEqual(
    2017              [b, a],
    2018              list(d.iterancestors()))
    2019
    2020 -    def test_iterancestors_tag(self):
    2021          Element    = self.etree.Element
    2022          SubElement = self.etree.SubElement
    2023
    2024          a = Element('a')
    2025          b = SubElement(a, 'b')
    2026          c = SubElement(a, 'c')
    2027          d = SubElement(b, 'd')
    2028          self.assertEqual(
    2029              [a],
    2030              list(d.iterancestors('a')))
    2031          self.assertEqual(
    2032              [a],
    2033              list(d.iterancestors(tag='a')))
    2034
    2035          self.assertEqual(
    2036              [b, a],
    2037              list(d.iterancestors('*')))
    2038          self.assertEqual(
    2039              [b, a],
    2040              list(d.iterancestors(tag='*')))
    2041
    2042 -    def test_iterancestors_tag_multiple(self):
    2043          Element    = self.etree.Element
    2044          SubElement = self.etree.SubElement
    2045
    2046          a = Element('a')
    2047          b = SubElement(a, 'b')
    2048          c = SubElement(a, 'c')
    2049          d = SubElement(b, 'd')
    2050          self.assertEqual(
    2051              [b, a],
    2052              list(d.iterancestors(tag=('a', 'b'))))
    2053          self.assertEqual(
    2054              [b, a],
    2055              list(d.iterancestors('a', 'b')))
    2056
    2057          self.assertEqual(
    2058              [],
    2059              list(d.iterancestors(tag=('w', 'x', 'y', 'z'))))
    2060          self.assertEqual(
    2061              [],
    2062              list(d.iterancestors('w', 'x', 'y', 'z')))
    2063
    2064          self.assertEqual(
    2065              [],
    2066              list(d.iterancestors(tag=('d', 'x'))))
    2067          self.assertEqual(
    2068              [],
    2069              list(d.iterancestors('d', 'x')))
    2070
    2071          self.assertEqual(
    2072              [b, a],
    2073              list(d.iterancestors(tag=('b', '*'))))
    2074          self.assertEqual(
    2075              [b, a],
    2076              list(d.iterancestors('b', '*')))
    2077
    2078          self.assertEqual(
    2079              [b],
    2080              list(d.iterancestors(tag=('b', 'c'))))
    2081          self.assertEqual(
    2082              [b],
    2083              list(d.iterancestors('b', 'c')))
    2084
    2085 -    def test_iterdescendants(self):
    2086          Element = self.etree.Element
    2087          SubElement = self.etree.SubElement
    2088
    2089          a = Element('a')
    2090          b = SubElement(a, 'b')
    2091          c = SubElement(a, 'c')
    2092          d = SubElement(b, 'd')
    2093          e = SubElement(c, 'e')
    2094
    2095          self.assertEqual(
    2096              [b, d, c, e],
    2097              list(a.iterdescendants()))
    2098          self.assertEqual(
    2099              [],
    2100              list(d.iterdescendants()))
    2101
    2102 -    def test_iterdescendants_tag(self):
    2103          Element = self.etree.Element
    2104          SubElement = self.etree.SubElement
    2105
    2106          a = Element('a')
    2107          b = SubElement(a, 'b')
    2108          c = SubElement(a, 'c')
    2109          d = SubElement(b, 'd')
    2110          e = SubElement(c, 'e')
    2111
    2112          self.assertEqual(
    2113              [],
    2114              list(a.iterdescendants('a')))
    2115          self.assertEqual(
    2116              [],
    2117              list(a.iterdescendants(tag='a')))
    2118
    2119          a2 = SubElement(e, 'a')
    2120          self.assertEqual(
    2121              [a2],
    2122              list(a.iterdescendants('a')))
    2123
    2124          self.assertEqual(
    2125              [a2],
    2126              list(c.iterdescendants('a')))
    2127          self.assertEqual(
    2128              [a2],
    2129              list(c.iterdescendants(tag='a')))
    2130
    2131 -    def test_iterdescendants_tag_multiple(self):
    2132          Element = self.etree.Element
    2133          SubElement = self.etree.SubElement
    2134
    2135          a = Element('a')
    2136          b = SubElement(a, 'b')
    2137          c = SubElement(a, 'c')
    2138          d = SubElement(b, 'd')
    2139          e = SubElement(c, 'e')
    2140
    2141          self.assertEqual(
    2142              [b, e],
    2143              list(a.iterdescendants(tag=('a', 'b', 'e'))))
    2144          self.assertEqual(
    2145              [b, e],
    2146              list(a.iterdescendants('a', 'b', 'e')))
    2147
    2148          a2 = SubElement(e, 'a')
    2149          self.assertEqual(
    2150              [b, a2],
    2151              list(a.iterdescendants(tag=('a', 'b'))))
    2152          self.assertEqual(
    2153              [b, a2],
    2154              list(a.iterdescendants('a', 'b')))
    2155
    2156          self.assertEqual(
    2157              [],
    2158              list(c.iterdescendants(tag=('x', 'y', 'z'))))
    2159          self.assertEqual(
    2160              [],
    2161              list(c.iterdescendants('x', 'y', 'z')))
    2162
    2163          self.assertEqual(
    2164              [b, d, c, e, a2],
    2165              list(a.iterdescendants(tag=('x', 'y', 'z', '*'))))
    2166          self.assertEqual(
    2167              [b, d, c, e, a2],
    2168              list(a.iterdescendants('x', 'y', 'z', '*')))
    2169
    2170 -    def test_getroottree(self):
    2171          Element = self.etree.Element
    2172          SubElement = self.etree.SubElement
    2173
    2174          a = Element('a')
    2175          b = SubElement(a, 'b')
    2176          c = SubElement(a, 'c')
    2177          d = SubElement(b, 'd')
    2178          self.assertEqual(
    2179              a,
    2180              a.getroottree().getroot())
    2181          self.assertEqual(
    2182              a,
    2183              b.getroottree().getroot())
    2184          self.assertEqual(
    2185              a,
    2186              d.getroottree().getroot())
    2187
    2188 -    def test_getnext(self):
    2189          Element    = self.etree.Element
    2190          SubElement = self.etree.SubElement
    2191
    2192          a = Element('a')
    2193          b = SubElement(a, 'b')
    2194          c = SubElement(a, 'c')
    2195          self.assertEqual(
    2196              None,
    2197              a.getnext())
    2198          self.assertEqual(
    2199              c,
    2200              b.getnext())
    2201          self.assertEqual(
    2202              None,
    2203              c.getnext())
    2204
    2205 -    def test_getprevious(self):
    2206          Element    = self.etree.Element
    2207          SubElement = self.etree.SubElement
    2208
    2209          a = Element('a')
    2210          b = SubElement(a, 'b')
    2211          c = SubElement(a, 'c')
    2212          d = SubElement(b, 'd')
    2213          self.assertEqual(
    2214              None,
    2215              a.getprevious())
    2216          self.assertEqual(
    2217              b,
    2218              c.getprevious())
    2219          self.assertEqual(
    2220              None,
    2221              b.getprevious())
    2222
    2223 -    def test_itersiblings(self):
    2224          Element    = self.etree.Element
    2225          SubElement = self.etree.SubElement
    2226
    2227          a = Element('a')
    2228          b = SubElement(a, 'b')
    2229          c = SubElement(a, 'c')
    2230          d = SubElement(b, 'd')
    2231          self.assertEqual(
    2232              [],
    2233              list(a.itersiblings()))
    2234          self.assertEqual(
    2235              [c],
    2236              list(b.itersiblings()))
    2237          self.assertEqual(
    2238              [],
    2239              list(c.itersiblings()))
    2240          self.assertEqual(
    2241              [b],
    2242              list(c.itersiblings(preceding=True)))
    2243          self.assertEqual(
    2244              [],
    2245              list(b.itersiblings(preceding=True)))
    2246
    2247 -    def test_itersiblings_tag(self):
    2248          Element    = self.etree.Element
    2249          SubElement = self.etree.SubElement
    2250
    2251          a = Element('a')
    2252          b = SubElement(a, 'b')
    2253          c = SubElement(a, 'c')
    2254          d = SubElement(b, 'd')
    2255          self.assertEqual(
    2256              [],
    2257              list(a.itersiblings(tag='XXX')))
    2258          self.assertEqual(
    2259              [c],
    2260              list(b.itersiblings(tag='c')))
    2261          self.assertEqual(
    2262              [c],
    2263              list(b.itersiblings(tag='*')))
    2264          self.assertEqual(
    2265              [b],
    2266              list(c.itersiblings(preceding=True, tag='b')))
    2267          self.assertEqual(
    2268              [],
    2269              list(c.itersiblings(preceding=True, tag='c')))
    2270
    2271 -    def test_itersiblings_tag_multiple(self):
    2272          Element    = self.etree.Element
    2273          SubElement = self.etree.SubElement
    2274
    2275          a = Element('a')
    2276          b = SubElement(a, 'b')
    2277          c = SubElement(a, 'c')
    2278          d = SubElement(b, 'd')
    2279          e = SubElement(a, 'e')
    2280          self.assertEqual(
    2281              [],
    2282              list(a.itersiblings(tag=('XXX', 'YYY'))))
    2283          self.assertEqual(
    2284              [c, e],
    2285              list(b.itersiblings(tag=('c', 'd', 'e'))))
    2286          self.assertEqual(
    2287              [b],
    2288              list(c.itersiblings(preceding=True, tag=('b', 'b', 'c', 'd'))))
    2289          self.assertEqual(
    2290              [c, b],
    2291              list(e.itersiblings(preceding=True, tag=('c', '*'))))
    2292
    2293 -    def test_parseid(self):
    2294          parseid = self.etree.parseid
    2295          XML     = self.etree.XML
    2296          xml_text = _bytes('''
    2297          <!DOCTYPE document [
    2298          <!ELEMENT document (h1,p)*>
    2299          <!ELEMENT h1 (#PCDATA)>
    2300          <!ATTLIST h1 myid ID #REQUIRED>
    2301          <!ELEMENT p  (#PCDATA)>
    2302          <!ATTLIST p  someid ID #REQUIRED>
    2303          ]>
    2304          <document>
    2305            <h1 myid="chapter1">...</h1>
    2306            <p id="note1" class="note">...</p>
    2307            <p>Regular paragraph.</p>
    2308            <p xml:id="xmlid">XML:ID paragraph.</p>
    2309            <p someid="warn1" class="warning">...</p>
    2310          </document>
    2311          ''')
    2312
    2313          tree, dic = parseid(BytesIO(xml_text))
    2314          root = tree.getroot()
    2315          root2 = XML(xml_text)
    2316          self.assertEqual(self._writeElement(root),
    2317                            self._writeElement(root2))
    2318          expected = {
    2319              "chapter1" : root[0],
    2320              "xmlid"    : root[3],
    2321              "warn1"    : root[4]
    2322              }
    2323          self.assertTrue("chapter1" in dic)
    2324          self.assertTrue("warn1" in dic)
    2325          self.assertTrue("xmlid" in dic)
    2326          self._checkIDDict(dic, expected)
    2327
    2328 -    def test_XMLDTDID(self):
    2329          XMLDTDID = self.etree.XMLDTDID
    2330          XML      = self.etree.XML
    2331          xml_text = _bytes('''
    2332          <!DOCTYPE document [
    2333          <!ELEMENT document (h1,p)*>
    2334          <!ELEMENT h1 (#PCDATA)>
    2335          <!ATTLIST h1 myid ID #REQUIRED>
    2336          <!ELEMENT p  (#PCDATA)>
    2337          <!ATTLIST p  someid ID #REQUIRED>
    2338          ]>
    2339          <document>
    2340            <h1 myid="chapter1">...</h1>
    2341            <p id="note1" class="note">...</p>
    2342            <p>Regular paragraph.</p>
    2343            <p xml:id="xmlid">XML:ID paragraph.</p>
    2344            <p someid="warn1" class="warning">...</p>
    2345          </document>
    2346          ''')
    2347
    2348          root, dic = XMLDTDID(xml_text)
    2349          root2 = XML(xml_text)
    2350          self.assertEqual(self._writeElement(root),
    2351                            self._writeElement(root2))
    2352          expected = {
    2353              "chapter1" : root[0],
    2354              "xmlid"    : root[3],
    2355              "warn1"    : root[4]
    2356              }
    2357          self.assertTrue("chapter1" in dic)
    2358          self.assertTrue("warn1" in dic)
    2359          self.assertTrue("xmlid" in dic)
    2360          self._checkIDDict(dic, expected)
    2361
    2362 -    def test_XMLDTDID_empty(self):
    2363          XMLDTDID = self.etree.XMLDTDID
    2364          XML      = self.etree.XML
    2365          xml_text = _bytes('''
    2366          <document>
    2367            <h1 myid="chapter1">...</h1>
    2368            <p id="note1" class="note">...</p>
    2369            <p>Regular paragraph.</p>
    2370            <p someid="warn1" class="warning">...</p>
    2371          </document>
    2372          ''')
    2373
    2374          root, dic = XMLDTDID(xml_text)
    2375          root2 = XML(xml_text)
    2376          self.assertEqual(self._writeElement(root),
    2377                            self._writeElement(root2))
    2378          expected = {}
    2379          self._checkIDDict(dic, expected)
    2380
    2381 -    def test_XMLDTDID_no_id_dict(self):
    2382          XMLDTDID = self.etree.XMLDTDID
    2383          XML      = self.etree.XML
    2384          xml_text = _bytes('''
    2385          <!DOCTYPE document [
    2386          <!ELEMENT document (h1,p)*>
    2387          <!ELEMENT h1 (#PCDATA)>
    2388          <!ATTLIST h1 myid ID #REQUIRED>
    2389          <!ELEMENT p  (#PCDATA)>
    2390          <!ATTLIST p  someid ID #REQUIRED>
    2391          ]>
    2392          <document>
    2393            <h1 myid="chapter1">...</h1>
    2394            <p id="note1" class="note">...</p>
    2395            <p>Regular paragraph.</p>
    2396            <p xml:id="xmlid">XML:ID paragraph.</p>
    2397            <p someid="warn1" class="warning">...</p>
    2398          </document>
    2399          ''')
    2400
    2401          parser = etree.XMLParser(collect_ids=False)
    2402          root, dic = XMLDTDID(xml_text, parser=parser)
    2403          root2 = XML(xml_text)
    2404          self.assertEqual(self._writeElement(root),
    2405                           self._writeElement(root2))
    2406          self.assertFalse(dic)
    2407          self._checkIDDict(dic, {})
    2408
    2409 -    def _checkIDDict(self, dic, expected):
    2410          self.assertEqual(len(dic),
    2411                            len(expected))
    2412          self.assertEqual(sorted(dic.items()),
    2413                            sorted(expected.items()))
    2414          if sys.version_info < (3,):
    2415              self.assertEqual(sorted(dic.iteritems()),
    2416                                sorted(expected.iteritems()))
    2417          self.assertEqual(sorted(dic.keys()),
    2418                            sorted(expected.keys()))
    2419          if sys.version_info < (3,):
    2420              self.assertEqual(sorted(dic.iterkeys()),
    2421                                sorted(expected.iterkeys()))
    2422          if sys.version_info < (3,):
    2423              self.assertEqual(sorted(dic.values()),
    2424                                sorted(expected.values()))
    2425              self.assertEqual(sorted(dic.itervalues()),
    2426                                sorted(expected.itervalues()))
    2427
    2428 -    def test_namespaces(self):
    2429          etree = self.etree
    2430
    2431          r = {'foo': 'http://ns.infrae.com/foo'}
    2432          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2433          self.assertEqual(
    2434              'foo',
    2435              e.prefix)
    2436          self.assertEqual(
    2437              _bytes('<foo:bar xmlns:foo="http://ns.infrae.com/foo"></foo:bar>'),
    2438              self._writeElement(e))
    2439
    2440 -    def test_namespaces_default(self):
    2441          etree = self.etree
    2442
    2443          r = {None: 'http://ns.infrae.com/foo'}
    2444          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2445          self.assertEqual(
    2446              None,
    2447              e.prefix)
    2448          self.assertEqual(
    2449              '{http://ns.infrae.com/foo}bar',
    2450              e.tag)
    2451          self.assertEqual(
    2452              _bytes('<bar xmlns="http://ns.infrae.com/foo"></bar>'),
    2453              self._writeElement(e))
    2454
    2455 -    def test_namespaces_default_and_other(self):
    2456          etree = self.etree
    2457
    2458          r = {None: 'http://ns.infrae.com/foo', 'p': 'http://test/'}
    2459          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2460          self.assertEqual(None, e.prefix)
    2461          self.assertEqual('{http://ns.infrae.com/foo}bar', e.tag)
    2462          self.assertEqual(
    2463              _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:p="http://test/"></bar>'),
    2464              self._writeElement(e))
    2465
    2466 -    def test_namespaces_default_and_attr(self):
    2467          etree = self.etree
    2468
    2469          r = {None: 'http://ns.infrae.com/foo',
    2470               'hoi': 'http://ns.infrae.com/hoi'}
    2471          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2472          e.set('{http://ns.infrae.com/hoi}test', 'value')
    2473          self.assertEqual(
    2474              _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi" hoi:test="value"></bar>'),
    2475              self._writeElement(e))
    2476
    2477 -    def test_attribute_keeps_namespace_prefix_on_merge(self):
    2478          etree = self.etree
    2479
    2480          root = etree.Element('{http://test/ns}root',
    2481                               nsmap={None: 'http://test/ns'})
    2482          sub = etree.Element('{http://test/ns}sub',
    2483                              nsmap={'test': 'http://test/ns'})
    2484
    2485          sub.attrib['{http://test/ns}attr'] = 'value'
    2486          self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
    2487          self.assertEqual(
    2488              _bytes('<test:sub xmlns:test="http://test/ns" test:attr="value"/>'),
    2489              etree.tostring(sub))
    2490
    2491          root.append(sub)
    2492          self.assertEqual(
    2493              _bytes('<root xmlns="http://test/ns">'
    2494                     '<sub xmlns:test="http://test/ns" test:attr="value"/>'
    2495                     '</root>'),
    2496              etree.tostring(root))
    2497
    2498 -    def test_attribute_keeps_namespace_prefix_on_merge_with_nons(self):
    2499          etree = self.etree
    2500
    2501          root = etree.Element('root')
    2502          sub = etree.Element('{http://test/ns}sub',
    2503                              nsmap={'test': 'http://test/ns'})
    2504
    2505          sub.attrib['{http://test/ns}attr'] = 'value'
    2506          self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
    2507          self.assertEqual(
    2508              _bytes('<test:sub xmlns:test="http://test/ns" test:attr="value"/>'),
    2509              etree.tostring(sub))
    2510
    2511          root.append(sub)
    2512          self.assertEqual(
    2513              _bytes('<root>'
    2514                     '<test:sub xmlns:test="http://test/ns" test:attr="value"/>'
    2515                     '</root>'),
    2516              etree.tostring(root))
    2517
    2518 -    def test_attribute_gets_namespace_prefix_on_merge_with_nons(self):
    2519          etree = self.etree
    2520
    2521          root = etree.Element('root')
    2522          sub = etree.Element('{http://test/ns}sub',
    2523                              nsmap={None: 'http://test/ns'})
    2524
    2525          sub.attrib['{http://test/ns}attr'] = 'value'
    2526          self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
    2527          self.assertEqual(
    2528              _bytes('<sub xmlns="http://test/ns" '
    2529                     'xmlns:ns0="http://test/ns" ns0:attr="value"/>'),
    2530              etree.tostring(sub))
    2531
    2532          root.append(sub)
    2533          self.assertEqual(
    2534              _bytes('<root>'
    2535                     '<sub xmlns="http://test/ns"'
    2536                     ' xmlns:ns0="http://test/ns" ns0:attr="value"/>'
    2537                     '</root>'),
    2538              etree.tostring(root))
    2539
    2540 -    def test_attribute_gets_namespace_prefix_on_merge(self):
    2541          etree = self.etree
    2542
    2543          root = etree.Element('{http://test/ns}root',
    2544                               nsmap={'test': 'http://test/ns',
    2545                                      None: 'http://test/ns'})
    2546          sub = etree.Element('{http://test/ns}sub',
    2547                              nsmap={None: 'http://test/ns'})
    2548
    2549          sub.attrib['{http://test/ns}attr'] = 'value'
    2550          self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
    2551          self.assertEqual(
    2552              _bytes('<sub xmlns="http://test/ns" '
    2553                     'xmlns:ns0="http://test/ns" ns0:attr="value"/>'),
    2554              etree.tostring(sub))
    2555
    2556          root.append(sub)
    2557          self.assertEqual(
    2558              _bytes('<test:root xmlns:test="http://test/ns" xmlns="http://test/ns">'
    2559                     '<test:sub test:attr="value"/>'
    2560                     '</test:root>'),
    2561              etree.tostring(root))
    2562
    2563 -    def test_namespaces_elementtree(self):
    2564          etree = self.etree
    2565          r = {None: 'http://ns.infrae.com/foo',
    2566               'hoi': 'http://ns.infrae.com/hoi'}
    2567          e = etree.Element('{http://ns.infrae.com/foo}z', nsmap=r)
    2568          tree = etree.ElementTree(element=e)
    2569          etree.SubElement(e, '{http://ns.infrae.com/hoi}x')
    2570          self.assertEqual(
    2571              _bytes('<z xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi"><hoi:x></hoi:x></z>'),
    2572              self._writeElement(e))
    2573
    2574 -    def test_namespaces_default_copy_element(self):
    2575          etree = self.etree
    2576
    2577          r = {None: 'http://ns.infrae.com/foo'}
    2578          e1 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2579          e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2580
    2581          e1.append(e2)
    2582
    2583          self.assertEqual(
    2584              None,
    2585              e1.prefix)
    2586          self.assertEqual(
    2587              None,
    2588              e1[0].prefix)
    2589          self.assertEqual(
    2590              '{http://ns.infrae.com/foo}bar',
    2591              e1.tag)
    2592          self.assertEqual(
    2593              '{http://ns.infrae.com/foo}bar',
    2594              e1[0].tag)
    2595
    2596 -    def test_namespaces_copy_element(self):
    2597          etree = self.etree
    2598
    2599          r = {None: 'http://ns.infrae.com/BAR'}
    2600          e1 = etree.Element('{http://ns.infrae.com/BAR}bar', nsmap=r)
    2601          e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2602
    2603          e1.append(e2)
    2604
    2605          self.assertEqual(
    2606              None,
    2607              e1.prefix)
    2608          self.assertNotEqual(
    2609              None,
    2610              e2.prefix)
    2611          self.assertEqual(
    2612              '{http://ns.infrae.com/BAR}bar',
    2613              e1.tag)
    2614          self.assertEqual(
    2615              '{http://ns.infrae.com/foo}bar',
    2616              e2.tag)
    2617
    2618 -    def test_namespaces_reuse_after_move(self):
    2619          ns_href = "http://a.b.c"
    2620          one = self.etree.fromstring(
    2621              _bytes('<foo><bar xmlns:ns="%s"><ns:baz/></bar></foo>' % ns_href))
    2622          baz = one[0][0]
    2623
    2624          two = self.etree.fromstring(
    2625              _bytes('<root xmlns:ns="%s"/>' % ns_href))
    2626          two.append(baz)
    2627          del one # make sure the source document is deallocated
    2628
    2629          self.assertEqual('{%s}baz' % ns_href, baz.tag)
    2630          self.assertEqual(
    2631              _bytes('<root xmlns:ns="%s"><ns:baz/></root>' % ns_href),
    2632              self.etree.tostring(two))
    2633
    2634 -    def test_namespace_cleanup(self):
    2635          xml = _bytes(
    2636              '<foo xmlns="F" xmlns:x="x">'
    2637              '<bar xmlns:ns="NS" xmlns:b="b" xmlns="B">'
    2638              '<ns:baz/>'
    2639              '</bar></foo>'
    2640          )
    2641          root = self.etree.fromstring(xml)
    2642          self.assertEqual(xml, self.etree.tostring(root))
    2643          self.etree.cleanup_namespaces(root)
    2644          self.assertEqual(
    2645              _bytes('<foo xmlns="F"><bar xmlns:ns="NS" xmlns="B"><ns:baz/></bar></foo>'),
    2646              self.etree.tostring(root))
    2647
    2648 -    def test_namespace_cleanup_attributes(self):
    2649          xml = _bytes(
    2650              '<foo xmlns="F" xmlns:x="X" xmlns:a="A">'
    2651              '<bar xmlns:ns="NS" xmlns:b="b" xmlns="B">'
    2652              '<ns:baz a:test="attr"/>'
    2653              '</bar></foo>'
    2654          )
    2655          root = self.etree.fromstring(xml)
    2656          self.assertEqual(xml, self.etree.tostring(root))
    2657          self.etree.cleanup_namespaces(root)
    2658          self.assertEqual(
    2659              _bytes('<foo xmlns="F" xmlns:a="A">'
    2660                     '<bar xmlns:ns="NS" xmlns="B">'
    2661                     '<ns:baz a:test="attr"/>'
    2662                     '</bar></foo>'),
    2663              self.etree.tostring(root))
    2664
    2665 -    def test_namespace_cleanup_many(self):
    2666          xml = ('<n12:foo ' +
    2667                 ' '.join('xmlns:n{n}="NS{n}"'.format(n=i) for i in range(100)) +
    2668                 '><n68:a/></n12:foo>').encode('utf8')
    2669          root = self.etree.fromstring(xml)
    2670          self.assertEqual(xml, self.etree.tostring(root))
    2671          self.etree.cleanup_namespaces(root)
    2672          self.assertEqual(
    2673              b'<n12:foo xmlns:n12="NS12" xmlns:n68="NS68"><n68:a/></n12:foo>',
    2674              self.etree.tostring(root))
    2675
    2676 -    def test_namespace_cleanup_deep(self):
    2677          xml = ('<root>' +
    2678                 ''.join('<a xmlns:n{n}="NS{n}">'.format(n=i) for i in range(100)) +
    2679                 '<n64:x/>' + '</a>'*100 + '</root>').encode('utf8')
    2680          root = self.etree.fromstring(xml)
    2681          self.assertEqual(xml, self.etree.tostring(root))
    2682          self.etree.cleanup_namespaces(root)
    2683          self.assertEqual(
    2684              b'<root>' + b'<a>'*64 + b'<a xmlns:n64="NS64">' + b'<a>'*35 +
    2685              b'<n64:x/>' + b'</a>'*100 + b'</root>',
    2686              self.etree.tostring(root))
    2687
    2688 -    def test_namespace_cleanup_deep_to_top(self):
    2689          xml = ('<root>' +
    2690                 ''.join('<a xmlns:n{n}="NS{n}">'.format(n=i) for i in range(100)) +
    2691                 '<n64:x xmlns:a="A" a:attr="X"/>' +
    2692                 '</a>'*100 +
    2693                 '</root>').encode('utf8')
    2694          root = self.etree.fromstring(xml)
    2695          self.assertEqual(xml, self.etree.tostring(root))
    2696          self.etree.cleanup_namespaces(root, top_nsmap={'n64': 'NS64'})
    2697          self.assertEqual(
    2698              b'<root xmlns:n64="NS64">' + b'<a>'*100 +
    2699              b'<n64:x xmlns:a="A" a:attr="X"/>' + b'</a>'*100 + b'</root>',
    2700              self.etree.tostring(root))
    2701
    2702 -    def test_namespace_cleanup_keep_prefixes(self):
    2703          xml = ('<root xmlns:n64="NS64" xmlns:foo="FOO" xmlns:unused1="UNUSED" xmlns:no="NO">'
    2704                 '<a xmlns:unused2="UNUSED"><n64:x xmlns:a="A" a:attr="X"/></a>'
    2705                 '<foo>foo:bar</foo>'
    2706                 '</root>').encode('utf8')
    2707          root = self.etree.fromstring(xml)
    2708          self.assertEqual(xml, self.etree.tostring(root))
    2709          self.etree.cleanup_namespaces(root, keep_ns_prefixes=['foo'])
    2710          self.assertEqual(
    2711              b'<root xmlns:n64="NS64" xmlns:foo="FOO">'
    2712              b'<a><n64:x xmlns:a="A" a:attr="X"/></a>'
    2713              b'<foo>foo:bar</foo>'
    2714              b'</root>',
    2715              self.etree.tostring(root))
    2716
    2717 -    def test_namespace_cleanup_keep_prefixes_top(self):
    2718          xml = ('<root xmlns:n64="NS64" xmlns:unused1="UNUSED" xmlns:no="NO">'
    2719                 '<sub xmlns:foo="FOO">'
    2720                 '<a xmlns:unused2="UNUSED"><n64:x xmlns:a="A" a:attr="X"/></a>'
    2721                 '<foo>foo:bar</foo>'
    2722                 '</sub>'
    2723                 '</root>').encode('utf8')
    2724          root = self.etree.fromstring(xml)
    2725          self.assertEqual(xml, self.etree.tostring(root))
    2726          self.etree.cleanup_namespaces(
    2727              root,
    2728              top_nsmap={'foo': 'FOO', 'unused1': 'UNUSED'},
    2729              keep_ns_prefixes=['foo'])
    2730          self.assertEqual(
    2731              b'<root xmlns:n64="NS64" xmlns:foo="FOO">'
    2732              b'<sub>'
    2733              b'<a><n64:x xmlns:a="A" a:attr="X"/></a>'
    2734              b'<foo>foo:bar</foo>'
    2735              b'</sub>'
    2736              b'</root>',
    2737              self.etree.tostring(root))
    2738
    2739 -    def test_element_nsmap(self):
    2740          etree = self.etree
    2741
    2742          r = {None: 'http://ns.infrae.com/foo',
    2743               'hoi': 'http://ns.infrae.com/hoi'}
    2744          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2745          self.assertEqual(
    2746              r,
    2747              e.nsmap)
    2748
    2749 -    def test_subelement_nsmap(self):
    2750          etree = self.etree
    2751
    2752          re = {None: 'http://ns.infrae.com/foo',
    2753               'hoi': 'http://ns.infrae.com/hoi'}
    2754          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=re)
    2755
    2756          rs = {None: 'http://ns.infrae.com/honk',
    2757               'top': 'http://ns.infrae.com/top'}
    2758          s = etree.SubElement(e, '{http://ns.infrae.com/honk}bar', nsmap=rs)
    2759
    2760          r = re.copy()
    2761          r.update(rs)
    2762          self.assertEqual(re, e.nsmap)
    2763          self.assertEqual(r,  s.nsmap)
    2764
    2765 -    def test_html_prefix_nsmap(self):
    2766          etree = self.etree
    2767          el = etree.HTML('<hha:page-description>aa</hha:page-description>').find('.//page-description')
    2768          self.assertEqual({'hha': None}, el.nsmap)
    2769
    2770 -    def test_getiterator_filter_multiple(self):
    2771          Element = self.etree.Element
    2772          SubElement = self.etree.SubElement
    2773
    2774          a = Element('a')
    2775          b = SubElement(a, 'b')
    2776          c = SubElement(a, 'c')
    2777          d = SubElement(b, 'd')
    2778          e = SubElement(c, 'e')
    2779          f = SubElement(c, 'f')
    2780
    2781          self.assertEqual(
    2782              [a, b],
    2783                 list(a.getiterator('a', 'b')))
    2784          self.assertEqual(
    2785              [],
    2786                list(a.getiterator('x', 'y')))
    2787          self.assertEqual(
    2788              [a, f],
    2789                list(a.getiterator('f', 'a')))
    2790          self.assertEqual(
    2791              [c, e, f],
    2792                 list(c.getiterator('c', '*', 'a')))
    2793          self.assertEqual(
    2794              [],
    2795                    list(a.getiterator( (), () )))
    2796
    2797 -    def test_getiterator_filter_multiple_tuple(self):
    2798          Element = self.etree.Element
    2799          SubElement = self.etree.SubElement
    2800
    2801          a = Element('a')
    2802          b = SubElement(a, 'b')
    2803          c = SubElement(a, 'c')
    2804          d = SubElement(b, 'd')
    2805          e = SubElement(c, 'e')
    2806          f = SubElement(c, 'f')
    2807
    2808          self.assertEqual(
    2809              [a, b],
    2810                    list(a.getiterator( ('a', 'b') )))
    2811          self.assertEqual(
    2812              [],
    2813                list(a.getiterator( ('x', 'y') )))
    2814          self.assertEqual(
    2815              [a, f],
    2816                    list(a.getiterator( ('f', 'a') )))
    2817          self.assertEqual(
    2818              [c, e, f],
    2819                       list(c.getiterator( ('c', '*', 'a') )))
    2820          self.assertEqual(
    2821              [],
    2822                list(a.getiterator( () )))
    2823
    2824 -    def test_getiterator_filter_namespace(self):
    2825          Element = self.etree.Element
    2826          SubElement = self.etree.SubElement
    2827
    2828          a = Element('{a}a')
    2829          b = SubElement(a, '{a}b')
    2830          c = SubElement(a, '{a}c')
    2831          d = SubElement(b, '{b}d')
    2832          e = SubElement(c, '{a}e')
    2833          f = SubElement(c, '{b}f')
    2834          g = SubElement(c, 'g')
    2835
    2836          self.assertEqual(
    2837              [a],
    2838              list(a.getiterator('{a}a')))
    2839          self.assertEqual(
    2840              [],
    2841              list(a.getiterator('{b}a')))
    2842          self.assertEqual(
    2843              [],
    2844              list(a.getiterator('a')))
    2845          self.assertEqual(
    2846              [a,b,d,c,e,f,g],
    2847              list(a.getiterator('*')))
    2848          self.assertEqual(
    2849              [f],
    2850              list(c.getiterator('{b}*')))
    2851          self.assertEqual(
    2852              [d, f],
    2853              list(a.getiterator('{b}*')))
    2854          self.assertEqual(
    2855              [g],
    2856              list(a.getiterator('g')))
    2857          self.assertEqual(
    2858              [g],
    2859              list(a.getiterator('{}g')))
    2860          self.assertEqual(
    2861              [g],
    2862              list(a.getiterator('{}*')))
    2863
    2864 -    def test_getiterator_filter_local_name(self):
    2865          Element = self.etree.Element
    2866          SubElement = self.etree.SubElement
    2867
    2868          a = Element('{a}a')
    2869          b = SubElement(a, '{nsA}b')
    2870          c = SubElement(b, '{nsB}b')
    2871          d = SubElement(a, 'b')
    2872          e = SubElement(a, '{nsA}e')
    2873          f = SubElement(e, '{nsB}e')
    2874          g = SubElement(e, 'e')
    2875
    2876          self.assertEqual(
    2877              [b, c, d],
    2878              list(a.getiterator('{*}b')))
    2879          self.assertEqual(
    2880              [e, f, g],
    2881              list(a.getiterator('{*}e')))
    2882          self.assertEqual(
    2883              [a, b, c, d, e, f, g],
    2884              list(a.getiterator('{*}*')))
    2885
    2886 -    def test_getiterator_filter_entities(self):
    2887          Element = self.etree.Element
    2888          Entity = self.etree.Entity
    2889          SubElement = self.etree.SubElement
    2890
    2891          a = Element('a')
    2892          b = SubElement(a, 'b')
    2893          entity_b = Entity("TEST-b")
    2894          b.append(entity_b)
    2895
    2896          self.assertEqual(
    2897              [entity_b],
    2898              list(a.getiterator(Entity)))
    2899
    2900          entity_a = Entity("TEST-a")
    2901          a.append(entity_a)
    2902
    2903          self.assertEqual(
    2904              [entity_b, entity_a],
    2905              list(a.getiterator(Entity)))
    2906
    2907          self.assertEqual(
    2908              [entity_b],
    2909              list(b.getiterator(Entity)))
    2910
    2911 -    def test_getiterator_filter_element(self):
    2912          Element = self.etree.Element
    2913          Comment = self.etree.Comment
    2914          PI = self.etree.PI
    2915          SubElement = self.etree.SubElement
    2916
    2917          a = Element('a')
    2918          b = SubElement(a, 'b')
    2919          a.append(Comment("test"))
    2920          a.append(PI("pi", "content"))
    2921          c = SubElement(a, 'c')
    2922
    2923          self.assertEqual(
    2924              [a, b, c],
    2925              list(a.getiterator(Element)))
    2926
    2927 -    def test_getiterator_filter_all_comment_pi(self):
    2928          # ElementTree iterates over everything here
    2929          Element = self.etree.Element
    2930          Comment = self.etree.Comment
    2931          PI = self.etree.PI
    2932          SubElement = self.etree.SubElement
    2933
    2934          a = Element('a')
    2935          b = SubElement(a, 'b')
    2936          a.append(Comment("test"))
    2937          a.append(PI("pi", "content"))
    2938          c = SubElement(a, 'c')
    2939
    2940          self.assertEqual(
    2941              [a, b, c],
    2942              list(a.getiterator('*')))
    2943
    2944 -    def test_elementtree_getelementpath(self):
    2945          a  = etree.Element("a")
    2946          b  = etree.SubElement(a, "b")
    2947          c  = etree.SubElement(a, "c")
    2948          d1 = etree.SubElement(c, "d")
    2949          d2 = etree.SubElement(c, "d")
    2950          c.text = d1.text = 'TEXT'
    2951
    2952          tree = etree.ElementTree(a)
    2953          self.assertEqual('.', tree.getelementpath(a))
    2954          self.assertEqual('c/d[1]', tree.getelementpath(d1))
    2955          self.assertEqual('c/d[2]', tree.getelementpath(d2))
    2956
    2957          self.assertEqual(d1, tree.find(tree.getelementpath(d1)))
    2958          self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
    2959
    2960          tree = etree.ElementTree(c)
    2961          self.assertEqual('.', tree.getelementpath(c))
    2962          self.assertEqual('d[2]', tree.getelementpath(d2))
    2963          self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
    2964
    2965          tree = etree.ElementTree(b)  # not a parent of a/c/d1/d2
    2966          self.assertEqual('.', tree.getelementpath(b))
    2967          self.assertRaises(ValueError, tree.getelementpath, a)
    2968          self.assertRaises(ValueError, tree.getelementpath, c)
    2969          self.assertRaises(ValueError, tree.getelementpath, d2)
    2970
    2971 -    def test_elementtree_getelementpath_ns(self):
    2972          a  = etree.Element("{http://ns1/}a")
    2973          b  = etree.SubElement(a, "{http://ns1/}b")
    2974          c  = etree.SubElement(a, "{http://ns1/}c")
    2975          d1 = etree.SubElement(c, "{http://ns1/}d")
    2976          d2 = etree.SubElement(c, "{http://ns2/}d")
    2977          d3 = etree.SubElement(c, "{http://ns1/}d")
    2978
    2979          tree = etree.ElementTree(a)
    2980          self.assertEqual('.', tree.getelementpath(a))
    2981          self.assertEqual('{http://ns1/}c/{http://ns1/}d[1]',
    2982                           tree.getelementpath(d1))
    2983          self.assertEqual('{http://ns1/}c/{http://ns2/}d',
    2984                           tree.getelementpath(d2))
    2985          self.assertEqual('{http://ns1/}c/{http://ns1/}d[2]',
    2986                           tree.getelementpath(d3))
    2987
    2988          self.assertEqual(a, tree.find(tree.getelementpath(a)))
    2989          self.assertEqual(b, tree.find(tree.getelementpath(b)))
    2990          self.assertEqual(c, tree.find(tree.getelementpath(c)))
    2991          self.assertEqual(d1, tree.find(tree.getelementpath(d1)))
    2992          self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
    2993          self.assertEqual(d3, tree.find(tree.getelementpath(d3)))
    2994
    2995          tree = etree.ElementTree(c)
    2996          self.assertEqual('{http://ns1/}d[1]', tree.getelementpath(d1))
    2997          self.assertEqual('{http://ns2/}d', tree.getelementpath(d2))
    2998          self.assertEqual('{http://ns1/}d[2]', tree.getelementpath(d3))
    2999          self.assertEqual(d1, tree.find(tree.getelementpath(d1)))
    3000          self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
    3001          self.assertEqual(d3, tree.find(tree.getelementpath(d3)))
    3002
    3003          tree = etree.ElementTree(b)  # not a parent of d1/d2
    3004          self.assertRaises(ValueError, tree.getelementpath, d1)
    3005          self.assertRaises(ValueError, tree.getelementpath, d2)
    3006
    3007 -    def test_elementtree_find_qname(self):
    3008          XML = self.etree.XML
    3009          ElementTree = self.etree.ElementTree
    3010          QName = self.etree.QName
    3011          tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>')))
    3012          self.assertEqual(tree.find(QName("c")), tree.getroot()[2])
    3013
    3014 -    def test_elementtree_findall_qname(self):
    3015          XML = self.etree.XML
    3016          ElementTree = self.etree.ElementTree
    3017          QName = self.etree.QName
    3018          tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>')))
    3019          self.assertEqual(len(list(tree.findall(QName("c")))), 1)
    3020
    3021 -    def test_elementtree_findall_ns_qname(self):
    3022          XML = self.etree.XML
    3023          ElementTree = self.etree.ElementTree
    3024          QName = self.etree.QName
    3025          tree = ElementTree(XML(
    3026                  _bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>')))
    3027          self.assertEqual(len(list(tree.findall(QName("b")))), 2)
    3028          self.assertEqual(len(list(tree.findall(QName("X", "b")))), 1)
    3029
    3030 -    def test_findall_ns(self):
    3031          XML = self.etree.XML
    3032          root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>'))
    3033          self.assertEqual(len(root.findall(".//{X}b")), 2)
    3034          self.assertEqual(len(root.findall(".//{X}*")), 2)
    3035          self.assertEqual(len(root.findall(".//b")), 3)
    3036
    3037 -    def test_findall_different_nsmaps(self):
    3038          XML = self.etree.XML
    3039          root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><y:b/></a>'))
    3040          nsmap = {'xx': 'X'}
    3041          self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2)
    3042          self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 2)
    3043          self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
    3044          nsmap = {'xx': 'Y'}
    3045          self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 1)
    3046          self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 1)
    3047          self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
    3048
    3049 -    def test_findall_empty_prefix(self):
    3050          XML = self.etree.XML
    3051          root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><y:b/></a>'))
    3052          nsmap = {'xx': 'X'}
    3053          self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2)
    3054          nsmap = {'xx': 'X', None: 'Y'}
    3055          self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 1)
    3056          nsmap = {'xx': 'X', '': 'Y'}
    3057          self.assertRaises(ValueError, root.findall, ".//xx:b", namespaces=nsmap)
    3058
    3059 -    def test_findall_syntax_error(self):
    3060          XML = self.etree.XML
    3061          root = XML(_bytes('<a><b><c/></b><b/><c><b/><b/></c><b/></a>'))
    3062          self.assertRaises(SyntaxError, root.findall, '')
    3063          self.assertRaises(SyntaxError, root.findall, '//')  # absolute path on Element
    3064          self.assertRaises(SyntaxError, root.findall, './//')
    3065
    3066 -    def test_index(self):
    3067          etree = self.etree
    3068          e = etree.Element('foo')
    3069          for i in range(10):
    3070              etree.SubElement(e, 'a%s' % i)
    3071          for i in range(10):
    3072              self.assertEqual(
    3073                  i,
    3074                  e.index(e[i]))
    3075          self.assertEqual(
    3076              3, e.index(e[3], 3))
    3077          self.assertRaises(
    3078              ValueError, e.index, e[3], 4)
    3079          self.assertRaises(
    3080              ValueError, e.index, e[3], 0, 2)
    3081          self.assertRaises(
    3082              ValueError, e.index, e[8], 0, -3)
    3083          self.assertRaises(
    3084              ValueError, e.index, e[8], -5, -3)
    3085          self.assertEqual(
    3086              8, e.index(e[8], 0, -1))
    3087          self.assertEqual(
    3088              8, e.index(e[8], -12, -1))
    3089          self.assertEqual(
    3090              0, e.index(e[0], -12, -1))
    3091
    3092 -    def test_replace(self):
    3093          etree = self.etree
    3094          e = etree.Element('foo')
    3095          for i in range(10):
    3096              el = etree.SubElement(e, 'a%s' % i)
    3097              el.text = "text%d" % i
    3098              el.tail = "tail%d" % i
    3099
    3100          child0 = e[0]
    3101          child1 = e[1]
    3102          child2 = e[2]
    3103
    3104          e.replace(e[0], e[1])
    3105          self.assertEqual(
    3106              9, len(e))
    3107          self.assertEqual(
    3108              child1, e[0])
    3109          self.assertEqual(
    3110              child1.text, "text1")
    3111          self.assertEqual(
    3112              child1.tail, "tail1")
    3113          self.assertEqual(
    3114              child0.tail, "tail0")
    3115          self.assertEqual(
    3116              child2, e[1])
    3117
    3118          e.replace(e[-1], e[0])
    3119          self.assertEqual(
    3120              child1, e[-1])
    3121          self.assertEqual(
    3122              child1.text, "text1")
    3123          self.assertEqual(
    3124              child1.tail, "tail1")
    3125          self.assertEqual(
    3126              child2, e[0])
    3127
    3128 -    def test_replace_new(self):
    3129          etree = self.etree
    3130          e = etree.Element('foo')
    3131          for i in range(10):
    3132              etree.SubElement(e, 'a%s' % i)
    3133
    3134          new_element = etree.Element("test")
    3135          new_element.text = "TESTTEXT"
    3136          new_element.tail = "TESTTAIL"
    3137          child1 = e[1]
    3138          e.replace(e[0], new_element)
    3139          self.assertEqual(
    3140              new_element, e[0])
    3141          self.assertEqual(
    3142              "TESTTEXT",
    3143              e[0].text)
    3144          self.assertEqual(
    3145              "TESTTAIL",
    3146              e[0].tail)
    3147          self.assertEqual(
    3148              child1, e[1])
    3149
    3150 -    def test_setslice_all_empty_reversed(self):
    3151          Element = self.etree.Element
    3152          SubElement = self.etree.SubElement
    3153
    3154          a = Element('a')
    3155
    3156          e = Element('e')
    3157          f = Element('f')
    3158          g = Element('g')
    3159
    3160          s = [e, f, g]
    3161          a[::-1] = s
    3162          self.assertEqual(
    3163              [g, f, e],
    3164              list(a))
    3165
    3166 -    def test_setslice_step(self):
    3167          Element = self.etree.Element
    3168          SubElement = self.etree.SubElement
    3169
    3170          a = Element('a')
    3171          b = SubElement(a, 'b')
    3172          c = SubElement(a, 'c')
    3173          d = SubElement(a, 'd')
    3174          e = SubElement(a, 'e')
    3175
    3176          x = Element('x')
    3177          y = Element('y')
    3178
    3179          a[1::2] = [x, y]
    3180          self.assertEqual(
    3181              [b, x, d, y],
    3182              list(a))
    3183
    3184 -    def test_setslice_step_negative(self):
    3185          Element = self.etree.Element
    3186          SubElement = self.etree.SubElement
    3187
    3188          a = Element('a')
    3189          b = SubElement(a, 'b')
    3190          c = SubElement(a, 'c')
    3191          d = SubElement(a, 'd')
    3192          e = SubElement(a, 'e')
    3193
    3194          x = Element('x')
    3195          y = Element('y')
    3196
    3197          a[1::-1] = [x, y]
    3198          self.assertEqual(
    3199              [y, x, d, e],
    3200              list(a))
    3201
    3202 -    def test_setslice_step_negative2(self):
    3203          Element = self.etree.Element
    3204          SubElement = self.etree.SubElement
    3205
    3206          a = Element('a')
    3207          b = SubElement(a, 'b')
    3208          c = SubElement(a, 'c')
    3209          d = SubElement(a, 'd')
    3210          e = SubElement(a, 'e')
    3211
    3212          x = Element('x')
    3213          y = Element('y')
    3214
    3215          a[::-2] = [x, y]
    3216          self.assertEqual(
    3217              [b, y, d, x],
    3218              list(a))
    3219
    3220 -    def test_setslice_step_overrun(self):
    3221          Element = self.etree.Element
    3222          SubElement = self.etree.SubElement
    3223          try:
    3224              slice
    3225          except NameError:
    3226              print("slice() not found")
    3227              return
    3228
    3229          a = Element('a')
    3230          b = SubElement(a, 'b')
    3231          c = SubElement(a, 'c')
    3232          d = SubElement(a, 'd')
    3233          e = SubElement(a, 'e')
    3234
    3235          x = Element('x')
    3236          y = Element('y')
    3237          z = Element('z')
    3238
    3239          self.assertRaises(
    3240              ValueError,
    3241              operator.setitem, a, slice(1,None,2), [x, y, z])
    3242
    3243          self.assertEqual(
    3244              [b, c, d, e],
    3245              list(a))
    3246
    3247 -    def test_sourceline_XML(self):
    3248          XML = self.etree.XML
    3249          root = XML(_bytes('''<?xml version="1.0"?>
    3250          <root><test>
    3251
    3252          <bla/></test>
    3253          </root>
    3254          '''))
    3255
    3256          self.assertEqual(
    3257              [2, 2, 4],
    3258              [ el.sourceline for el in root.getiterator() ])
    3259
    3260 -    def test_large_sourceline_XML(self):
    3261          XML = self.etree.XML
    3262          root = XML(_bytes(
    3263              '<?xml version="1.0"?>\n'
    3264              '<root>' + '\n' * 65536 +
    3265              '<p>' + '\n' * 65536 + '</p>\n' +
    3266              '<br/>\n'
    3267              '</root>'))
    3268
    3269          if self.etree.LIBXML_VERSION >= (2, 9):
    3270              expected = [2, 131074, 131076]
    3271          else:
    3272              expected = [2, 65535, 65535]
    3273
    3274          self.assertEqual(expected, [el.sourceline for el in root.iter()])
    3275
    3276 -    def test_sourceline_parse(self):
    3277          parse = self.etree.parse
    3278          tree = parse(fileInTestDir('include/test_xinclude.xml'))
    3279
    3280          self.assertEqual(
    3281              [1, 2, 3],
    3282              [ el.sourceline for el in tree.getiterator() ])
    3283
    3284 -    def test_sourceline_iterparse_end(self):
    3285          iterparse = self.etree.iterparse
    3286          lines = [ el.sourceline for (event, el) in
    3287                    iterparse(fileInTestDir('include/test_xinclude.xml')) ]
    3288
    3289          self.assertEqual(
    3290              [2, 3, 1],
    3291              lines)
    3292
    3293 -    def test_sourceline_iterparse_start(self):
    3294          iterparse = self.etree.iterparse
    3295          lines = [ el.sourceline for (event, el) in
    3296                    iterparse(fileInTestDir('include/test_xinclude.xml'),
    3297                              events=("start",)) ]
    3298
    3299          self.assertEqual(
    3300              [1, 2, 3],
    3301              lines)
    3302
    3303 -    def test_sourceline_element(self):
    3304          Element = self.etree.Element
    3305          SubElement = self.etree.SubElement
    3306          el = Element("test")
    3307          self.assertEqual(None, el.sourceline)
    3308
    3309          child = SubElement(el, "test")
    3310          self.assertEqual(None, el.sourceline)
    3311          self.assertEqual(None, child.sourceline)
    3312
    3313 -    def test_XML_base_url_docinfo(self):
    3314          etree = self.etree
    3315          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    3316          docinfo = root.getroottree().docinfo
    3317          self.assertEqual(docinfo.URL, "http://no/such/url")
    3318
    3319 -    def test_XML_set_base_url_docinfo(self):
    3320          etree = self.etree
    3321          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    3322          docinfo = root.getroottree().docinfo
    3323          self.assertEqual(docinfo.URL, "http://no/such/url")
    3324          docinfo.URL = "https://secret/url"
    3325          self.assertEqual(docinfo.URL, "https://secret/url")
    3326
    3327 -    def test_parse_stringio_base_url(self):
    3328          etree = self.etree
    3329          tree = etree.parse(BytesIO("<root/>"), base_url="http://no/such/url")
    3330          docinfo = tree.docinfo
    3331          self.assertEqual(docinfo.URL, "http://no/such/url")
    3332
    3333 -    def test_parse_base_url_docinfo(self):
    3334          etree = self.etree
    3335          tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
    3336                             base_url="http://no/such/url")
    3337          docinfo = tree.docinfo
    3338          self.assertEqual(docinfo.URL, "http://no/such/url")
    3339
    3340 -    def test_HTML_base_url_docinfo(self):
    3341          etree = self.etree
    3342          root = etree.HTML(_bytes("<html/>"), base_url="http://no/such/url")
    3343          docinfo = root.getroottree().docinfo
    3344          self.assertEqual(docinfo.URL, "http://no/such/url")
    3345
    3346 -    def test_docinfo_public(self):
    3347          etree = self.etree
    3348          xml_header = '<?xml version="1.0" encoding="ascii"?>'
    3349          pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
    3350          sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    3351          doctype_string = '<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id)
    3352
    3353          xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
    3354
    3355          tree = etree.parse(BytesIO(xml))
    3356          docinfo = tree.docinfo
    3357          self.assertEqual(docinfo.encoding,    "ascii")
    3358          self.assertEqual(docinfo.xml_version, "1.0")
    3359          self.assertEqual(docinfo.public_id,   pub_id)
    3360          self.assertEqual(docinfo.system_url,  sys_id)
    3361          self.assertEqual(docinfo.root_name,   'html')
    3362          self.assertEqual(docinfo.doctype, doctype_string)
    3363
    3364 -    def test_docinfo_system(self):
    3365          etree = self.etree
    3366          xml_header = '<?xml version="1.0" encoding="UTF-8"?>'
    3367          sys_id = "some.dtd"
    3368          doctype_string = '<!DOCTYPE html SYSTEM "%s">' % sys_id
    3369          xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
    3370
    3371          tree = etree.parse(BytesIO(xml))
    3372          docinfo = tree.docinfo
    3373          self.assertEqual(docinfo.encoding,    "UTF-8")
    3374          self.assertEqual(docinfo.xml_version, "1.0")
    3375          self.assertEqual(docinfo.public_id,   None)
    3376          self.assertEqual(docinfo.system_url,  sys_id)
    3377          self.assertEqual(docinfo.root_name,   'html')
    3378          self.assertEqual(docinfo.doctype, doctype_string)
    3379
    3380 -    def test_docinfo_empty(self):
    3381          etree = self.etree
    3382          xml = _bytes('<html><body></body></html>')
    3383          tree = etree.parse(BytesIO(xml))
    3384          docinfo = tree.docinfo
    3385          self.assertEqual(docinfo.encoding,    "UTF-8")
    3386          self.assertEqual(docinfo.xml_version, "1.0")
    3387          self.assertEqual(docinfo.public_id,   None)
    3388          self.assertEqual(docinfo.system_url,  None)
    3389          self.assertEqual(docinfo.root_name,   'html')
    3390          self.assertEqual(docinfo.doctype, '')
    3391
    3392 -    def test_docinfo_name_only(self):
    3393          etree = self.etree
    3394          xml = _bytes('<!DOCTYPE root><root></root>')
    3395          tree = etree.parse(BytesIO(xml))
    3396          docinfo = tree.docinfo
    3397          self.assertEqual(docinfo.encoding,    "UTF-8")
    3398          self.assertEqual(docinfo.xml_version, "1.0")
    3399          self.assertEqual(docinfo.public_id,   None)
    3400          self.assertEqual(docinfo.system_url,  None)
    3401          self.assertEqual(docinfo.root_name,   'root')
    3402          self.assertEqual(docinfo.doctype, '<!DOCTYPE root>')
    3403
    3404 -    def test_doctype_name_only_roundtrip(self):
    3405          etree = self.etree
    3406          xml = _bytes('<!DOCTYPE root>\n<root/>')
    3407          tree = etree.parse(BytesIO(xml))
    3408          self.assertEqual(xml, etree.tostring(tree))
    3409
    3410 -    def test_doctype_output_override(self):
    3411          etree = self.etree
    3412          pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
    3413          sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    3414          doctype_string = _bytes('<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id))
    3415
    3416          xml = _bytes('<!DOCTYPE root>\n<root/>')
    3417          tree = etree.parse(BytesIO(xml))
    3418          self.assertEqual(xml.replace(_bytes('<!DOCTYPE root>'), doctype_string),
    3419                            etree.tostring(tree, doctype=doctype_string))
    3420
    3421 -    def test_xml_base(self):
    3422          etree = self.etree
    3423          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    3424          self.assertEqual(root.base, "http://no/such/url")
    3425          self.assertEqual(
    3426              root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
    3427          root.base = "https://secret/url"
    3428          self.assertEqual(root.base, "https://secret/url")
    3429          self.assertEqual(
    3430              root.get('{http://www.w3.org/XML/1998/namespace}base'),
    3431              "https://secret/url")
    3432
    3433 -    def test_xml_base_attribute(self):
    3434          etree = self.etree
    3435          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    3436          self.assertEqual(root.base, "http://no/such/url")
    3437          self.assertEqual(
    3438              root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
    3439          root.set('{http://www.w3.org/XML/1998/namespace}base',
    3440                   "https://secret/url")
    3441          self.assertEqual(root.base, "https://secret/url")
    3442          self.assertEqual(
    3443              root.get('{http://www.w3.org/XML/1998/namespace}base'),
    3444              "https://secret/url")
    3445
    3446 -    def test_html_base(self):
    3447          etree = self.etree
    3448          root = etree.HTML(_bytes("<html><body></body></html>"),
    3449                            base_url="http://no/such/url")
    3450          self.assertEqual(root.base, "http://no/such/url")
    3451
    3452 -    def test_html_base_tag(self):
    3453          etree = self.etree
    3454          root = etree.HTML(_bytes('<html><head><base href="http://no/such/url"></head></html>'))
    3455          self.assertEqual(root.base, "http://no/such/url")
    3456
    3457 -    def test_parse_fileobject_unicode(self):
    3458          # parse from a file object that returns unicode strings
    3459          f = LargeFileLikeUnicode()
    3460          tree = self.etree.parse(f)
    3461          root = tree.getroot()
    3462          self.assertTrue(root.tag.endswith('root'))
    3463
    3464 -    def test_dtd_io(self):
    3465          # check that DTDs that go in also go back out
    3466          xml = _bytes('''\
    3467          <!DOCTYPE test SYSTEM "test.dtd" [
    3468            <!ENTITY entity "tasty">
    3469            <!ELEMENT test (a)>
    3470            <!ELEMENT a (#PCDATA)>
    3471          ]>
    3472          <test><a>test-test</a></test>\
    3473          ''')
    3474          tree = self.etree.parse(BytesIO(xml))
    3475          self.assertEqual(self.etree.tostring(tree).replace(_bytes(" "), _bytes("")),
    3476                           xml.replace(_bytes(" "), _bytes("")))
    3477
    3478 -    def test_byte_zero(self):
    3479          Element = self.etree.Element
    3480
    3481          a = Element('a')
    3482          self.assertRaises(ValueError, setattr, a, "text", 'ha\0ho')
    3483          self.assertRaises(ValueError, setattr, a, "tail", 'ha\0ho')
    3484
    3485          self.assertRaises(ValueError, Element, 'ha\0ho')
    3486
    3487 -    def test_unicode_byte_zero(self):
    3488          Element = self.etree.Element
    3489
    3490          a = Element('a')
    3491          self.assertRaises(ValueError, setattr, a, "text",
    3492                            _str('ha\0ho'))
    3493          self.assertRaises(ValueError, setattr, a, "tail",
    3494                            _str('ha\0ho'))
    3495
    3496          self.assertRaises(ValueError, Element,
    3497                            _str('ha\0ho'))
    3498
    3499 -    def test_byte_invalid(self):
    3500          Element = self.etree.Element
    3501
    3502          a = Element('a')
    3503          self.assertRaises(ValueError, setattr, a, "text", 'ha\x07ho')
    3504          self.assertRaises(ValueError, setattr, a, "text", 'ha\x02ho')
    3505
    3506          self.assertRaises(ValueError, setattr, a, "tail", 'ha\x07ho')
    3507          self.assertRaises(ValueError, setattr, a, "tail", 'ha\x02ho')
    3508
    3509          self.assertRaises(ValueError, Element, 'ha\x07ho')
    3510          self.assertRaises(ValueError, Element, 'ha\x02ho')
    3511
    3512 -    def test_unicode_byte_invalid(self):
    3513          Element = self.etree.Element
    3514
    3515          a = Element('a')
    3516          self.assertRaises(ValueError, setattr, a, "text",
    3517                            _str('ha\x07ho'))
    3518          self.assertRaises(ValueError, setattr, a, "text",
    3519                            _str('ha\x02ho'))
    3520
    3521          self.assertRaises(ValueError, setattr, a, "tail",
    3522                            _str('ha\x07ho'))
    3523          self.assertRaises(ValueError, setattr, a, "tail",
    3524                            _str('ha\x02ho'))
    3525
    3526          self.assertRaises(ValueError, Element,
    3527                            _str('ha\x07ho'))
    3528          self.assertRaises(ValueError, Element,
    3529                            _str('ha\x02ho'))
    3530
    3531 -    def test_unicode_byte_invalid_sequence(self):
    3532          Element = self.etree.Element
    3533
    3534          a = Element('a')
    3535          self.assertRaises(ValueError, setattr, a, "text",
    3536                            _str('ha\u1234\x07ho'))
    3537          self.assertRaises(ValueError, setattr, a, "text",
    3538                            _str('ha\u1234\x02ho'))
    3539
    3540          self.assertRaises(ValueError, setattr, a, "tail",
    3541                            _str('ha\u1234\x07ho'))
    3542          self.assertRaises(ValueError, setattr, a, "tail",
    3543                            _str('ha\u1234\x02ho'))
    3544
    3545          self.assertRaises(ValueError, Element,
    3546                            _str('ha\u1234\x07ho'))
    3547          self.assertRaises(ValueError, Element,
    3548                            _str('ha\u1234\x02ho'))
    3549
    3550 -    def test_encoding_tostring_utf16(self):
    3551          # ElementTree fails to serialize this
    3552          tostring = self.etree.tostring
    3553          Element = self.etree.Element
    3554          SubElement = self.etree.SubElement
    3555
    3556          a = Element('a')
    3557          b = SubElement(a, 'b')
    3558          c = SubElement(a, 'c')
    3559
    3560          result = tostring(a, encoding='UTF-16')
    3561          self.assertEqual(_bytes('<a><b></b><c></c></a>'),
    3562                            canonicalize(result))
    3563
    3564 -    def test_tostring_none(self):
    3565          # ElementTree raises an AssertionError here
    3566          tostring = self.etree.tostring
    3567          self.assertRaises(TypeError, self.etree.tostring, None)
    3568
    3569 -    def test_tostring_pretty(self):
    3570          tostring = self.etree.tostring
    3571          Element = self.etree.Element
    3572          SubElement = self.etree.SubElement
    3573
    3574          a = Element('a')
    3575          b = SubElement(a, 'b')
    3576          c = SubElement(a, 'c')
    3577
    3578          result = tostring(a)
    3579          self.assertEqual(result, _bytes("<a><b/><c/></a>"))
    3580
    3581          result = tostring(a, pretty_print=False)
    3582          self.assertEqual(result, _bytes("<a><b/><c/></a>"))
    3583
    3584          result = tostring(a, pretty_print=True)
    3585          self.assertEqual(result, _bytes("<a>\n  <b/>\n  <c/>\n</a>\n"))
    3586
    3587 -    def test_tostring_with_tail(self):
    3588          tostring = self.etree.tostring
    3589          Element = self.etree.Element
    3590          SubElement = self.etree.SubElement
    3591
    3592          a = Element('a')
    3593          a.tail = "aTAIL"
    3594          b = SubElement(a, 'b')
    3595          b.tail = "bTAIL"
    3596          c = SubElement(a, 'c')
    3597
    3598          result = tostring(a)
    3599          self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
    3600
    3601          result = tostring(a, with_tail=False)
    3602          self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>"))
    3603
    3604          result = tostring(a, with_tail=True)
    3605          self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
    3606
    3607 -    def test_tostring_method_html_with_tail(self):
    3608          tostring = self.etree.tostring
    3609          html = self.etree.fromstring(
    3610              '<html><body>'
    3611              '<div><p>Some text<i>\r\n</i></p></div>\r\n'
    3612              '</body></html>',
    3613              parser=self.etree.HTMLParser())
    3614          self.assertEqual(html.tag, 'html')
    3615          div = html.find('.//div')
    3616          self.assertEqual(div.tail, '\r\n')
    3617          result = tostring(div, method='html')
    3618          self.assertEqual(
    3619              result,
    3620              _bytes("<div><p>Some text<i>\r\n</i></p></div>\r\n"))
    3621          result = tostring(div, method='html', with_tail=True)
    3622          self.assertEqual(
    3623              result,
    3624              _bytes("<div><p>Some text<i>\r\n</i></p></div>\r\n"))
    3625          result = tostring(div, method='html', with_tail=False)
    3626          self.assertEqual(
    3627              result,
    3628              _bytes("<div><p>Some text<i>\r\n</i></p></div>"))
    3629
    3630 -    def test_standalone(self):
    3631          tostring = self.etree.tostring
    3632          XML = self.etree.XML
    3633          ElementTree = self.etree.ElementTree
    3634          Element = self.etree.Element
    3635
    3636          tree = Element("root").getroottree()
    3637          self.assertEqual(None, tree.docinfo.standalone)
    3638
    3639          tree = XML(_bytes("<root/>")).getroottree()
    3640          self.assertEqual(None, tree.docinfo.standalone)
    3641
    3642          tree = XML(_bytes(
    3643              "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"
    3644              )).getroottree()
    3645          self.assertEqual(True, tree.docinfo.standalone)
    3646
    3647          tree = XML(_bytes(
    3648              "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>"
    3649              )).getroottree()
    3650          self.assertEqual(False, tree.docinfo.standalone)
    3651
    3652 -    def test_tostring_standalone(self):
    3653          tostring = self.etree.tostring
    3654          XML = self.etree.XML
    3655          ElementTree = self.etree.ElementTree
    3656
    3657          root = XML(_bytes("<root/>"))
    3658
    3659          tree = ElementTree(root)
    3660          self.assertEqual(None, tree.docinfo.standalone)
    3661
    3662          result = tostring(root, xml_declaration=True, encoding="ASCII")
    3663          self.assertEqual(result, _bytes(
    3664              "<?xml version='1.0' encoding='ASCII'?>\n<root/>"))
    3665
    3666          result = tostring(root, xml_declaration=True, encoding="ASCII",
    3667                            standalone=True)
    3668          self.assertEqual(result, _bytes(
    3669              "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"))
    3670
    3671          tree = ElementTree(XML(result))
    3672          self.assertEqual(True, tree.docinfo.standalone)
    3673
    3674          result = tostring(root, xml_declaration=True, encoding="ASCII",
    3675                            standalone=False)
    3676          self.assertEqual(result, _bytes(
    3677              "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>"))
    3678
    3679          tree = ElementTree(XML(result))
    3680          self.assertEqual(False, tree.docinfo.standalone)
    3681
    3682 -    def test_tostring_standalone_in_out(self):
    3683          tostring = self.etree.tostring
    3684          XML = self.etree.XML
    3685          ElementTree = self.etree.ElementTree
    3686
    3687          root = XML(_bytes(
    3688              "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>\n<root/>"))
    3689
    3690          tree = ElementTree(root)
    3691          self.assertEqual(True, tree.docinfo.standalone)
    3692
    3693          result = tostring(root, xml_declaration=True, encoding="ASCII")
    3694          self.assertEqual(result, _bytes(
    3695              "<?xml version='1.0' encoding='ASCII'?>\n<root/>"))
    3696
    3697          result = tostring(root, xml_declaration=True, encoding="ASCII",
    3698                            standalone=True)
    3699          self.assertEqual(result, _bytes(
    3700              "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"))
    3701
    3702 -    def test_tostring_method_text_encoding(self):
    3703          tostring = self.etree.tostring
    3704          Element = self.etree.Element
    3705          SubElement = self.etree.SubElement
    3706
    3707          a = Element('a')
    3708          a.text = "A"
    3709          a.tail = "tail"
    3710          b = SubElement(a, 'b')
    3711          b.text = "B"
    3712          b.tail = _str("Søk på nettet")
    3713          c = SubElement(a, 'c')
    3714          c.text = "C"
    3715
    3716          result = tostring(a, method="text", encoding="UTF-16")
    3717
    3718          self.assertEqual(_str('ABSøk på nettetCtail').encode("UTF-16"),
    3719                            result)
    3720
    3721 -    def test_tostring_method_text_unicode(self):
    3722          tostring = self.etree.tostring
    3723          Element = self.etree.Element
    3724          SubElement = self.etree.SubElement
    3725
    3726          a = Element('a')
    3727          a.text = _str('Søk på nettetA')
    3728          a.tail = "tail"
    3729          b = SubElement(a, 'b')
    3730          b.text = "B"
    3731          b.tail = _str('Søk på nettetB')
    3732          c = SubElement(a, 'c')
    3733          c.text = "C"
    3734
    3735          self.assertRaises(UnicodeEncodeError,
    3736                            tostring, a, method="text")
    3737
    3738          self.assertEqual(
    3739              _str('Søk på nettetABSøk på nettetBCtail').encode('utf-8'),
    3740              tostring(a, encoding="UTF-8", method="text"))
    3741
    3742 -    def test_tounicode(self):
    3743          tounicode = self.etree.tounicode
    3744          Element = self.etree.Element
    3745          SubElement = self.etree.SubElement
    3746
    3747          a = Element('a')
    3748          b = SubElement(a, 'b')
    3749          c = SubElement(a, 'c')
    3750
    3751          self.assertTrue(isinstance(tounicode(a), _unicode))
    3752          self.assertEqual(_bytes('<a><b></b><c></c></a>'),
    3753                            canonicalize(tounicode(a)))
    3754
    3755 -    def test_tounicode_element(self):
    3756          tounicode = self.etree.tounicode
    3757          Element = self.etree.Element
    3758          SubElement = self.etree.SubElement
    3759
    3760          a = Element('a')
    3761          b = SubElement(a, 'b')
    3762          c = SubElement(a, 'c')
    3763          d = SubElement(c, 'd')
    3764          self.assertTrue(isinstance(tounicode(b), _unicode))
    3765          self.assertTrue(isinstance(tounicode(c), _unicode))
    3766          self.assertEqual(_bytes('<b></b>'),
    3767                            canonicalize(tounicode(b)))
    3768          self.assertEqual(_bytes('<c><d></d></c>'),
    3769                            canonicalize(tounicode(c)))
    3770
    3771 -    def test_tounicode_none(self):
    3772          tounicode = self.etree.tounicode
    3773          self.assertRaises(TypeError, self.etree.tounicode, None)
    3774
    3775 -    def test_tounicode_element_tail(self):
    3776          tounicode = self.etree.tounicode
    3777          Element = self.etree.Element
    3778          SubElement = self.etree.SubElement
    3779
    3780          a = Element('a')
    3781          b = SubElement(a, 'b')
    3782          c = SubElement(a, 'c')
    3783          d = SubElement(c, 'd')
    3784          b.tail = 'Foo'
    3785
    3786          self.assertTrue(isinstance(tounicode(b), _unicode))
    3787          self.assertTrue(tounicode(b) == '<b/>Foo' or
    3788                       tounicode(b) == '<b />Foo')
    3789
    3790 -    def test_tounicode_pretty(self):
    3791          tounicode = self.etree.tounicode
    3792          Element = self.etree.Element
    3793          SubElement = self.etree.SubElement
    3794
    3795          a = Element('a')
    3796          b = SubElement(a, 'b')
    3797          c = SubElement(a, 'c')
    3798
    3799          result = tounicode(a)
    3800          self.assertEqual(result, "<a><b/><c/></a>")
    3801
    3802          result = tounicode(a, pretty_print=False)
    3803          self.assertEqual(result, "<a><b/><c/></a>")
    3804
    3805          result = tounicode(a, pretty_print=True)
    3806          self.assertEqual(result, "<a>\n  <b/>\n  <c/>\n</a>\n")
    3807
    3808 -    def test_tostring_unicode(self):
    3809          tostring = self.etree.tostring
    3810          Element = self.etree.Element
    3811          SubElement = self.etree.SubElement
    3812
    3813          a = Element('a')
    3814          b = SubElement(a, 'b')
    3815          c = SubElement(a, 'c')
    3816
    3817          self.assertTrue(isinstance(tostring(a, encoding=_unicode), _unicode))
    3818          self.assertEqual(_bytes('<a><b></b><c></c></a>'),
    3819                            canonicalize(tostring(a, encoding=_unicode)))
    3820
    3821 -    def test_tostring_unicode_element(self):
    3822          tostring = self.etree.tostring
    3823          Element = self.etree.Element
    3824          SubElement = self.etree.SubElement
    3825
    3826          a = Element('a')
    3827          b = SubElement(a, 'b')
    3828          c = SubElement(a, 'c')
    3829          d = SubElement(c, 'd')
    3830          self.assertTrue(isinstance(tostring(b, encoding=_unicode), _unicode))
    3831          self.assertTrue(isinstance(tostring(c, encoding=_unicode), _unicode))
    3832          self.assertEqual(_bytes('<b></b>'),
    3833                            canonicalize(tostring(b, encoding=_unicode)))
    3834          self.assertEqual(_bytes('<c><d></d></c>'),
    3835                            canonicalize(tostring(c, encoding=_unicode)))
    3836
    3837 -    def test_tostring_unicode_none(self):
    3838          tostring = self.etree.tostring
    3839          self.assertRaises(TypeError, self.etree.tostring,
    3840                            None, encoding=_unicode)
    3841
    3842 -    def test_tostring_unicode_element_tail(self):
    3843          tostring = self.etree.tostring
    3844          Element = self.etree.Element
    3845          SubElement = self.etree.SubElement
    3846
    3847          a = Element('a')
    3848          b = SubElement(a, 'b')
    3849          c = SubElement(a, 'c')
    3850          d = SubElement(c, 'd')
    3851          b.tail = 'Foo'
    3852
    3853          self.assertTrue(isinstance(tostring(b, encoding=_unicode), _unicode))
    3854          self.assertTrue(tostring(b, encoding=_unicode) == '<b/>Foo' or
    3855                       tostring(b, encoding=_unicode) == '<b />Foo')
    3856
    3857 -    def test_tostring_unicode_pretty(self):
    3858          tostring = self.etree.tostring
    3859          Element = self.etree.Element
    3860          SubElement = self.etree.SubElement
    3861
    3862          a = Element('a')
    3863          b = SubElement(a, 'b')
    3864          c = SubElement(a, 'c')
    3865
    3866          result = tostring(a, encoding=_unicode)
    3867          self.assertEqual(result, "<a><b/><c/></a>")
    3868
    3869          result = tostring(a, encoding=_unicode, pretty_print=False)
    3870          self.assertEqual(result, "<a><b/><c/></a>")
    3871
    3872          result = tostring(a, encoding=_unicode, pretty_print=True)
    3873          self.assertEqual(result, "<a>\n  <b/>\n  <c/>\n</a>\n")
    3874
    3875 -    def test_pypy_proxy_collect(self):
    3876          root = etree.Element('parent')
    3877          etree.SubElement(root, 'child')
    3878
    3879          self.assertEqual(len(root), 1)
    3880          self.assertEqual(root[0].tag, 'child')
    3881
    3882          # in PyPy, GC used to kill the Python proxy instance without cleanup
    3883          gc.collect()
    3884          self.assertEqual(len(root), 1)
    3885          self.assertEqual(root[0].tag, 'child')
    3886
    3887 -    def test_element_refcycle(self):
    3888          class SubEl(etree.ElementBase):
    3889              pass
    3890
    3891          el1 = SubEl()
    3892          el2 = SubEl()
    3893          self.assertEqual('SubEl', el1.tag)
    3894          self.assertEqual('SubEl', el2.tag)
    3895          el1.other = el2
    3896          el2.other = el1
    3897
    3898          del el1, el2
    3899          gc.collect()
    3900          # not really testing anything here, but it shouldn't crash
    3901
    3902 -    def test_proxy_collect_siblings(self):
    3903          root = etree.Element('parent')
    3904          c1 = etree.SubElement(root, 'child1')
    3905          c2 = etree.SubElement(root, 'child2')
    3906
    3907          root.remove(c1)
    3908          root.remove(c2)
    3909          c1.addnext(c2)
    3910          del c1
    3911          # trigger deallocation attempt of c1
    3912          c2.getprevious()
    3913          # make sure it wasn't deallocated
    3914          self.assertEqual('child1', c2.getprevious().tag)
    3915
    3916 -    def test_proxy_collect_siblings_text(self):
    3917          root = etree.Element('parent')
    3918          c1 = etree.SubElement(root, 'child1')
    3919          c2 = etree.SubElement(root, 'child2')
    3920
    3921          root.remove(c1)
    3922          root.remove(c2)
    3923          c1.addnext(c2)
    3924          c1.tail = 'abc'
    3925          c2.tail = 'xyz'
    3926          del c1
    3927          # trigger deallocation attempt of c1
    3928          c2.getprevious()
    3929          # make sure it wasn't deallocated
    3930          self.assertEqual('child1', c2.getprevious().tag)
    3931          self.assertEqual('abc', c2.getprevious().tail)
    3932
    3933      # helper methods
    3934
    3935 -    def _writeElement(self, element, encoding='us-ascii', compression=0):
    3936          """Write out element for comparison.
    3937          """
    3938          ElementTree = self.etree.ElementTree
    3939          f = BytesIO()
    3940          tree = ElementTree(element=element)
    3941          tree.write(f, encoding=encoding, compression=compression)
    3942          data = f.getvalue()
    3943          if compression:
    3944              data = zlib.decompress(data)
    3945          return canonicalize(data)
    3946
    3947
    3948 -class _XIncludeTestCase(HelperTestCase):
    3949 -    def test_xinclude_text(self):
    3950          filename = fileInTestDir('test_broken.xml')
    3951          root = etree.XML(_bytes('''\
    3952          <doc xmlns:xi="http://www.w3.org/2001/XInclude">
    3953            <xi:include href="%s" parse="text"/>
    3954          </doc>
    3955          ''' % path2url(filename)))
    3956          old_text = root.text
    3957          content = read_file(filename)
    3958          old_tail = root[0].tail
    3959
    3960          self.include( etree.ElementTree(root) )
    3961          self.assertEqual(old_text + content + old_tail,
    3962                            root.text)
    3963
    3964 -    def test_xinclude(self):
    3965          tree = etree.parse(fileInTestDir('include/test_xinclude.xml'))
    3966          self.assertNotEqual(
    3967              'a',
    3968              tree.getroot()[1].tag)
    3969          # process xincludes
    3970          self.include( tree )
    3971          # check whether we find it replaced with included data
    3972          self.assertEqual(
    3973              'a',
    3974              tree.getroot()[1].tag)
    3975
    3976 -    def test_xinclude_resolver(self):
    3977          class res(etree.Resolver):
    3978              include_text = read_file(fileInTestDir('test.xml'))
    3979              called = {}
    3980              def resolve(self, url, id, context):
    3981                  if url.endswith(".dtd"):
    3982                      self.called["dtd"] = True
    3983                      return self.resolve_filename(
    3984                          fileInTestDir('test.dtd'), context)
    3985                  elif url.endswith("test_xinclude.xml"):
    3986                      self.called["input"] = True
    3987                      return None # delegate to default resolver
    3988                  else:
    3989                      self.called["include"] = True
    3990                      return self.resolve_string(self.include_text, context)
    3991
    3992          res_instance = res()
    3993          parser = etree.XMLParser(load_dtd = True)
    3994          parser.resolvers.add(res_instance)
    3995
    3996          tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
    3997                             parser = parser)
    3998
    3999          self.include(tree)
    4000
    4001          called = list(res_instance.called.items())
    4002          called.sort()
    4003          self.assertEqual(
    4004              [("dtd", True), ("include", True), ("input", True)],
    4005              called)
    4006
    4007 -    def test_xinclude_resolver_recursive(self):
    4008          data = textwrap.dedent('''
    4009          <doc xmlns:xi="http://www.w3.org/2001/XInclude">
    4010          <foo/>
    4011          <xi:include href="./test.xml" />
    4012          </doc>
    4013          ''')
    4014
    4015          class Resolver(etree.Resolver):
    4016              called = {}
    4017
    4018              def resolve(self, url, id, context):
    4019                  if url.endswith("test_xinclude.xml"):
    4020                      assert not self.called.get("input")
    4021                      self.called["input"] = True
    4022                      return None  # delegate to default resolver
    4023                  elif url.endswith('/test5.xml'):
    4024                      assert not self.called.get("DONE")
    4025                      self.called["DONE"] = True
    4026                      return self.resolve_string('<DONE/>', context)
    4027                  else:
    4028                      _, filename = url.rsplit('/', 1)
    4029                      assert not self.called.get(filename)
    4030                      self.called[filename] = True
    4031                      next_data = data.replace(
    4032                          'test.xml', 'test%d.xml' % len(self.called))
    4033                      return self.resolve_string(next_data, context)
    4034
    4035          res_instance = Resolver()
    4036          parser = etree.XMLParser(load_dtd=True)
    4037          parser.resolvers.add(res_instance)
    4038
    4039          tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
    4040                             parser=parser)
    4041
    4042          self.include(tree)
    4043
    4044          called = list(res_instance.called.items())
    4045          called.sort()
    4046          self.assertEqual(
    4047              [("DONE", True), ("input", True), ("test.xml", True),
    4048               ("test2.xml", True), ("test3.xml", True), ("test4.xml", True)],
    4049              called)
    4050
    4051
    4052 -class ETreeXIncludeTestCase(_XIncludeTestCase):
    4053 -    def include(self, tree):
    4054          tree.xinclude()
    4055
    4056
    4057 -class ElementIncludeTestCase(_XIncludeTestCase):
    4058      from lxml import ElementInclude
    4059 -    def include(self, tree):
    4060          self.ElementInclude.include(tree.getroot())
    4061
    4062
    4063 -class ETreeC14NTestCase(HelperTestCase):
    4064 -    def test_c14n(self):
    4065          tree = self.parse(_bytes('<a><b/></a>'))
    4066          f = BytesIO()
    4067          tree.write_c14n(f)
    4068          s = f.getvalue()
    4069          self.assertEqual(_bytes('<a><b></b></a>'),
    4070                            s)
    4071
    4072 -    def test_c14n_gzip(self):
    4073          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    4074          f = BytesIO()
    4075          tree.write_c14n(f, compression=9)
    4076          with closing(gzip.GzipFile(fileobj=BytesIO(f.getvalue()))) as gzfile:
    4077              s = gzfile.read()
    4078          self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'),
    4079                            s)
    4080
    4081 -    def test_c14n_file(self):
    4082          tree = self.parse(_bytes('<a><b/></a>'))
    4083          with tmpfile() as filename:
    4084              tree.write_c14n(filename)
    4085              data = read_file(filename, 'rb')
    4086          self.assertEqual(_bytes('<a><b></b></a>'),
    4087                            data)
    4088
    4089 -    def test_c14n_file_gzip(self):
    4090          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    4091          with tmpfile() as filename:
    4092              tree.write_c14n(filename, compression=9)
    4093              with closing(gzip.open(filename, 'rb')) as f:
    4094                  data = f.read()
    4095          self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'),
    4096                            data)
    4097
    4098 -    def test_c14n_with_comments(self):
    4099          tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
    4100          f = BytesIO()
    4101          tree.write_c14n(f)
    4102          s = f.getvalue()
    4103          self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
    4104                            s)
    4105          f = BytesIO()
    4106          tree.write_c14n(f, with_comments=True)
    4107          s = f.getvalue()
    4108          self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
    4109                            s)
    4110          f = BytesIO()
    4111          tree.write_c14n(f, with_comments=False)
    4112          s = f.getvalue()
    4113          self.assertEqual(_bytes('<a><b></b></a>'),
    4114                            s)
    4115
    4116 -    def test_c14n_tostring_with_comments(self):
    4117          tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
    4118          s = etree.tostring(tree, method='c14n')
    4119          self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
    4120                            s)
    4121          s = etree.tostring(tree, method='c14n', with_comments=True)
    4122          self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
    4123                            s)
    4124          s = etree.tostring(tree, method='c14n', with_comments=False)
    4125          self.assertEqual(_bytes('<a><b></b></a>'),
    4126                            s)
    4127
    4128 -    def test_c14n_element_tostring_with_comments(self):
    4129          tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
    4130          s = etree.tostring(tree.getroot(), method='c14n')
    4131          self.assertEqual(_bytes('<a><!--ho--><b></b></a>'),
    4132                            s)
    4133          s = etree.tostring(tree.getroot(), method='c14n', with_comments=True)
    4134          self.assertEqual(_bytes('<a><!--ho--><b></b></a>'),
    4135                            s)
    4136          s = etree.tostring(tree.getroot(), method='c14n', with_comments=False)
    4137          self.assertEqual(_bytes('<a><b></b></a>'),
    4138                            s)
    4139
    4140 -    def test_c14n_exclusive(self):
    4141          tree = self.parse(_bytes(
    4142                  '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
    4143          f = BytesIO()
    4144          tree.write_c14n(f)
    4145          s = f.getvalue()
    4146          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    4147                            s)
    4148          f = BytesIO()
    4149          tree.write_c14n(f, exclusive=False)
    4150          s = f.getvalue()
    4151          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    4152                            s)
    4153          f = BytesIO()
    4154          tree.write_c14n(f, exclusive=True)
    4155          s = f.getvalue()
    4156          self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
    4157                            s)
    4158
    4159          f = BytesIO()
    4160          tree.write_c14n(f, exclusive=True, inclusive_ns_prefixes=['z'])
    4161          s = f.getvalue()
    4162          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:z="http://cde"><z:b></z:b></a>'),
    4163                            s)
    4164
    4165 -    def test_c14n_tostring_exclusive(self):
    4166          tree = self.parse(_bytes(
    4167                  '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
    4168          s = etree.tostring(tree, method='c14n')
    4169          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    4170                            s)
    4171          s = etree.tostring(tree, method='c14n', exclusive=False)
    4172          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    4173                            s)
    4174          s = etree.tostring(tree, method='c14n', exclusive=True)
    4175          self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
    4176                            s)
    4177
    4178          s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['y'])
    4179          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd"><z:b xmlns:z="http://cde"></z:b></a>'),
    4180                            s)
    4181
    4182 -    def test_c14n_element_tostring_exclusive(self):
    4183          tree = self.parse(_bytes(
    4184                  '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
    4185          s = etree.tostring(tree.getroot(), method='c14n')
    4186          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    4187                            s)
    4188          s = etree.tostring(tree.getroot(), method='c14n', exclusive=False)
    4189          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    4190                            s)
    4191          s = etree.tostring(tree.getroot(), method='c14n', exclusive=True)
    4192          self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
    4193                            s)
    4194
    4195          s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=False)
    4196          self.assertEqual(_bytes('<z:b xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'),
    4197                            s)
    4198          s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True)
    4199          self.assertEqual(_bytes('<z:b xmlns:z="http://cde"></z:b>'),
    4200                            s)
    4201
    4202          s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True, inclusive_ns_prefixes=['y'])
    4203          self.assertEqual(_bytes('<z:b xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'),
    4204                            s)
    4205
    4206 -    def test_c14n_tostring_inclusive_ns_prefixes(self):
    4207          """ Regression test to fix memory allocation issues (use 3+ inclusive NS spaces)"""
    4208          tree = self.parse(_bytes(
    4209                  '<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
    4210
    4211          s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['x', 'y', 'z'])
    4212          self.assertEqual(_bytes('<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    4213                            s)
    4214
    4215
    4216 -class ETreeWriteTestCase(HelperTestCase):
    4217 -    def test_write(self):
    4218          tree = self.parse(_bytes('<a><b/></a>'))
    4219          f = BytesIO()
    4220          tree.write(f)
    4221          s = f.getvalue()
    4222          self.assertEqual(_bytes('<a><b/></a>'),
    4223                            s)
    4224
    4225 -    def test_write_doctype(self):
    4226          tree = self.parse(_bytes('<a><b/></a>'))
    4227          f = BytesIO()
    4228          tree.write(f, doctype='HUHU')
    4229          s = f.getvalue()
    4230          self.assertEqual(_bytes('HUHU\n<a><b/></a>'),
    4231                            s)
    4232
    4233 -    def test_write_gzip(self):
    4234          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    4235          f = BytesIO()
    4236          tree.write(f, compression=9)
    4237          with closing(gzip.GzipFile(fileobj=BytesIO(f.getvalue()))) as gzfile:
    4238              s = gzfile.read()
    4239          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    4240                            s)
    4241
    4242 -    def test_write_gzip_doctype(self):
    4243          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    4244          f = BytesIO()
    4245          tree.write(f, compression=9, doctype='<!DOCTYPE a>')
    4246          with closing(gzip.GzipFile(fileobj=BytesIO(f.getvalue()))) as gzfile:
    4247              s = gzfile.read()
    4248          self.assertEqual(_bytes('<!DOCTYPE a>\n<a>'+'<b/>'*200+'</a>'),
    4249                            s)
    4250
    4251 -    def test_write_gzip_level(self):
    4252          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    4253          f = BytesIO()
    4254          tree.write(f, compression=0)
    4255          s0 = f.getvalue()
    4256
    4257          f = BytesIO()
    4258          tree.write(f)
    4259          self.assertEqual(f.getvalue(), s0)
    4260
    4261          f = BytesIO()
    4262          tree.write(f, compression=1)
    4263          s = f.getvalue()
    4264          self.assertTrue(len(s) <= len(s0))
    4265          with closing(gzip.GzipFile(fileobj=BytesIO(s))) as gzfile:
    4266              s1 = gzfile.read()
    4267
    4268          f = BytesIO()
    4269          tree.write(f, compression=9)
    4270          s = f.getvalue()
    4271          self.assertTrue(len(s) <= len(s0))
    4272          with closing(gzip.GzipFile(fileobj=BytesIO(s))) as gzfile:
    4273              s9 = gzfile.read()
    4274
    4275          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    4276                            s0)
    4277          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    4278                            s1)
    4279          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    4280                            s9)
    4281
    4282 -    def test_write_file(self):
    4283          tree = self.parse(_bytes('<a><b/></a>'))
    4284          with tmpfile() as filename:
    4285              tree.write(filename)
    4286              data = read_file(filename, 'rb')
    4287          self.assertEqual(_bytes('<a><b/></a>'),
    4288                            data)
    4289
    4290 -    def test_write_file_gzip(self):
    4291          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    4292          with tmpfile() as filename:
    4293              tree.write(filename, compression=9)
    4294              with closing(gzip.open(filename, 'rb')) as f:
    4295                  data = f.read()
    4296          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    4297                            data)
    4298
    4299 -    def test_write_file_gzip_parse(self):
    4300          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    4301          with tmpfile() as filename:
    4302              tree.write(filename, compression=9)
    4303              data = etree.tostring(etree.parse(filename))
    4304          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    4305                            data)
    4306
    4307 -    def test_write_file_gzipfile_parse(self):
    4308          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    4309          with tmpfile() as filename:
    4310              tree.write(filename, compression=9)
    4311              with closing(gzip.GzipFile(filename)) as f:
    4312                  data = etree.tostring(etree.parse(f))
    4313          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    4314                            data)
    4315
    4316
    4317 -class ETreeErrorLogTest(HelperTestCase):
    4318      etree = etree
    4319
    4320 -    def test_parse_error_logging(self):
    4321          parse = self.etree.parse
    4322          f = BytesIO('<a><b></c></b></a>')
    4323          self.etree.clear_error_log()
    4324          try:
    4325              parse(f)
    4326              logs = None
    4327          except SyntaxError:
    4328              e = sys.exc_info()[1]
    4329              logs = e.error_log
    4330          f.close()
    4331          self.assertTrue([ log for log in logs
    4332                         if 'mismatch' in log.message ])
    4333          self.assertTrue([ log for log in logs
    4334                         if 'PARSER'   in log.domain_name])
    4335          self.assertTrue([ log for log in logs
    4336                         if 'ERR_TAG_NAME_MISMATCH' in log.type_name ])
    4337          self.assertTrue([ log for log in logs
    4338                         if 1 == log.line ])
    4339          self.assertTrue([ log for log in logs
    4340                         if 15 == log.column ])
    4341
    4342 -    def _test_python_error_logging(self):
    4343          """This can't really be tested as long as there isn't a way to
    4344          reset the logging setup ...
    4345          """
    4346          parse = self.etree.parse
    4347
    4348          messages = []
    4349          class Logger(self.etree.PyErrorLog):
    4350              def log(self, entry, message, *args):
    4351                  messages.append(message)
    4352
    4353          self.etree.use_global_python_log(Logger())
    4354          f = BytesIO('<a><b></c></b></a>')
    4355          try:
    4356              parse(f)
    4357          except SyntaxError:
    4358              pass
    4359          f.close()
    4360
    4361          self.assertTrue([ message for message in messages
    4362                         if 'mismatch' in message ])
    4363          self.assertTrue([ message for message in messages
    4364                         if ':PARSER:'   in message])
    4365          self.assertTrue([ message for message in messages
    4366                         if ':ERR_TAG_NAME_MISMATCH:' in message ])
    4367          self.assertTrue([ message for message in messages
    4368                         if ':1:15:' in message ])
    4369
    4370
    4371 -class XMLPullParserTest(unittest.TestCase):
    4372      etree = etree
    4373
    4374 -    def assert_event_tags(self, events, expected):
    4375          self.assertEqual([(action, elem.tag) for action, elem in events],
    4376                           expected)
    4377
    4378 -    def test_pull_from_simple_target(self):
    4379          class Target(object):
    4380              def start(self, tag, attrib):
    4381                  return 'start(%s)' % tag
    4382              def end(self, tag):
    4383                  return 'end(%s)' % tag
    4384              def close(self):
    4385                  return 'close()'
    4386
    4387          parser = self.etree.XMLPullParser(target=Target())
    4388          events = parser.read_events()
    4389
    4390          parser.feed('<root><element>')
    4391          self.assertFalse(list(events))
    4392          self.assertFalse(list(events))
    4393          parser.feed('</element><child>')
    4394          self.assertEqual([('end', 'end(element)')], list(events))
    4395          parser.feed('</child>')
    4396          self.assertEqual([('end', 'end(child)')], list(events))
    4397          parser.feed('</root>')
    4398          self.assertEqual([('end', 'end(root)')], list(events))
    4399          self.assertFalse(list(events))
    4400          self.assertEqual('close()', parser.close())
    4401
    4402 -    def test_pull_from_simple_target_start_end(self):
    4403          class Target(object):
    4404              def start(self, tag, attrib):
    4405                  return 'start(%s)' % tag
    4406              def end(self, tag):
    4407                  return 'end(%s)' % tag
    4408              def close(self):
    4409                  return 'close()'
    4410
    4411          parser = self.etree.XMLPullParser(
    4412              ['start', 'end'], target=Target())
    4413          events = parser.read_events()
    4414
    4415          parser.feed('<root><element>')
    4416          self.assertEqual(
    4417              [('start', 'start(root)'), ('start', 'start(element)')],
    4418              list(events))
    4419          self.assertFalse(list(events))
    4420          parser.feed('</element><child>')
    4421          self.assertEqual(
    4422              [('end', 'end(element)'), ('start', 'start(child)')],
    4423              list(events))
    4424          parser.feed('</child>')
    4425          self.assertEqual(
    4426              [('end', 'end(child)')],
    4427              list(events))
    4428          parser.feed('</root>')
    4429          self.assertEqual(
    4430              [('end', 'end(root)')],
    4431              list(events))
    4432          self.assertFalse(list(events))
    4433          self.assertEqual('close()', parser.close())
    4434
    4435 -    def test_pull_from_tree_builder(self):
    4436          parser = self.etree.XMLPullParser(
    4437              ['start', 'end'], target=etree.TreeBuilder())
    4438          events = parser.read_events()
    4439
    4440          parser.feed('<root><element>')
    4441          self.assert_event_tags(
    4442              events, [('start', 'root'), ('start', 'element')])
    4443          self.assertFalse(list(events))
    4444          parser.feed('</element><child>')
    4445          self.assert_event_tags(
    4446              events, [('end', 'element'), ('start', 'child')])
    4447          parser.feed('</child>')
    4448          self.assert_event_tags(
    4449              events, [('end', 'child')])
    4450          parser.feed('</root>')
    4451          self.assert_event_tags(
    4452              events, [('end', 'root')])
    4453          self.assertFalse(list(events))
    4454          root = parser.close()
    4455          self.assertEqual('root', root.tag)
    4456
    4457 -    def test_pull_from_tree_builder_subclass(self):
    4458          class Target(etree.TreeBuilder):
    4459              def end(self, tag):
    4460                  el = super(Target, self).end(tag)
    4461                  el.tag += '-huhu'
    4462                  return el
    4463
    4464          parser = self.etree.XMLPullParser(
    4465              ['start', 'end'], target=Target())
    4466          events = parser.read_events()
    4467
    4468          parser.feed('<root><element>')
    4469          self.assert_event_tags(
    4470              events, [('start', 'root'), ('start', 'element')])
    4471          self.assertFalse(list(events))
    4472          parser.feed('</element><child>')
    4473          self.assert_event_tags(
    4474              events, [('end', 'element-huhu'), ('start', 'child')])
    4475          parser.feed('</child>')
    4476          self.assert_event_tags(
    4477              events, [('end', 'child-huhu')])
    4478          parser.feed('</root>')
    4479          self.assert_event_tags(
    4480              events, [('end', 'root-huhu')])
    4481          self.assertFalse(list(events))
    4482          root = parser.close()
    4483          self.assertEqual('root-huhu', root.tag)
    4484
    4485
    4486 -def test_suite():
    4487      suite = unittest.TestSuite()
    4488      suite.addTests([unittest.makeSuite(ETreeOnlyTestCase)])
    4489      suite.addTests([unittest.makeSuite(ETreeXIncludeTestCase)])
    4490      suite.addTests([unittest.makeSuite(ElementIncludeTestCase)])
    4491      suite.addTests([unittest.makeSuite(ETreeC14NTestCase)])
    4492      suite.addTests([unittest.makeSuite(ETreeWriteTestCase)])
    4493      suite.addTests([unittest.makeSuite(ETreeErrorLogTest)])
    4494      suite.addTests([unittest.makeSuite(XMLPullParserTest)])
    4495
    4496      # add original doctests from ElementTree selftest modules
    4497      from . import selftest, selftest2
    4498      suite.addTests(doctest.DocTestSuite(selftest))
    4499      suite.addTests(doctest.DocTestSuite(selftest2))
    4500
    4501      # add doctests
    4502      suite.addTests(doctest.DocTestSuite(etree))
    4503      suite.addTests(
    4504          [make_doctest('../../../doc/tutorial.txt')])
    4505      if sys.version_info >= (2,6):
    4506          # now requires the 'with' statement
    4507          suite.addTests(
    4508              [make_doctest('../../../doc/api.txt')])
    4509      suite.addTests(
    4510          [make_doctest('../../../doc/FAQ.txt')])
    4511      suite.addTests(
    4512          [make_doctest('../../../doc/parsing.txt')])
    4513      suite.addTests(
    4514          [make_doctest('../../../doc/resolvers.txt')])
    4515      return suite
    4516
    4517
    4518  if __name__ == '__main__':
    4519      print('to test use test.py %s' % __file__)
    4520