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

# Source Code for Module lxml.tests.test_etree

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