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