lxml.tests.test_etree

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

# Source Code for Module lxml.tests.test_etree

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