lxml.tests.test_etree

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