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_tail(self):
    1446          CDATA = self.etree.CDATA
    1447          Element = self.etree.Element
    1448          SubElement = self.etree.SubElement
    1449          tostring = self.etree.tostring
    1450
    1451          root = Element("root")
    1452          child = SubElement(root, 'child')
    1453          child.tail = CDATA('test')
    1454
    1455          self.assertEqual('test', child.tail)
    1456          self.assertEqual(_bytes('<root><child/><![CDATA[test]]></root>'),
    1457                           tostring(root))
    1458
    1459          root = Element("root")
    1460          root.tail = CDATA('test')
    1461
    1462          self.assertEqual('test', root.tail)
    1463          self.assertEqual(_bytes('<root/><![CDATA[test]]>'),
    1464                           tostring(root))
    1465
    1466 -    def test_cdata_type(self):
    1467          CDATA = self.etree.CDATA
    1468          Element = self.etree.Element
    1469          root = Element("root")
    1470
    1471          root.text = CDATA("test")
    1472          self.assertEqual('test', root.text)
    1473
    1474          root.text = CDATA(_str("test"))
    1475          self.assertEqual('test', root.text)
    1476
    1477          self.assertRaises(TypeError, CDATA, 1)
    1478
    1479 -    def test_cdata_errors(self):
    1480          CDATA = self.etree.CDATA
    1481          Element = self.etree.Element
    1482
    1483          root = Element("root")
    1484          cdata = CDATA('test')
    1485
    1486          self.assertRaises(TypeError,
    1487                            root.set, 'attr', cdata)
    1488          self.assertRaises(TypeError,
    1489                            operator.setitem, root.attrib, 'attr', cdata)
    1490
    1491 -    def test_cdata_parser(self):
    1492          tostring = self.etree.tostring
    1493          parser = self.etree.XMLParser(strip_cdata=False)
    1494          root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser)
    1495
    1496          self.assertEqual('test', root.text)
    1497          self.assertEqual(_bytes('<root><![CDATA[test]]></root>'),
    1498                            tostring(root))
    1499
    1500 -    def test_cdata_xpath(self):
    1501          tostring = self.etree.tostring
    1502          parser = self.etree.XMLParser(strip_cdata=False)
    1503          root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'), parser)
    1504          self.assertEqual(_bytes('<root><![CDATA[test]]></root>'),
    1505                            tostring(root))
    1506
    1507          self.assertEqual(['test'], root.xpath('//text()'))
    1508
    1509      # TypeError in etree, AssertionError in ElementTree;
    1510 -    def test_setitem_assert(self):
    1511          Element = self.etree.Element
    1512          SubElement = self.etree.SubElement
    1513
    1514          a = Element('a')
    1515          b = SubElement(a, 'b')
    1516
    1517          self.assertRaises(TypeError,
    1518                            a.__setitem__, 0, 'foo')
    1519
    1520 -    def test_append_error(self):
    1521          Element = self.etree.Element
    1522          root = Element('root')
    1523          # raises AssertionError in ElementTree
    1524          self.assertRaises(TypeError, root.append, None)
    1525          self.assertRaises(TypeError, root.extend, [None])
    1526          self.assertRaises(TypeError, root.extend, [Element('one'), None])
    1527          self.assertEqual('one', root[0].tag)
    1528
    1529 -    def test_append_recursive_error(self):
    1530          Element = self.etree.Element
    1531          SubElement = self.etree.SubElement
    1532          root = Element('root')
    1533          self.assertRaises(ValueError, root.append, root)
    1534          child = SubElement(root, 'child')
    1535          self.assertRaises(ValueError, child.append, root)
    1536          child2 = SubElement(child, 'child2')
    1537          self.assertRaises(ValueError, child2.append, root)
    1538          self.assertRaises(ValueError, child2.append, child)
    1539          self.assertEqual('child2', root[0][0].tag)
    1540
    1541 -    def test_addnext(self):
    1542          Element = self.etree.Element
    1543          SubElement = self.etree.SubElement
    1544          root = Element('root')
    1545          SubElement(root, 'a')
    1546          SubElement(root, 'b')
    1547
    1548          self.assertEqual(['a', 'b'],
    1549                            [c.tag for c in root])
    1550          root[1].addnext(root[0])
    1551          self.assertEqual(['b', 'a'],
    1552                            [c.tag for c in root])
    1553
    1554 -    def test_addprevious(self):
    1555          Element = self.etree.Element
    1556          SubElement = self.etree.SubElement
    1557          root = Element('root')
    1558          SubElement(root, 'a')
    1559          SubElement(root, 'b')
    1560
    1561          self.assertEqual(['a', 'b'],
    1562                            [c.tag for c in root])
    1563          root[0].addprevious(root[1])
    1564          self.assertEqual(['b', 'a'],
    1565                            [c.tag for c in root])
    1566
    1567 -    def test_addnext_cycle(self):
    1568          Element = self.etree.Element
    1569          SubElement = self.etree.SubElement
    1570          root = Element('root')
    1571          a = SubElement(root, 'a')
    1572          b = SubElement(a, 'b')
    1573          # appending parent as sibling is forbidden
    1574          self.assertRaises(ValueError, b.addnext, a)
    1575          self.assertEqual(['a'], [c.tag for c in root])
    1576          self.assertEqual(['b'], [c.tag for c in a])
    1577
    1578 -    def test_addprevious_cycle(self):
    1579          Element = self.etree.Element
    1580          SubElement = self.etree.SubElement
    1581          root = Element('root')
    1582          a = SubElement(root, 'a')
    1583          b = SubElement(a, 'b')
    1584          # appending parent as sibling is forbidden
    1585          self.assertRaises(ValueError, b.addprevious, a)
    1586          self.assertEqual(['a'], [c.tag for c in root])
    1587          self.assertEqual(['b'], [c.tag for c in a])
    1588
    1589 -    def test_addnext_cycle_long(self):
    1590          Element = self.etree.Element
    1591          SubElement = self.etree.SubElement
    1592          root = Element('root')
    1593          a = SubElement(root, 'a')
    1594          b = SubElement(a, 'b')
    1595          c = SubElement(b, 'c')
    1596          # appending parent as sibling is forbidden
    1597          self.assertRaises(ValueError, c.addnext, a)
    1598
    1599 -    def test_addprevious_cycle_long(self):
    1600          Element = self.etree.Element
    1601          SubElement = self.etree.SubElement
    1602          root = Element('root')
    1603          a = SubElement(root, 'a')
    1604          b = SubElement(a, 'b')
    1605          c = SubElement(b, 'c')
    1606          # appending parent as sibling is forbidden
    1607          self.assertRaises(ValueError, c.addprevious, a)
    1608
    1609 -    def test_addprevious_noops(self):
    1610          Element = self.etree.Element
    1611          SubElement = self.etree.SubElement
    1612          root = Element('root')
    1613          a = SubElement(root, 'a')
    1614          b = SubElement(root, 'b')
    1615          a.addprevious(a)
    1616          self.assertEqual('a', root[0].tag)
    1617          self.assertEqual('b', root[1].tag)
    1618          b.addprevious(b)
    1619          self.assertEqual('a', root[0].tag)
    1620          self.assertEqual('b', root[1].tag)
    1621          b.addprevious(a)
    1622          self.assertEqual('a', root[0].tag)
    1623          self.assertEqual('b', root[1].tag)
    1624
    1625 -    def test_addnext_noops(self):
    1626          Element = self.etree.Element
    1627          SubElement = self.etree.SubElement
    1628          root = Element('root')
    1629          a = SubElement(root, 'a')
    1630          b = SubElement(root, 'b')
    1631          a.addnext(a)
    1632          self.assertEqual('a', root[0].tag)
    1633          self.assertEqual('b', root[1].tag)
    1634          b.addnext(b)
    1635          self.assertEqual('a', root[0].tag)
    1636          self.assertEqual('b', root[1].tag)
    1637          a.addnext(b)
    1638          self.assertEqual('a', root[0].tag)
    1639          self.assertEqual('b', root[1].tag)
    1640
    1641 -    def test_addnext_root(self):
    1642          Element = self.etree.Element
    1643          a = Element('a')
    1644          b = Element('b')
    1645          self.assertRaises(TypeError, a.addnext, b)
    1646
    1647 -    def test_addprevious_pi(self):
    1648          Element = self.etree.Element
    1649          SubElement = self.etree.SubElement
    1650          PI = self.etree.PI
    1651          root = Element('root')
    1652          SubElement(root, 'a')
    1653          pi = PI('TARGET', 'TEXT')
    1654          pi.tail = "TAIL"
    1655
    1656          self.assertEqual(_bytes('<root><a></a></root>'),
    1657                            self._writeElement(root))
    1658          root[0].addprevious(pi)
    1659          self.assertEqual(_bytes('<root><?TARGET TEXT?>TAIL<a></a></root>'),
    1660                            self._writeElement(root))
    1661
    1662 -    def test_addprevious_root_pi(self):
    1663          Element = self.etree.Element
    1664          PI = self.etree.PI
    1665          root = Element('root')
    1666          pi = PI('TARGET', 'TEXT')
    1667          pi.tail = "TAIL"
    1668
    1669          self.assertEqual(_bytes('<root></root>'),
    1670                            self._writeElement(root))
    1671          root.addprevious(pi)
    1672          self.assertEqual(_bytes('<?TARGET TEXT?>\n<root></root>'),
    1673                            self._writeElement(root))
    1674
    1675 -    def test_addnext_pi(self):
    1676          Element = self.etree.Element
    1677          SubElement = self.etree.SubElement
    1678          PI = self.etree.PI
    1679          root = Element('root')
    1680          SubElement(root, 'a')
    1681          pi = PI('TARGET', 'TEXT')
    1682          pi.tail = "TAIL"
    1683
    1684          self.assertEqual(_bytes('<root><a></a></root>'),
    1685                            self._writeElement(root))
    1686          root[0].addnext(pi)
    1687          self.assertEqual(_bytes('<root><a></a><?TARGET TEXT?>TAIL</root>'),
    1688                            self._writeElement(root))
    1689
    1690 -    def test_addnext_root_pi(self):
    1691          Element = self.etree.Element
    1692          PI = self.etree.PI
    1693          root = Element('root')
    1694          pi = PI('TARGET', 'TEXT')
    1695          pi.tail = "TAIL"
    1696
    1697          self.assertEqual(_bytes('<root></root>'),
    1698                            self._writeElement(root))
    1699          root.addnext(pi)
    1700          self.assertEqual(_bytes('<root></root>\n<?TARGET TEXT?>'),
    1701                            self._writeElement(root))
    1702
    1703 -    def test_addnext_comment(self):
    1704          Element = self.etree.Element
    1705          SubElement = self.etree.SubElement
    1706          Comment = self.etree.Comment
    1707          root = Element('root')
    1708          SubElement(root, 'a')
    1709          comment = Comment('TEXT ')
    1710          comment.tail = "TAIL"
    1711
    1712          self.assertEqual(_bytes('<root><a></a></root>'),
    1713                            self._writeElement(root))
    1714          root[0].addnext(comment)
    1715          self.assertEqual(_bytes('<root><a></a><!--TEXT -->TAIL</root>'),
    1716                            self._writeElement(root))
    1717
    1718 -    def test_addnext_root_comment(self):
    1719          Element = self.etree.Element
    1720          Comment = self.etree.Comment
    1721          root = Element('root')
    1722          comment = Comment('TEXT ')
    1723          comment.tail = "TAIL"
    1724
    1725          self.assertEqual(_bytes('<root></root>'),
    1726                            self._writeElement(root))
    1727          root.addnext(comment)
    1728          self.assertEqual(_bytes('<root></root>\n<!--TEXT -->'),
    1729                            self._writeElement(root))
    1730
    1731 -    def test_addprevious_comment(self):
    1732          Element = self.etree.Element
    1733          SubElement = self.etree.SubElement
    1734          Comment = self.etree.Comment
    1735          root = Element('root')
    1736          SubElement(root, 'a')
    1737          comment = Comment('TEXT ')
    1738          comment.tail = "TAIL"
    1739
    1740          self.assertEqual(_bytes('<root><a></a></root>'),
    1741                            self._writeElement(root))
    1742          root[0].addprevious(comment)
    1743          self.assertEqual(_bytes('<root><!--TEXT -->TAIL<a></a></root>'),
    1744                            self._writeElement(root))
    1745
    1746 -    def test_addprevious_root_comment(self):
    1747          Element = self.etree.Element
    1748          Comment = self.etree.Comment
    1749          root = Element('root')
    1750          comment = Comment('TEXT ')
    1751          comment.tail = "TAIL"
    1752
    1753          self.assertEqual(_bytes('<root></root>'),
    1754                            self._writeElement(root))
    1755          root.addprevious(comment)
    1756          self.assertEqual(_bytes('<!--TEXT -->\n<root></root>'),
    1757                            self._writeElement(root))
    1758
    1759      # ET's Elements have items() and key(), but not values()
    1760 -    def test_attribute_values(self):
    1761          XML = self.etree.XML
    1762
    1763          root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
    1764          values = root.values()
    1765          values.sort()
    1766          self.assertEqual(['Alpha', 'Beta', 'Gamma'], values)
    1767
    1768      # gives error in ElementTree
    1769 -    def test_comment_empty(self):
    1770          Element = self.etree.Element
    1771          Comment = self.etree.Comment
    1772
    1773          a = Element('a')
    1774          a.append(Comment())
    1775          self.assertEqual(
    1776              _bytes('<a><!----></a>'),
    1777              self._writeElement(a))
    1778
    1779      # ElementTree ignores comments
    1780 -    def test_comment_parse_empty(self):
    1781          ElementTree = self.etree.ElementTree
    1782          tostring = self.etree.tostring
    1783
    1784          xml = _bytes('<a><b/><!----><c/></a>')
    1785          f = BytesIO(xml)
    1786          doc = ElementTree(file=f)
    1787          a = doc.getroot()
    1788          self.assertEqual(
    1789              '',
    1790              a[1].text)
    1791          self.assertEqual(
    1792              xml,
    1793              tostring(a))
    1794
    1795      # ElementTree ignores comments
    1796 -    def test_comment_no_proxy_yet(self):
    1797          ElementTree = self.etree.ElementTree
    1798
    1799          f = BytesIO('<a><b></b><!-- hoi --><c></c></a>')
    1800          doc = ElementTree(file=f)
    1801          a = doc.getroot()
    1802          self.assertEqual(
    1803              ' hoi ',
    1804              a[1].text)
    1805
    1806      # does not raise an exception in ElementTree
    1807 -    def test_comment_immutable(self):
    1808          Element = self.etree.Element
    1809          Comment = self.etree.Comment
    1810
    1811          c = Comment()
    1812          el = Element('myel')
    1813
    1814          self.assertRaises(TypeError, c.append, el)
    1815          self.assertRaises(TypeError, c.insert, 0, el)
    1816          self.assertRaises(TypeError, c.set, "myattr", "test")
    1817
    1818 -    def test_comment_immutable_attrib(self):
    1819          c = self.etree.Comment()
    1820          self.assertEqual(0, len(c.attrib))
    1821
    1822          self.assertFalse(c.attrib.__contains__('nope'))
    1823          self.assertFalse('nope' in c.attrib)
    1824          self.assertFalse('nope' in c.attrib.keys())
    1825          self.assertFalse('nope' in c.attrib.values())
    1826          self.assertFalse(('nope', 'huhu') in c.attrib.items())
    1827
    1828          self.assertEqual([], list(c.attrib))
    1829          self.assertEqual([], list(c.attrib.keys()))
    1830          self.assertEqual([], list(c.attrib.items()))
    1831          self.assertEqual([], list(c.attrib.values()))
    1832          self.assertEqual([], list(c.attrib.iterkeys()))
    1833          self.assertEqual([], list(c.attrib.iteritems()))
    1834          self.assertEqual([], list(c.attrib.itervalues()))
    1835
    1836          self.assertEqual('HUHU', c.attrib.pop('nope', 'HUHU'))
    1837          self.assertRaises(KeyError, c.attrib.pop, 'nope')
    1838
    1839          self.assertRaises(KeyError, c.attrib.__getitem__, 'only')
    1840          self.assertRaises(KeyError, c.attrib.__getitem__, 'names')
    1841          self.assertRaises(KeyError, c.attrib.__getitem__, 'nope')
    1842          self.assertRaises(KeyError, c.attrib.__setitem__, 'nope', 'yep')
    1843          self.assertRaises(KeyError, c.attrib.__delitem__, 'nope')
    1844
    1845      # test passing 'None' to dump()
    1846 -    def test_dump_none(self):
    1847          self.assertRaises(TypeError, self.etree.dump, None)
    1848
    1849 -    def test_prefix(self):
    1850          ElementTree = self.etree.ElementTree
    1851
    1852          f = BytesIO('<a xmlns:foo="http://www.infrae.com/ns/1"><foo:b/></a>')
    1853          doc = ElementTree(file=f)
    1854          a = doc.getroot()
    1855          self.assertEqual(
    1856              None,
    1857              a.prefix)
    1858          self.assertEqual(
    1859              'foo',
    1860              a[0].prefix)
    1861
    1862 -    def test_prefix_default_ns(self):
    1863          ElementTree = self.etree.ElementTree
    1864
    1865          f = BytesIO('<a xmlns="http://www.infrae.com/ns/1"><b/></a>')
    1866          doc = ElementTree(file=f)
    1867          a = doc.getroot()
    1868          self.assertEqual(
    1869              None,
    1870              a.prefix)
    1871          self.assertEqual(
    1872              None,
    1873              a[0].prefix)
    1874
    1875 -    def test_getparent(self):
    1876          Element = self.etree.Element
    1877          SubElement = self.etree.SubElement
    1878
    1879          a = Element('a')
    1880          b = SubElement(a, 'b')
    1881          c = SubElement(a, 'c')
    1882          d = SubElement(b, 'd')
    1883          self.assertEqual(
    1884              None,
    1885              a.getparent())
    1886          self.assertEqual(
    1887              a,
    1888              b.getparent())
    1889          self.assertEqual(
    1890              b.getparent(),
    1891              c.getparent())
    1892          self.assertEqual(
    1893              b,
    1894              d.getparent())
    1895
    1896 -    def test_iterchildren(self):
    1897          XML = self.etree.XML
    1898
    1899          root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
    1900          result = []
    1901          for el in root.iterchildren():
    1902              result.append(el.tag)
    1903          self.assertEqual(['one', 'two', 'three'], result)
    1904
    1905 -    def test_iterchildren_reversed(self):
    1906          XML = self.etree.XML
    1907
    1908          root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
    1909          result = []
    1910          for el in root.iterchildren(reversed=True):
    1911              result.append(el.tag)
    1912          self.assertEqual(['three', 'two', 'one'], result)
    1913
    1914 -    def test_iterchildren_tag(self):
    1915          XML = self.etree.XML
    1916
    1917          root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
    1918          result = []
    1919          for el in root.iterchildren(tag='two'):
    1920              result.append(el.text)
    1921          self.assertEqual(['Two', 'Bla'], result)
    1922
    1923 -    def test_iterchildren_tag_posarg(self):
    1924          XML = self.etree.XML
    1925
    1926          root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
    1927          result = []
    1928          for el in root.iterchildren('two'):
    1929              result.append(el.text)
    1930          self.assertEqual(['Two', 'Bla'], result)
    1931
    1932 -    def test_iterchildren_tag_reversed(self):
    1933          XML = self.etree.XML
    1934
    1935          root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two></doc>'))
    1936          result = []
    1937          for el in root.iterchildren(reversed=True, tag='two'):
    1938              result.append(el.text)
    1939          self.assertEqual(['Bla', 'Two'], result)
    1940
    1941 -    def test_iterchildren_tag_multiple(self):
    1942          XML = self.etree.XML
    1943
    1944          root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
    1945          result = []
    1946          for el in root.iterchildren(tag=['two', 'three']):
    1947              result.append(el.text)
    1948          self.assertEqual(['Two', 'Bla', None], result)
    1949
    1950 -    def test_iterchildren_tag_multiple_posarg(self):
    1951          XML = self.etree.XML
    1952
    1953          root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
    1954          result = []
    1955          for el in root.iterchildren('two', 'three'):
    1956              result.append(el.text)
    1957          self.assertEqual(['Two', 'Bla', None], result)
    1958
    1959 -    def test_iterchildren_tag_multiple_reversed(self):
    1960          XML = self.etree.XML
    1961
    1962          root = XML(_bytes('<doc><one/><two>Two</two>Hm<two>Bla</two><three/></doc>'))
    1963          result = []
    1964          for el in root.iterchildren(reversed=True, tag=['two', 'three']):
    1965              result.append(el.text)
    1966          self.assertEqual([None, 'Bla', 'Two'], result)
    1967
    1968 -    def test_iterancestors(self):
    1969          Element    = self.etree.Element
    1970          SubElement = self.etree.SubElement
    1971
    1972          a = Element('a')
    1973          b = SubElement(a, 'b')
    1974          c = SubElement(a, 'c')
    1975          d = SubElement(b, 'd')
    1976          self.assertEqual(
    1977              [],
    1978              list(a.iterancestors()))
    1979          self.assertEqual(
    1980              [a],
    1981              list(b.iterancestors()))
    1982          self.assertEqual(
    1983              [a],
    1984              list(c.iterancestors()))
    1985          self.assertEqual(
    1986              [b, a],
    1987              list(d.iterancestors()))
    1988
    1989 -    def test_iterancestors_tag(self):
    1990          Element    = self.etree.Element
    1991          SubElement = self.etree.SubElement
    1992
    1993          a = Element('a')
    1994          b = SubElement(a, 'b')
    1995          c = SubElement(a, 'c')
    1996          d = SubElement(b, 'd')
    1997          self.assertEqual(
    1998              [a],
    1999              list(d.iterancestors('a')))
    2000          self.assertEqual(
    2001              [a],
    2002              list(d.iterancestors(tag='a')))
    2003
    2004          self.assertEqual(
    2005              [b, a],
    2006              list(d.iterancestors('*')))
    2007          self.assertEqual(
    2008              [b, a],
    2009              list(d.iterancestors(tag='*')))
    2010
    2011 -    def test_iterancestors_tag_multiple(self):
    2012          Element    = self.etree.Element
    2013          SubElement = self.etree.SubElement
    2014
    2015          a = Element('a')
    2016          b = SubElement(a, 'b')
    2017          c = SubElement(a, 'c')
    2018          d = SubElement(b, 'd')
    2019          self.assertEqual(
    2020              [b, a],
    2021              list(d.iterancestors(tag=('a', 'b'))))
    2022          self.assertEqual(
    2023              [b, a],
    2024              list(d.iterancestors('a', 'b')))
    2025
    2026          self.assertEqual(
    2027              [],
    2028              list(d.iterancestors(tag=('w', 'x', 'y', 'z'))))
    2029          self.assertEqual(
    2030              [],
    2031              list(d.iterancestors('w', 'x', 'y', 'z')))
    2032
    2033          self.assertEqual(
    2034              [],
    2035              list(d.iterancestors(tag=('d', 'x'))))
    2036          self.assertEqual(
    2037              [],
    2038              list(d.iterancestors('d', 'x')))
    2039
    2040          self.assertEqual(
    2041              [b, a],
    2042              list(d.iterancestors(tag=('b', '*'))))
    2043          self.assertEqual(
    2044              [b, a],
    2045              list(d.iterancestors('b', '*')))
    2046
    2047          self.assertEqual(
    2048              [b],
    2049              list(d.iterancestors(tag=('b', 'c'))))
    2050          self.assertEqual(
    2051              [b],
    2052              list(d.iterancestors('b', 'c')))
    2053
    2054 -    def test_iterdescendants(self):
    2055          Element = self.etree.Element
    2056          SubElement = self.etree.SubElement
    2057
    2058          a = Element('a')
    2059          b = SubElement(a, 'b')
    2060          c = SubElement(a, 'c')
    2061          d = SubElement(b, 'd')
    2062          e = SubElement(c, 'e')
    2063
    2064          self.assertEqual(
    2065              [b, d, c, e],
    2066              list(a.iterdescendants()))
    2067          self.assertEqual(
    2068              [],
    2069              list(d.iterdescendants()))
    2070
    2071 -    def test_iterdescendants_tag(self):
    2072          Element = self.etree.Element
    2073          SubElement = self.etree.SubElement
    2074
    2075          a = Element('a')
    2076          b = SubElement(a, 'b')
    2077          c = SubElement(a, 'c')
    2078          d = SubElement(b, 'd')
    2079          e = SubElement(c, 'e')
    2080
    2081          self.assertEqual(
    2082              [],
    2083              list(a.iterdescendants('a')))
    2084          self.assertEqual(
    2085              [],
    2086              list(a.iterdescendants(tag='a')))
    2087
    2088          a2 = SubElement(e, 'a')
    2089          self.assertEqual(
    2090              [a2],
    2091              list(a.iterdescendants('a')))
    2092
    2093          self.assertEqual(
    2094              [a2],
    2095              list(c.iterdescendants('a')))
    2096          self.assertEqual(
    2097              [a2],
    2098              list(c.iterdescendants(tag='a')))
    2099
    2100 -    def test_iterdescendants_tag_multiple(self):
    2101          Element = self.etree.Element
    2102          SubElement = self.etree.SubElement
    2103
    2104          a = Element('a')
    2105          b = SubElement(a, 'b')
    2106          c = SubElement(a, 'c')
    2107          d = SubElement(b, 'd')
    2108          e = SubElement(c, 'e')
    2109
    2110          self.assertEqual(
    2111              [b, e],
    2112              list(a.iterdescendants(tag=('a', 'b', 'e'))))
    2113          self.assertEqual(
    2114              [b, e],
    2115              list(a.iterdescendants('a', 'b', 'e')))
    2116
    2117          a2 = SubElement(e, 'a')
    2118          self.assertEqual(
    2119              [b, a2],
    2120              list(a.iterdescendants(tag=('a', 'b'))))
    2121          self.assertEqual(
    2122              [b, a2],
    2123              list(a.iterdescendants('a', 'b')))
    2124
    2125          self.assertEqual(
    2126              [],
    2127              list(c.iterdescendants(tag=('x', 'y', 'z'))))
    2128          self.assertEqual(
    2129              [],
    2130              list(c.iterdescendants('x', 'y', 'z')))
    2131
    2132          self.assertEqual(
    2133              [b, d, c, e, a2],
    2134              list(a.iterdescendants(tag=('x', 'y', 'z', '*'))))
    2135          self.assertEqual(
    2136              [b, d, c, e, a2],
    2137              list(a.iterdescendants('x', 'y', 'z', '*')))
    2138
    2139 -    def test_getroottree(self):
    2140          Element = self.etree.Element
    2141          SubElement = self.etree.SubElement
    2142
    2143          a = Element('a')
    2144          b = SubElement(a, 'b')
    2145          c = SubElement(a, 'c')
    2146          d = SubElement(b, 'd')
    2147          self.assertEqual(
    2148              a,
    2149              a.getroottree().getroot())
    2150          self.assertEqual(
    2151              a,
    2152              b.getroottree().getroot())
    2153          self.assertEqual(
    2154              a,
    2155              d.getroottree().getroot())
    2156
    2157 -    def test_getnext(self):
    2158          Element    = self.etree.Element
    2159          SubElement = self.etree.SubElement
    2160
    2161          a = Element('a')
    2162          b = SubElement(a, 'b')
    2163          c = SubElement(a, 'c')
    2164          self.assertEqual(
    2165              None,
    2166              a.getnext())
    2167          self.assertEqual(
    2168              c,
    2169              b.getnext())
    2170          self.assertEqual(
    2171              None,
    2172              c.getnext())
    2173
    2174 -    def test_getprevious(self):
    2175          Element    = self.etree.Element
    2176          SubElement = self.etree.SubElement
    2177
    2178          a = Element('a')
    2179          b = SubElement(a, 'b')
    2180          c = SubElement(a, 'c')
    2181          d = SubElement(b, 'd')
    2182          self.assertEqual(
    2183              None,
    2184              a.getprevious())
    2185          self.assertEqual(
    2186              b,
    2187              c.getprevious())
    2188          self.assertEqual(
    2189              None,
    2190              b.getprevious())
    2191
    2192 -    def test_itersiblings(self):
    2193          Element    = self.etree.Element
    2194          SubElement = self.etree.SubElement
    2195
    2196          a = Element('a')
    2197          b = SubElement(a, 'b')
    2198          c = SubElement(a, 'c')
    2199          d = SubElement(b, 'd')
    2200          self.assertEqual(
    2201              [],
    2202              list(a.itersiblings()))
    2203          self.assertEqual(
    2204              [c],
    2205              list(b.itersiblings()))
    2206          self.assertEqual(
    2207              [],
    2208              list(c.itersiblings()))
    2209          self.assertEqual(
    2210              [b],
    2211              list(c.itersiblings(preceding=True)))
    2212          self.assertEqual(
    2213              [],
    2214              list(b.itersiblings(preceding=True)))
    2215
    2216 -    def test_itersiblings_tag(self):
    2217          Element    = self.etree.Element
    2218          SubElement = self.etree.SubElement
    2219
    2220          a = Element('a')
    2221          b = SubElement(a, 'b')
    2222          c = SubElement(a, 'c')
    2223          d = SubElement(b, 'd')
    2224          self.assertEqual(
    2225              [],
    2226              list(a.itersiblings(tag='XXX')))
    2227          self.assertEqual(
    2228              [c],
    2229              list(b.itersiblings(tag='c')))
    2230          self.assertEqual(
    2231              [c],
    2232              list(b.itersiblings(tag='*')))
    2233          self.assertEqual(
    2234              [b],
    2235              list(c.itersiblings(preceding=True, tag='b')))
    2236          self.assertEqual(
    2237              [],
    2238              list(c.itersiblings(preceding=True, tag='c')))
    2239
    2240 -    def test_itersiblings_tag_multiple(self):
    2241          Element    = self.etree.Element
    2242          SubElement = self.etree.SubElement
    2243
    2244          a = Element('a')
    2245          b = SubElement(a, 'b')
    2246          c = SubElement(a, 'c')
    2247          d = SubElement(b, 'd')
    2248          e = SubElement(a, 'e')
    2249          self.assertEqual(
    2250              [],
    2251              list(a.itersiblings(tag=('XXX', 'YYY'))))
    2252          self.assertEqual(
    2253              [c, e],
    2254              list(b.itersiblings(tag=('c', 'd', 'e'))))
    2255          self.assertEqual(
    2256              [b],
    2257              list(c.itersiblings(preceding=True, tag=('b', 'b', 'c', 'd'))))
    2258          self.assertEqual(
    2259              [c, b],
    2260              list(e.itersiblings(preceding=True, tag=('c', '*'))))
    2261
    2262 -    def test_parseid(self):
    2263          parseid = self.etree.parseid
    2264          XML     = self.etree.XML
    2265          xml_text = _bytes('''
    2266          <!DOCTYPE document [
    2267          <!ELEMENT document (h1,p)*>
    2268          <!ELEMENT h1 (#PCDATA)>
    2269          <!ATTLIST h1 myid ID #REQUIRED>
    2270          <!ELEMENT p  (#PCDATA)>
    2271          <!ATTLIST p  someid ID #REQUIRED>
    2272          ]>
    2273          <document>
    2274            <h1 myid="chapter1">...</h1>
    2275            <p id="note1" class="note">...</p>
    2276            <p>Regular paragraph.</p>
    2277            <p xml:id="xmlid">XML:ID paragraph.</p>
    2278            <p someid="warn1" class="warning">...</p>
    2279          </document>
    2280          ''')
    2281
    2282          tree, dic = parseid(BytesIO(xml_text))
    2283          root = tree.getroot()
    2284          root2 = XML(xml_text)
    2285          self.assertEqual(self._writeElement(root),
    2286                            self._writeElement(root2))
    2287          expected = {
    2288              "chapter1" : root[0],
    2289              "xmlid"    : root[3],
    2290              "warn1"    : root[4]
    2291              }
    2292          self.assertTrue("chapter1" in dic)
    2293          self.assertTrue("warn1" in dic)
    2294          self.assertTrue("xmlid" in dic)
    2295          self._checkIDDict(dic, expected)
    2296
    2297 -    def test_XMLDTDID(self):
    2298          XMLDTDID = self.etree.XMLDTDID
    2299          XML      = self.etree.XML
    2300          xml_text = _bytes('''
    2301          <!DOCTYPE document [
    2302          <!ELEMENT document (h1,p)*>
    2303          <!ELEMENT h1 (#PCDATA)>
    2304          <!ATTLIST h1 myid ID #REQUIRED>
    2305          <!ELEMENT p  (#PCDATA)>
    2306          <!ATTLIST p  someid ID #REQUIRED>
    2307          ]>
    2308          <document>
    2309            <h1 myid="chapter1">...</h1>
    2310            <p id="note1" class="note">...</p>
    2311            <p>Regular paragraph.</p>
    2312            <p xml:id="xmlid">XML:ID paragraph.</p>
    2313            <p someid="warn1" class="warning">...</p>
    2314          </document>
    2315          ''')
    2316
    2317          root, dic = XMLDTDID(xml_text)
    2318          root2 = XML(xml_text)
    2319          self.assertEqual(self._writeElement(root),
    2320                            self._writeElement(root2))
    2321          expected = {
    2322              "chapter1" : root[0],
    2323              "xmlid"    : root[3],
    2324              "warn1"    : root[4]
    2325              }
    2326          self.assertTrue("chapter1" in dic)
    2327          self.assertTrue("warn1" in dic)
    2328          self.assertTrue("xmlid" in dic)
    2329          self._checkIDDict(dic, expected)
    2330
    2331 -    def test_XMLDTDID_empty(self):
    2332          XMLDTDID = self.etree.XMLDTDID
    2333          XML      = self.etree.XML
    2334          xml_text = _bytes('''
    2335          <document>
    2336            <h1 myid="chapter1">...</h1>
    2337            <p id="note1" class="note">...</p>
    2338            <p>Regular paragraph.</p>
    2339            <p someid="warn1" class="warning">...</p>
    2340          </document>
    2341          ''')
    2342
    2343          root, dic = XMLDTDID(xml_text)
    2344          root2 = XML(xml_text)
    2345          self.assertEqual(self._writeElement(root),
    2346                            self._writeElement(root2))
    2347          expected = {}
    2348          self._checkIDDict(dic, expected)
    2349
    2350 -    def test_XMLDTDID_no_id_dict(self):
    2351          XMLDTDID = self.etree.XMLDTDID
    2352          XML      = self.etree.XML
    2353          xml_text = _bytes('''
    2354          <!DOCTYPE document [
    2355          <!ELEMENT document (h1,p)*>
    2356          <!ELEMENT h1 (#PCDATA)>
    2357          <!ATTLIST h1 myid ID #REQUIRED>
    2358          <!ELEMENT p  (#PCDATA)>
    2359          <!ATTLIST p  someid ID #REQUIRED>
    2360          ]>
    2361          <document>
    2362            <h1 myid="chapter1">...</h1>
    2363            <p id="note1" class="note">...</p>
    2364            <p>Regular paragraph.</p>
    2365            <p xml:id="xmlid">XML:ID paragraph.</p>
    2366            <p someid="warn1" class="warning">...</p>
    2367          </document>
    2368          ''')
    2369
    2370          parser = etree.XMLParser(collect_ids=False)
    2371          root, dic = XMLDTDID(xml_text, parser=parser)
    2372          root2 = XML(xml_text)
    2373          self.assertEqual(self._writeElement(root),
    2374                           self._writeElement(root2))
    2375          self.assertFalse(dic)
    2376          self._checkIDDict(dic, {})
    2377
    2378 -    def _checkIDDict(self, dic, expected):
    2379          self.assertEqual(len(dic),
    2380                            len(expected))
    2381          self.assertEqual(sorted(dic.items()),
    2382                            sorted(expected.items()))
    2383          if sys.version_info < (3,):
    2384              self.assertEqual(sorted(dic.iteritems()),
    2385                                sorted(expected.iteritems()))
    2386          self.assertEqual(sorted(dic.keys()),
    2387                            sorted(expected.keys()))
    2388          if sys.version_info < (3,):
    2389              self.assertEqual(sorted(dic.iterkeys()),
    2390                                sorted(expected.iterkeys()))
    2391          if sys.version_info < (3,):
    2392              self.assertEqual(sorted(dic.values()),
    2393                                sorted(expected.values()))
    2394              self.assertEqual(sorted(dic.itervalues()),
    2395                                sorted(expected.itervalues()))
    2396
    2397 -    def test_namespaces(self):
    2398          etree = self.etree
    2399
    2400          r = {'foo': 'http://ns.infrae.com/foo'}
    2401          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2402          self.assertEqual(
    2403              'foo',
    2404              e.prefix)
    2405          self.assertEqual(
    2406              _bytes('<foo:bar xmlns:foo="http://ns.infrae.com/foo"></foo:bar>'),
    2407              self._writeElement(e))
    2408
    2409 -    def test_namespaces_default(self):
    2410          etree = self.etree
    2411
    2412          r = {None: 'http://ns.infrae.com/foo'}
    2413          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2414          self.assertEqual(
    2415              None,
    2416              e.prefix)
    2417          self.assertEqual(
    2418              '{http://ns.infrae.com/foo}bar',
    2419              e.tag)
    2420          self.assertEqual(
    2421              _bytes('<bar xmlns="http://ns.infrae.com/foo"></bar>'),
    2422              self._writeElement(e))
    2423
    2424 -    def test_namespaces_default_and_attr(self):
    2425          etree = self.etree
    2426
    2427          r = {None: 'http://ns.infrae.com/foo',
    2428               'hoi': 'http://ns.infrae.com/hoi'}
    2429          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2430          e.set('{http://ns.infrae.com/hoi}test', 'value')
    2431          self.assertEqual(
    2432              _bytes('<bar xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi" hoi:test="value"></bar>'),
    2433              self._writeElement(e))
    2434
    2435 -    def test_attribute_keeps_namespace_prefix_on_merge(self):
    2436          etree = self.etree
    2437
    2438          root = etree.Element('{http://test/ns}root',
    2439                               nsmap={None: 'http://test/ns'})
    2440          sub = etree.Element('{http://test/ns}sub',
    2441                              nsmap={'test': 'http://test/ns'})
    2442
    2443          sub.attrib['{http://test/ns}attr'] = 'value'
    2444          self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
    2445          self.assertEqual(
    2446              _bytes('<test:sub xmlns:test="http://test/ns" test:attr="value"/>'),
    2447              etree.tostring(sub))
    2448
    2449          root.append(sub)
    2450          self.assertEqual(
    2451              _bytes('<root xmlns="http://test/ns">'
    2452                     '<sub xmlns:test="http://test/ns" test:attr="value"/>'
    2453                     '</root>'),
    2454              etree.tostring(root))
    2455
    2456 -    def test_attribute_keeps_namespace_prefix_on_merge_with_nons(self):
    2457          etree = self.etree
    2458
    2459          root = etree.Element('root')
    2460          sub = etree.Element('{http://test/ns}sub',
    2461                              nsmap={'test': 'http://test/ns'})
    2462
    2463          sub.attrib['{http://test/ns}attr'] = 'value'
    2464          self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
    2465          self.assertEqual(
    2466              _bytes('<test:sub xmlns:test="http://test/ns" test:attr="value"/>'),
    2467              etree.tostring(sub))
    2468
    2469          root.append(sub)
    2470          self.assertEqual(
    2471              _bytes('<root>'
    2472                     '<test:sub xmlns:test="http://test/ns" test:attr="value"/>'
    2473                     '</root>'),
    2474              etree.tostring(root))
    2475
    2476 -    def test_attribute_gets_namespace_prefix_on_merge_with_nons(self):
    2477          etree = self.etree
    2478
    2479          root = etree.Element('root')
    2480          sub = etree.Element('{http://test/ns}sub',
    2481                              nsmap={None: 'http://test/ns'})
    2482
    2483          sub.attrib['{http://test/ns}attr'] = 'value'
    2484          self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
    2485          self.assertEqual(
    2486              _bytes('<sub xmlns="http://test/ns" '
    2487                     'xmlns:ns0="http://test/ns" ns0:attr="value"/>'),
    2488              etree.tostring(sub))
    2489
    2490          root.append(sub)
    2491          self.assertEqual(
    2492              _bytes('<root>'
    2493                     '<sub xmlns="http://test/ns"'
    2494                     ' xmlns:ns0="http://test/ns" ns0:attr="value"/>'
    2495                     '</root>'),
    2496              etree.tostring(root))
    2497
    2498 -    def test_attribute_gets_namespace_prefix_on_merge(self):
    2499          etree = self.etree
    2500
    2501          root = etree.Element('{http://test/ns}root',
    2502                               nsmap={'test': 'http://test/ns',
    2503                                      None: 'http://test/ns'})
    2504          sub = etree.Element('{http://test/ns}sub',
    2505                              nsmap={None: 'http://test/ns'})
    2506
    2507          sub.attrib['{http://test/ns}attr'] = 'value'
    2508          self.assertEqual(sub.attrib['{http://test/ns}attr'], 'value')
    2509          self.assertEqual(
    2510              _bytes('<sub xmlns="http://test/ns" '
    2511                     'xmlns:ns0="http://test/ns" ns0:attr="value"/>'),
    2512              etree.tostring(sub))
    2513
    2514          root.append(sub)
    2515          self.assertEqual(
    2516              _bytes('<test:root xmlns:test="http://test/ns" xmlns="http://test/ns">'
    2517                     '<test:sub test:attr="value"/>'
    2518                     '</test:root>'),
    2519              etree.tostring(root))
    2520
    2521 -    def test_namespaces_elementtree(self):
    2522          etree = self.etree
    2523          r = {None: 'http://ns.infrae.com/foo',
    2524               'hoi': 'http://ns.infrae.com/hoi'}
    2525          e = etree.Element('{http://ns.infrae.com/foo}z', nsmap=r)
    2526          tree = etree.ElementTree(element=e)
    2527          etree.SubElement(e, '{http://ns.infrae.com/hoi}x')
    2528          self.assertEqual(
    2529              _bytes('<z xmlns="http://ns.infrae.com/foo" xmlns:hoi="http://ns.infrae.com/hoi"><hoi:x></hoi:x></z>'),
    2530              self._writeElement(e))
    2531
    2532 -    def test_namespaces_default_copy_element(self):
    2533          etree = self.etree
    2534
    2535          r = {None: 'http://ns.infrae.com/foo'}
    2536          e1 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2537          e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2538
    2539          e1.append(e2)
    2540
    2541          self.assertEqual(
    2542              None,
    2543              e1.prefix)
    2544          self.assertEqual(
    2545              None,
    2546              e1[0].prefix)
    2547          self.assertEqual(
    2548              '{http://ns.infrae.com/foo}bar',
    2549              e1.tag)
    2550          self.assertEqual(
    2551              '{http://ns.infrae.com/foo}bar',
    2552              e1[0].tag)
    2553
    2554 -    def test_namespaces_copy_element(self):
    2555          etree = self.etree
    2556
    2557          r = {None: 'http://ns.infrae.com/BAR'}
    2558          e1 = etree.Element('{http://ns.infrae.com/BAR}bar', nsmap=r)
    2559          e2 = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2560
    2561          e1.append(e2)
    2562
    2563          self.assertEqual(
    2564              None,
    2565              e1.prefix)
    2566          self.assertNotEqual(
    2567              None,
    2568              e2.prefix)
    2569          self.assertEqual(
    2570              '{http://ns.infrae.com/BAR}bar',
    2571              e1.tag)
    2572          self.assertEqual(
    2573              '{http://ns.infrae.com/foo}bar',
    2574              e2.tag)
    2575
    2576 -    def test_namespaces_reuse_after_move(self):
    2577          ns_href = "http://a.b.c"
    2578          one = self.etree.fromstring(
    2579              _bytes('<foo><bar xmlns:ns="%s"><ns:baz/></bar></foo>' % ns_href))
    2580          baz = one[0][0]
    2581
    2582          two = self.etree.fromstring(
    2583              _bytes('<root xmlns:ns="%s"/>' % ns_href))
    2584          two.append(baz)
    2585          del one # make sure the source document is deallocated
    2586
    2587          self.assertEqual('{%s}baz' % ns_href, baz.tag)
    2588          self.assertEqual(
    2589              _bytes('<root xmlns:ns="%s"><ns:baz/></root>' % ns_href),
    2590              self.etree.tostring(two))
    2591
    2592 -    def test_namespace_cleanup(self):
    2593          xml = _bytes('<foo xmlns="F" xmlns:x="x"><bar xmlns:ns="NS" xmlns:b="b" xmlns="B"><ns:baz/></bar></foo>')
    2594          root = self.etree.fromstring(xml)
    2595          self.assertEqual(xml,
    2596                            self.etree.tostring(root))
    2597          self.etree.cleanup_namespaces(root)
    2598          self.assertEqual(
    2599              _bytes('<foo xmlns="F"><bar xmlns:ns="NS" xmlns="B"><ns:baz/></bar></foo>'),
    2600              self.etree.tostring(root))
    2601
    2602 -    def test_element_nsmap(self):
    2603          etree = self.etree
    2604
    2605          r = {None: 'http://ns.infrae.com/foo',
    2606               'hoi': 'http://ns.infrae.com/hoi'}
    2607          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=r)
    2608          self.assertEqual(
    2609              r,
    2610              e.nsmap)
    2611
    2612 -    def test_subelement_nsmap(self):
    2613          etree = self.etree
    2614
    2615          re = {None: 'http://ns.infrae.com/foo',
    2616               'hoi': 'http://ns.infrae.com/hoi'}
    2617          e = etree.Element('{http://ns.infrae.com/foo}bar', nsmap=re)
    2618
    2619          rs = {None: 'http://ns.infrae.com/honk',
    2620               'top': 'http://ns.infrae.com/top'}
    2621          s = etree.SubElement(e, '{http://ns.infrae.com/honk}bar', nsmap=rs)
    2622
    2623          r = re.copy()
    2624          r.update(rs)
    2625          self.assertEqual(re, e.nsmap)
    2626          self.assertEqual(r,  s.nsmap)
    2627
    2628 -    def test_html_prefix_nsmap(self):
    2629          etree = self.etree
    2630          el = etree.HTML('<hha:page-description>aa</hha:page-description>').find('.//page-description')
    2631          self.assertEqual({'hha': None}, el.nsmap)
    2632
    2633 -    def test_getiterator_filter_multiple(self):
    2634          Element = self.etree.Element
    2635          SubElement = self.etree.SubElement
    2636
    2637          a = Element('a')
    2638          b = SubElement(a, 'b')
    2639          c = SubElement(a, 'c')
    2640          d = SubElement(b, 'd')
    2641          e = SubElement(c, 'e')
    2642          f = SubElement(c, 'f')
    2643
    2644          self.assertEqual(
    2645              [a, b],
    2646                 list(a.getiterator('a', 'b')))
    2647          self.assertEqual(
    2648              [],
    2649                list(a.getiterator('x', 'y')))
    2650          self.assertEqual(
    2651              [a, f],
    2652                list(a.getiterator('f', 'a')))
    2653          self.assertEqual(
    2654              [c, e, f],
    2655                 list(c.getiterator('c', '*', 'a')))
    2656          self.assertEqual(
    2657              [],
    2658                    list(a.getiterator( (), () )))
    2659
    2660 -    def test_getiterator_filter_multiple_tuple(self):
    2661          Element = self.etree.Element
    2662          SubElement = self.etree.SubElement
    2663
    2664          a = Element('a')
    2665          b = SubElement(a, 'b')
    2666          c = SubElement(a, 'c')
    2667          d = SubElement(b, 'd')
    2668          e = SubElement(c, 'e')
    2669          f = SubElement(c, 'f')
    2670
    2671          self.assertEqual(
    2672              [a, b],
    2673                    list(a.getiterator( ('a', 'b') )))
    2674          self.assertEqual(
    2675              [],
    2676                list(a.getiterator( ('x', 'y') )))
    2677          self.assertEqual(
    2678              [a, f],
    2679                    list(a.getiterator( ('f', 'a') )))
    2680          self.assertEqual(
    2681              [c, e, f],
    2682                       list(c.getiterator( ('c', '*', 'a') )))
    2683          self.assertEqual(
    2684              [],
    2685                list(a.getiterator( () )))
    2686
    2687 -    def test_getiterator_filter_namespace(self):
    2688          Element = self.etree.Element
    2689          SubElement = self.etree.SubElement
    2690
    2691          a = Element('{a}a')
    2692          b = SubElement(a, '{a}b')
    2693          c = SubElement(a, '{a}c')
    2694          d = SubElement(b, '{b}d')
    2695          e = SubElement(c, '{a}e')
    2696          f = SubElement(c, '{b}f')
    2697          g = SubElement(c, 'g')
    2698
    2699          self.assertEqual(
    2700              [a],
    2701              list(a.getiterator('{a}a')))
    2702          self.assertEqual(
    2703              [],
    2704              list(a.getiterator('{b}a')))
    2705          self.assertEqual(
    2706              [],
    2707              list(a.getiterator('a')))
    2708          self.assertEqual(
    2709              [a,b,d,c,e,f,g],
    2710              list(a.getiterator('*')))
    2711          self.assertEqual(
    2712              [f],
    2713              list(c.getiterator('{b}*')))
    2714          self.assertEqual(
    2715              [d, f],
    2716              list(a.getiterator('{b}*')))
    2717          self.assertEqual(
    2718              [g],
    2719              list(a.getiterator('g')))
    2720          self.assertEqual(
    2721              [g],
    2722              list(a.getiterator('{}g')))
    2723          self.assertEqual(
    2724              [g],
    2725              list(a.getiterator('{}*')))
    2726
    2727 -    def test_getiterator_filter_local_name(self):
    2728          Element = self.etree.Element
    2729          SubElement = self.etree.SubElement
    2730
    2731          a = Element('{a}a')
    2732          b = SubElement(a, '{nsA}b')
    2733          c = SubElement(b, '{nsB}b')
    2734          d = SubElement(a, 'b')
    2735          e = SubElement(a, '{nsA}e')
    2736          f = SubElement(e, '{nsB}e')
    2737          g = SubElement(e, 'e')
    2738
    2739          self.assertEqual(
    2740              [b, c, d],
    2741              list(a.getiterator('{*}b')))
    2742          self.assertEqual(
    2743              [e, f, g],
    2744              list(a.getiterator('{*}e')))
    2745          self.assertEqual(
    2746              [a, b, c, d, e, f, g],
    2747              list(a.getiterator('{*}*')))
    2748
    2749 -    def test_getiterator_filter_entities(self):
    2750          Element = self.etree.Element
    2751          Entity = self.etree.Entity
    2752          SubElement = self.etree.SubElement
    2753
    2754          a = Element('a')
    2755          b = SubElement(a, 'b')
    2756          entity_b = Entity("TEST-b")
    2757          b.append(entity_b)
    2758
    2759          self.assertEqual(
    2760              [entity_b],
    2761              list(a.getiterator(Entity)))
    2762
    2763          entity_a = Entity("TEST-a")
    2764          a.append(entity_a)
    2765
    2766          self.assertEqual(
    2767              [entity_b, entity_a],
    2768              list(a.getiterator(Entity)))
    2769
    2770          self.assertEqual(
    2771              [entity_b],
    2772              list(b.getiterator(Entity)))
    2773
    2774 -    def test_getiterator_filter_element(self):
    2775          Element = self.etree.Element
    2776          Comment = self.etree.Comment
    2777          PI = self.etree.PI
    2778          SubElement = self.etree.SubElement
    2779
    2780          a = Element('a')
    2781          b = SubElement(a, 'b')
    2782          a.append(Comment("test"))
    2783          a.append(PI("pi", "content"))
    2784          c = SubElement(a, 'c')
    2785
    2786          self.assertEqual(
    2787              [a, b, c],
    2788              list(a.getiterator(Element)))
    2789
    2790 -    def test_getiterator_filter_all_comment_pi(self):
    2791          # ElementTree iterates over everything here
    2792          Element = self.etree.Element
    2793          Comment = self.etree.Comment
    2794          PI = self.etree.PI
    2795          SubElement = self.etree.SubElement
    2796
    2797          a = Element('a')
    2798          b = SubElement(a, 'b')
    2799          a.append(Comment("test"))
    2800          a.append(PI("pi", "content"))
    2801          c = SubElement(a, 'c')
    2802
    2803          self.assertEqual(
    2804              [a, b, c],
    2805              list(a.getiterator('*')))
    2806
    2807 -    def test_elementtree_getelementpath(self):
    2808          a  = etree.Element("a")
    2809          b  = etree.SubElement(a, "b")
    2810          c  = etree.SubElement(a, "c")
    2811          d1 = etree.SubElement(c, "d")
    2812          d2 = etree.SubElement(c, "d")
    2813          c.text = d1.text = 'TEXT'
    2814
    2815          tree = etree.ElementTree(a)
    2816          self.assertEqual('.', tree.getelementpath(a))
    2817          self.assertEqual('c/d[1]', tree.getelementpath(d1))
    2818          self.assertEqual('c/d[2]', tree.getelementpath(d2))
    2819
    2820          self.assertEqual(d1, tree.find(tree.getelementpath(d1)))
    2821          self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
    2822
    2823          tree = etree.ElementTree(c)
    2824          self.assertEqual('.', tree.getelementpath(c))
    2825          self.assertEqual('d[2]', tree.getelementpath(d2))
    2826          self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
    2827
    2828          tree = etree.ElementTree(b)  # not a parent of a/c/d1/d2
    2829          self.assertEqual('.', tree.getelementpath(b))
    2830          self.assertRaises(ValueError, tree.getelementpath, a)
    2831          self.assertRaises(ValueError, tree.getelementpath, c)
    2832          self.assertRaises(ValueError, tree.getelementpath, d2)
    2833
    2834 -    def test_elementtree_getelementpath_ns(self):
    2835          a  = etree.Element("{http://ns1/}a")
    2836          b  = etree.SubElement(a, "{http://ns1/}b")
    2837          c  = etree.SubElement(a, "{http://ns1/}c")
    2838          d1 = etree.SubElement(c, "{http://ns1/}d")
    2839          d2 = etree.SubElement(c, "{http://ns2/}d")
    2840          d3 = etree.SubElement(c, "{http://ns1/}d")
    2841
    2842          tree = etree.ElementTree(a)
    2843          self.assertEqual('.', tree.getelementpath(a))
    2844          self.assertEqual('{http://ns1/}c/{http://ns1/}d[1]',
    2845                           tree.getelementpath(d1))
    2846          self.assertEqual('{http://ns1/}c/{http://ns2/}d',
    2847                           tree.getelementpath(d2))
    2848          self.assertEqual('{http://ns1/}c/{http://ns1/}d[2]',
    2849                           tree.getelementpath(d3))
    2850
    2851          self.assertEqual(a, tree.find(tree.getelementpath(a)))
    2852          self.assertEqual(b, tree.find(tree.getelementpath(b)))
    2853          self.assertEqual(c, tree.find(tree.getelementpath(c)))
    2854          self.assertEqual(d1, tree.find(tree.getelementpath(d1)))
    2855          self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
    2856          self.assertEqual(d3, tree.find(tree.getelementpath(d3)))
    2857
    2858          tree = etree.ElementTree(c)
    2859          self.assertEqual('{http://ns1/}d[1]', tree.getelementpath(d1))
    2860          self.assertEqual('{http://ns2/}d', tree.getelementpath(d2))
    2861          self.assertEqual('{http://ns1/}d[2]', tree.getelementpath(d3))
    2862          self.assertEqual(d1, tree.find(tree.getelementpath(d1)))
    2863          self.assertEqual(d2, tree.find(tree.getelementpath(d2)))
    2864          self.assertEqual(d3, tree.find(tree.getelementpath(d3)))
    2865
    2866          tree = etree.ElementTree(b)  # not a parent of d1/d2
    2867          self.assertRaises(ValueError, tree.getelementpath, d1)
    2868          self.assertRaises(ValueError, tree.getelementpath, d2)
    2869
    2870 -    def test_elementtree_find_qname(self):
    2871          XML = self.etree.XML
    2872          ElementTree = self.etree.ElementTree
    2873          QName = self.etree.QName
    2874          tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>')))
    2875          self.assertEqual(tree.find(QName("c")), tree.getroot()[2])
    2876
    2877 -    def test_elementtree_findall_qname(self):
    2878          XML = self.etree.XML
    2879          ElementTree = self.etree.ElementTree
    2880          QName = self.etree.QName
    2881          tree = ElementTree(XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>')))
    2882          self.assertEqual(len(list(tree.findall(QName("c")))), 1)
    2883
    2884 -    def test_elementtree_findall_ns_qname(self):
    2885          XML = self.etree.XML
    2886          ElementTree = self.etree.ElementTree
    2887          QName = self.etree.QName
    2888          tree = ElementTree(XML(
    2889                  _bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>')))
    2890          self.assertEqual(len(list(tree.findall(QName("b")))), 2)
    2891          self.assertEqual(len(list(tree.findall(QName("X", "b")))), 1)
    2892
    2893 -    def test_findall_ns(self):
    2894          XML = self.etree.XML
    2895          root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>'))
    2896          self.assertEqual(len(root.findall(".//{X}b")), 2)
    2897          self.assertEqual(len(root.findall(".//{X}*")), 2)
    2898          self.assertEqual(len(root.findall(".//b")), 3)
    2899
    2900 -    def test_findall_different_nsmaps(self):
    2901          XML = self.etree.XML
    2902          root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><y:b/></a>'))
    2903          nsmap = {'xx': 'X'}
    2904          self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 2)
    2905          self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 2)
    2906          self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
    2907          nsmap = {'xx': 'Y'}
    2908          self.assertEqual(len(root.findall(".//xx:b", namespaces=nsmap)), 1)
    2909          self.assertEqual(len(root.findall(".//xx:*", namespaces=nsmap)), 1)
    2910          self.assertEqual(len(root.findall(".//b", namespaces=nsmap)), 2)
    2911
    2912 -    def test_findall_syntax_error(self):
    2913          XML = self.etree.XML
    2914          root = XML(_bytes('<a><b><c/></b><b/><c><b/><b/></c><b/></a>'))
    2915          self.assertRaises(SyntaxError, root.findall, '')
    2916          self.assertRaises(SyntaxError, root.findall, '//')  # absolute path on Element
    2917          self.assertRaises(SyntaxError, root.findall, './//')
    2918
    2919 -    def test_index(self):
    2920          etree = self.etree
    2921          e = etree.Element('foo')
    2922          for i in range(10):
    2923              etree.SubElement(e, 'a%s' % i)
    2924          for i in range(10):
    2925              self.assertEqual(
    2926                  i,
    2927                  e.index(e[i]))
    2928          self.assertEqual(
    2929              3, e.index(e[3], 3))
    2930          self.assertRaises(
    2931              ValueError, e.index, e[3], 4)
    2932          self.assertRaises(
    2933              ValueError, e.index, e[3], 0, 2)
    2934          self.assertRaises(
    2935              ValueError, e.index, e[8], 0, -3)
    2936          self.assertRaises(
    2937              ValueError, e.index, e[8], -5, -3)
    2938          self.assertEqual(
    2939              8, e.index(e[8], 0, -1))
    2940          self.assertEqual(
    2941              8, e.index(e[8], -12, -1))
    2942          self.assertEqual(
    2943              0, e.index(e[0], -12, -1))
    2944
    2945 -    def test_replace(self):
    2946          etree = self.etree
    2947          e = etree.Element('foo')
    2948          for i in range(10):
    2949              el = etree.SubElement(e, 'a%s' % i)
    2950              el.text = "text%d" % i
    2951              el.tail = "tail%d" % i
    2952
    2953          child0 = e[0]
    2954          child1 = e[1]
    2955          child2 = e[2]
    2956
    2957          e.replace(e[0], e[1])
    2958          self.assertEqual(
    2959              9, len(e))
    2960          self.assertEqual(
    2961              child1, e[0])
    2962          self.assertEqual(
    2963              child1.text, "text1")
    2964          self.assertEqual(
    2965              child1.tail, "tail1")
    2966          self.assertEqual(
    2967              child0.tail, "tail0")
    2968          self.assertEqual(
    2969              child2, e[1])
    2970
    2971          e.replace(e[-1], e[0])
    2972          self.assertEqual(
    2973              child1, e[-1])
    2974          self.assertEqual(
    2975              child1.text, "text1")
    2976          self.assertEqual(
    2977              child1.tail, "tail1")
    2978          self.assertEqual(
    2979              child2, e[0])
    2980
    2981 -    def test_replace_new(self):
    2982          etree = self.etree
    2983          e = etree.Element('foo')
    2984          for i in range(10):
    2985              etree.SubElement(e, 'a%s' % i)
    2986
    2987          new_element = etree.Element("test")
    2988          new_element.text = "TESTTEXT"
    2989          new_element.tail = "TESTTAIL"
    2990          child1 = e[1]
    2991          e.replace(e[0], new_element)
    2992          self.assertEqual(
    2993              new_element, e[0])
    2994          self.assertEqual(
    2995              "TESTTEXT",
    2996              e[0].text)
    2997          self.assertEqual(
    2998              "TESTTAIL",
    2999              e[0].tail)
    3000          self.assertEqual(
    3001              child1, e[1])
    3002
    3003 -    def test_setslice_all_empty_reversed(self):
    3004          Element = self.etree.Element
    3005          SubElement = self.etree.SubElement
    3006
    3007          a = Element('a')
    3008
    3009          e = Element('e')
    3010          f = Element('f')
    3011          g = Element('g')
    3012
    3013          s = [e, f, g]
    3014          a[::-1] = s
    3015          self.assertEqual(
    3016              [g, f, e],
    3017              list(a))
    3018
    3019 -    def test_setslice_step(self):
    3020          Element = self.etree.Element
    3021          SubElement = self.etree.SubElement
    3022
    3023          a = Element('a')
    3024          b = SubElement(a, 'b')
    3025          c = SubElement(a, 'c')
    3026          d = SubElement(a, 'd')
    3027          e = SubElement(a, 'e')
    3028
    3029          x = Element('x')
    3030          y = Element('y')
    3031
    3032          a[1::2] = [x, y]
    3033          self.assertEqual(
    3034              [b, x, d, y],
    3035              list(a))
    3036
    3037 -    def test_setslice_step_negative(self):
    3038          Element = self.etree.Element
    3039          SubElement = self.etree.SubElement
    3040
    3041          a = Element('a')
    3042          b = SubElement(a, 'b')
    3043          c = SubElement(a, 'c')
    3044          d = SubElement(a, 'd')
    3045          e = SubElement(a, 'e')
    3046
    3047          x = Element('x')
    3048          y = Element('y')
    3049
    3050          a[1::-1] = [x, y]
    3051          self.assertEqual(
    3052              [y, x, d, e],
    3053              list(a))
    3054
    3055 -    def test_setslice_step_negative2(self):
    3056          Element = self.etree.Element
    3057          SubElement = self.etree.SubElement
    3058
    3059          a = Element('a')
    3060          b = SubElement(a, 'b')
    3061          c = SubElement(a, 'c')
    3062          d = SubElement(a, 'd')
    3063          e = SubElement(a, 'e')
    3064
    3065          x = Element('x')
    3066          y = Element('y')
    3067
    3068          a[::-2] = [x, y]
    3069          self.assertEqual(
    3070              [b, y, d, x],
    3071              list(a))
    3072
    3073 -    def test_setslice_step_overrun(self):
    3074          Element = self.etree.Element
    3075          SubElement = self.etree.SubElement
    3076          try:
    3077              slice
    3078          except NameError:
    3079              print("slice() not found")
    3080              return
    3081
    3082          a = Element('a')
    3083          b = SubElement(a, 'b')
    3084          c = SubElement(a, 'c')
    3085          d = SubElement(a, 'd')
    3086          e = SubElement(a, 'e')
    3087
    3088          x = Element('x')
    3089          y = Element('y')
    3090          z = Element('z')
    3091
    3092          self.assertRaises(
    3093              ValueError,
    3094              operator.setitem, a, slice(1,None,2), [x, y, z])
    3095
    3096          self.assertEqual(
    3097              [b, c, d, e],
    3098              list(a))
    3099
    3100 -    def test_sourceline_XML(self):
    3101          XML = self.etree.XML
    3102          root = XML(_bytes('''<?xml version="1.0"?>
    3103          <root><test>
    3104
    3105          <bla/></test>
    3106          </root>
    3107          '''))
    3108
    3109          self.assertEqual(
    3110              [2, 2, 4],
    3111              [ el.sourceline for el in root.getiterator() ])
    3112
    3113 -    def test_large_sourceline_XML(self):
    3114          XML = self.etree.XML
    3115          root = XML(_bytes(
    3116              '<?xml version="1.0"?>\n'
    3117              '<root>' + '\n' * 65536 +
    3118              '<p>' + '\n' * 65536 + '</p>\n' +
    3119              '<br/>\n'
    3120              '</root>'))
    3121
    3122          if self.etree.LIBXML_VERSION >= (2, 9):
    3123              expected = [2, 131074, 131076]
    3124          else:
    3125              expected = [2, 65535, 65535]
    3126
    3127          self.assertEqual(expected, [el.sourceline for el in root.iter()])
    3128
    3129 -    def test_sourceline_parse(self):
    3130          parse = self.etree.parse
    3131          tree = parse(fileInTestDir('include/test_xinclude.xml'))
    3132
    3133          self.assertEqual(
    3134              [1, 2, 3],
    3135              [ el.sourceline for el in tree.getiterator() ])
    3136
    3137 -    def test_sourceline_iterparse_end(self):
    3138          iterparse = self.etree.iterparse
    3139          lines = [ el.sourceline for (event, el) in
    3140                    iterparse(fileInTestDir('include/test_xinclude.xml')) ]
    3141
    3142          self.assertEqual(
    3143              [2, 3, 1],
    3144              lines)
    3145
    3146 -    def test_sourceline_iterparse_start(self):
    3147          iterparse = self.etree.iterparse
    3148          lines = [ el.sourceline for (event, el) in
    3149                    iterparse(fileInTestDir('include/test_xinclude.xml'),
    3150                              events=("start",)) ]
    3151
    3152          self.assertEqual(
    3153              [1, 2, 3],
    3154              lines)
    3155
    3156 -    def test_sourceline_element(self):
    3157          Element = self.etree.Element
    3158          SubElement = self.etree.SubElement
    3159          el = Element("test")
    3160          self.assertEqual(None, el.sourceline)
    3161
    3162          child = SubElement(el, "test")
    3163          self.assertEqual(None, el.sourceline)
    3164          self.assertEqual(None, child.sourceline)
    3165
    3166 -    def test_XML_base_url_docinfo(self):
    3167          etree = self.etree
    3168          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    3169          docinfo = root.getroottree().docinfo
    3170          self.assertEqual(docinfo.URL, "http://no/such/url")
    3171
    3172 -    def test_XML_set_base_url_docinfo(self):
    3173          etree = self.etree
    3174          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    3175          docinfo = root.getroottree().docinfo
    3176          self.assertEqual(docinfo.URL, "http://no/such/url")
    3177          docinfo.URL = "https://secret/url"
    3178          self.assertEqual(docinfo.URL, "https://secret/url")
    3179
    3180 -    def test_parse_stringio_base_url(self):
    3181          etree = self.etree
    3182          tree = etree.parse(BytesIO("<root/>"), base_url="http://no/such/url")
    3183          docinfo = tree.docinfo
    3184          self.assertEqual(docinfo.URL, "http://no/such/url")
    3185
    3186 -    def test_parse_base_url_docinfo(self):
    3187          etree = self.etree
    3188          tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
    3189                             base_url="http://no/such/url")
    3190          docinfo = tree.docinfo
    3191          self.assertEqual(docinfo.URL, "http://no/such/url")
    3192
    3193 -    def test_HTML_base_url_docinfo(self):
    3194          etree = self.etree
    3195          root = etree.HTML(_bytes("<html/>"), base_url="http://no/such/url")
    3196          docinfo = root.getroottree().docinfo
    3197          self.assertEqual(docinfo.URL, "http://no/such/url")
    3198
    3199 -    def test_docinfo_public(self):
    3200          etree = self.etree
    3201          xml_header = '<?xml version="1.0" encoding="ascii"?>'
    3202          pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
    3203          sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    3204          doctype_string = '<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id)
    3205
    3206          xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
    3207
    3208          tree = etree.parse(BytesIO(xml))
    3209          docinfo = tree.docinfo
    3210          self.assertEqual(docinfo.encoding,    "ascii")
    3211          self.assertEqual(docinfo.xml_version, "1.0")
    3212          self.assertEqual(docinfo.public_id,   pub_id)
    3213          self.assertEqual(docinfo.system_url,  sys_id)
    3214          self.assertEqual(docinfo.root_name,   'html')
    3215          self.assertEqual(docinfo.doctype, doctype_string)
    3216
    3217 -    def test_docinfo_system(self):
    3218          etree = self.etree
    3219          xml_header = '<?xml version="1.0" encoding="UTF-8"?>'
    3220          sys_id = "some.dtd"
    3221          doctype_string = '<!DOCTYPE html SYSTEM "%s">' % sys_id
    3222          xml = _bytes(xml_header + doctype_string + '<html><body></body></html>')
    3223
    3224          tree = etree.parse(BytesIO(xml))
    3225          docinfo = tree.docinfo
    3226          self.assertEqual(docinfo.encoding,    "UTF-8")
    3227          self.assertEqual(docinfo.xml_version, "1.0")
    3228          self.assertEqual(docinfo.public_id,   None)
    3229          self.assertEqual(docinfo.system_url,  sys_id)
    3230          self.assertEqual(docinfo.root_name,   'html')
    3231          self.assertEqual(docinfo.doctype, doctype_string)
    3232
    3233 -    def test_docinfo_empty(self):
    3234          etree = self.etree
    3235          xml = _bytes('<html><body></body></html>')
    3236          tree = etree.parse(BytesIO(xml))
    3237          docinfo = tree.docinfo
    3238          self.assertEqual(docinfo.encoding,    "UTF-8")
    3239          self.assertEqual(docinfo.xml_version, "1.0")
    3240          self.assertEqual(docinfo.public_id,   None)
    3241          self.assertEqual(docinfo.system_url,  None)
    3242          self.assertEqual(docinfo.root_name,   'html')
    3243          self.assertEqual(docinfo.doctype, '')
    3244
    3245 -    def test_docinfo_name_only(self):
    3246          etree = self.etree
    3247          xml = _bytes('<!DOCTYPE root><root></root>')
    3248          tree = etree.parse(BytesIO(xml))
    3249          docinfo = tree.docinfo
    3250          self.assertEqual(docinfo.encoding,    "UTF-8")
    3251          self.assertEqual(docinfo.xml_version, "1.0")
    3252          self.assertEqual(docinfo.public_id,   None)
    3253          self.assertEqual(docinfo.system_url,  None)
    3254          self.assertEqual(docinfo.root_name,   'root')
    3255          self.assertEqual(docinfo.doctype, '<!DOCTYPE root>')
    3256
    3257 -    def test_doctype_name_only_roundtrip(self):
    3258          etree = self.etree
    3259          xml = _bytes('<!DOCTYPE root>\n<root/>')
    3260          tree = etree.parse(BytesIO(xml))
    3261          self.assertEqual(xml, etree.tostring(tree))
    3262
    3263 -    def test_doctype_output_override(self):
    3264          etree = self.etree
    3265          pub_id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
    3266          sys_id = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    3267          doctype_string = _bytes('<!DOCTYPE html PUBLIC "%s" "%s">' % (pub_id, sys_id))
    3268
    3269          xml = _bytes('<!DOCTYPE root>\n<root/>')
    3270          tree = etree.parse(BytesIO(xml))
    3271          self.assertEqual(xml.replace(_bytes('<!DOCTYPE root>'), doctype_string),
    3272                            etree.tostring(tree, doctype=doctype_string))
    3273
    3274 -    def test_xml_base(self):
    3275          etree = self.etree
    3276          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    3277          self.assertEqual(root.base, "http://no/such/url")
    3278          self.assertEqual(
    3279              root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
    3280          root.base = "https://secret/url"
    3281          self.assertEqual(root.base, "https://secret/url")
    3282          self.assertEqual(
    3283              root.get('{http://www.w3.org/XML/1998/namespace}base'),
    3284              "https://secret/url")
    3285
    3286 -    def test_xml_base_attribute(self):
    3287          etree = self.etree
    3288          root = etree.XML(_bytes("<root/>"), base_url="http://no/such/url")
    3289          self.assertEqual(root.base, "http://no/such/url")
    3290          self.assertEqual(
    3291              root.get('{http://www.w3.org/XML/1998/namespace}base'), None)
    3292          root.set('{http://www.w3.org/XML/1998/namespace}base',
    3293                   "https://secret/url")
    3294          self.assertEqual(root.base, "https://secret/url")
    3295          self.assertEqual(
    3296              root.get('{http://www.w3.org/XML/1998/namespace}base'),
    3297              "https://secret/url")
    3298
    3299 -    def test_html_base(self):
    3300          etree = self.etree
    3301          root = etree.HTML(_bytes("<html><body></body></html>"),
    3302                            base_url="http://no/such/url")
    3303          self.assertEqual(root.base, "http://no/such/url")
    3304
    3305 -    def test_html_base_tag(self):
    3306          etree = self.etree
    3307          root = etree.HTML(_bytes('<html><head><base href="http://no/such/url"></head></html>'))
    3308          self.assertEqual(root.base, "http://no/such/url")
    3309
    3310 -    def test_parse_fileobject_unicode(self):
    3311          # parse from a file object that returns unicode strings
    3312          f = LargeFileLikeUnicode()
    3313          tree = self.etree.parse(f)
    3314          root = tree.getroot()
    3315          self.assertTrue(root.tag.endswith('root'))
    3316
    3317 -    def test_dtd_io(self):
    3318          # check that DTDs that go in also go back out
    3319          xml = _bytes('''\
    3320          <!DOCTYPE test SYSTEM "test.dtd" [
    3321            <!ENTITY entity "tasty">
    3322            <!ELEMENT test (a)>
    3323            <!ELEMENT a (#PCDATA)>
    3324          ]>
    3325          <test><a>test-test</a></test>\
    3326          ''')
    3327          tree = self.etree.parse(BytesIO(xml))
    3328          self.assertEqual(self.etree.tostring(tree).replace(_bytes(" "), _bytes("")),
    3329                           xml.replace(_bytes(" "), _bytes("")))
    3330
    3331 -    def test_byte_zero(self):
    3332          Element = self.etree.Element
    3333
    3334          a = Element('a')
    3335          self.assertRaises(ValueError, setattr, a, "text", 'ha\0ho')
    3336          self.assertRaises(ValueError, setattr, a, "tail", 'ha\0ho')
    3337
    3338          self.assertRaises(ValueError, Element, 'ha\0ho')
    3339
    3340 -    def test_unicode_byte_zero(self):
    3341          Element = self.etree.Element
    3342
    3343          a = Element('a')
    3344          self.assertRaises(ValueError, setattr, a, "text",
    3345                            _str('ha\0ho'))
    3346          self.assertRaises(ValueError, setattr, a, "tail",
    3347                            _str('ha\0ho'))
    3348
    3349          self.assertRaises(ValueError, Element,
    3350                            _str('ha\0ho'))
    3351
    3352 -    def test_byte_invalid(self):
    3353          Element = self.etree.Element
    3354
    3355          a = Element('a')
    3356          self.assertRaises(ValueError, setattr, a, "text", 'ha\x07ho')
    3357          self.assertRaises(ValueError, setattr, a, "text", 'ha\x02ho')
    3358
    3359          self.assertRaises(ValueError, setattr, a, "tail", 'ha\x07ho')
    3360          self.assertRaises(ValueError, setattr, a, "tail", 'ha\x02ho')
    3361
    3362          self.assertRaises(ValueError, Element, 'ha\x07ho')
    3363          self.assertRaises(ValueError, Element, 'ha\x02ho')
    3364
    3365 -    def test_unicode_byte_invalid(self):
    3366          Element = self.etree.Element
    3367
    3368          a = Element('a')
    3369          self.assertRaises(ValueError, setattr, a, "text",
    3370                            _str('ha\x07ho'))
    3371          self.assertRaises(ValueError, setattr, a, "text",
    3372                            _str('ha\x02ho'))
    3373
    3374          self.assertRaises(ValueError, setattr, a, "tail",
    3375                            _str('ha\x07ho'))
    3376          self.assertRaises(ValueError, setattr, a, "tail",
    3377                            _str('ha\x02ho'))
    3378
    3379          self.assertRaises(ValueError, Element,
    3380                            _str('ha\x07ho'))
    3381          self.assertRaises(ValueError, Element,
    3382                            _str('ha\x02ho'))
    3383
    3384 -    def test_unicode_byte_invalid_sequence(self):
    3385          Element = self.etree.Element
    3386
    3387          a = Element('a')
    3388          self.assertRaises(ValueError, setattr, a, "text",
    3389                            _str('ha\u1234\x07ho'))
    3390          self.assertRaises(ValueError, setattr, a, "text",
    3391                            _str('ha\u1234\x02ho'))
    3392
    3393          self.assertRaises(ValueError, setattr, a, "tail",
    3394                            _str('ha\u1234\x07ho'))
    3395          self.assertRaises(ValueError, setattr, a, "tail",
    3396                            _str('ha\u1234\x02ho'))
    3397
    3398          self.assertRaises(ValueError, Element,
    3399                            _str('ha\u1234\x07ho'))
    3400          self.assertRaises(ValueError, Element,
    3401                            _str('ha\u1234\x02ho'))
    3402
    3403 -    def test_encoding_tostring_utf16(self):
    3404          # ElementTree fails to serialize this
    3405          tostring = self.etree.tostring
    3406          Element = self.etree.Element
    3407          SubElement = self.etree.SubElement
    3408
    3409          a = Element('a')
    3410          b = SubElement(a, 'b')
    3411          c = SubElement(a, 'c')
    3412
    3413          result = tostring(a, encoding='UTF-16')
    3414          self.assertEqual(_bytes('<a><b></b><c></c></a>'),
    3415                            canonicalize(result))
    3416
    3417 -    def test_tostring_none(self):
    3418          # ElementTree raises an AssertionError here
    3419          tostring = self.etree.tostring
    3420          self.assertRaises(TypeError, self.etree.tostring, None)
    3421
    3422 -    def test_tostring_pretty(self):
    3423          tostring = self.etree.tostring
    3424          Element = self.etree.Element
    3425          SubElement = self.etree.SubElement
    3426
    3427          a = Element('a')
    3428          b = SubElement(a, 'b')
    3429          c = SubElement(a, 'c')
    3430
    3431          result = tostring(a)
    3432          self.assertEqual(result, _bytes("<a><b/><c/></a>"))
    3433
    3434          result = tostring(a, pretty_print=False)
    3435          self.assertEqual(result, _bytes("<a><b/><c/></a>"))
    3436
    3437          result = tostring(a, pretty_print=True)
    3438          self.assertEqual(result, _bytes("<a>\n  <b/>\n  <c/>\n</a>\n"))
    3439
    3440 -    def test_tostring_with_tail(self):
    3441          tostring = self.etree.tostring
    3442          Element = self.etree.Element
    3443          SubElement = self.etree.SubElement
    3444
    3445          a = Element('a')
    3446          a.tail = "aTAIL"
    3447          b = SubElement(a, 'b')
    3448          b.tail = "bTAIL"
    3449          c = SubElement(a, 'c')
    3450
    3451          result = tostring(a)
    3452          self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
    3453
    3454          result = tostring(a, with_tail=False)
    3455          self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>"))
    3456
    3457          result = tostring(a, with_tail=True)
    3458          self.assertEqual(result, _bytes("<a><b/>bTAIL<c/></a>aTAIL"))
    3459
    3460 -    def test_tostring_method_html_with_tail(self):
    3461          tostring = self.etree.tostring
    3462          html = self.etree.fromstring(
    3463              '<html><body>'
    3464              '<div><p>Some text<i>\r\n</i></p></div>\r\n'
    3465              '</body></html>',
    3466              parser=self.etree.HTMLParser())
    3467          self.assertEqual(html.tag, 'html')
    3468          div = html.find('.//div')
    3469          self.assertEqual(div.tail, '\r\n')
    3470          result = tostring(div, method='html')
    3471          self.assertEqual(
    3472              result,
    3473              _bytes("<div><p>Some text<i>\r\n</i></p></div>\r\n"))
    3474          result = tostring(div, method='html', with_tail=True)
    3475          self.assertEqual(
    3476              result,
    3477              _bytes("<div><p>Some text<i>\r\n</i></p></div>\r\n"))
    3478          result = tostring(div, method='html', with_tail=False)
    3479          self.assertEqual(
    3480              result,
    3481              _bytes("<div><p>Some text<i>\r\n</i></p></div>"))
    3482
    3483 -    def test_standalone(self):
    3484          tostring = self.etree.tostring
    3485          XML = self.etree.XML
    3486          ElementTree = self.etree.ElementTree
    3487          Element = self.etree.Element
    3488
    3489          tree = Element("root").getroottree()
    3490          self.assertEqual(None, tree.docinfo.standalone)
    3491
    3492          tree = XML(_bytes("<root/>")).getroottree()
    3493          self.assertEqual(None, tree.docinfo.standalone)
    3494
    3495          tree = XML(_bytes(
    3496              "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"
    3497              )).getroottree()
    3498          self.assertEqual(True, tree.docinfo.standalone)
    3499
    3500          tree = XML(_bytes(
    3501              "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>"
    3502              )).getroottree()
    3503          self.assertEqual(False, tree.docinfo.standalone)
    3504
    3505 -    def test_tostring_standalone(self):
    3506          tostring = self.etree.tostring
    3507          XML = self.etree.XML
    3508          ElementTree = self.etree.ElementTree
    3509
    3510          root = XML(_bytes("<root/>"))
    3511
    3512          tree = ElementTree(root)
    3513          self.assertEqual(None, tree.docinfo.standalone)
    3514
    3515          result = tostring(root, xml_declaration=True, encoding="ASCII")
    3516          self.assertEqual(result, _bytes(
    3517              "<?xml version='1.0' encoding='ASCII'?>\n<root/>"))
    3518
    3519          result = tostring(root, xml_declaration=True, encoding="ASCII",
    3520                            standalone=True)
    3521          self.assertEqual(result, _bytes(
    3522              "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"))
    3523
    3524          tree = ElementTree(XML(result))
    3525          self.assertEqual(True, tree.docinfo.standalone)
    3526
    3527          result = tostring(root, xml_declaration=True, encoding="ASCII",
    3528                            standalone=False)
    3529          self.assertEqual(result, _bytes(
    3530              "<?xml version='1.0' encoding='ASCII' standalone='no'?>\n<root/>"))
    3531
    3532          tree = ElementTree(XML(result))
    3533          self.assertEqual(False, tree.docinfo.standalone)
    3534
    3535 -    def test_tostring_standalone_in_out(self):
    3536          tostring = self.etree.tostring
    3537          XML = self.etree.XML
    3538          ElementTree = self.etree.ElementTree
    3539
    3540          root = XML(_bytes(
    3541              "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>\n<root/>"))
    3542
    3543          tree = ElementTree(root)
    3544          self.assertEqual(True, tree.docinfo.standalone)
    3545
    3546          result = tostring(root, xml_declaration=True, encoding="ASCII")
    3547          self.assertEqual(result, _bytes(
    3548              "<?xml version='1.0' encoding='ASCII'?>\n<root/>"))
    3549
    3550          result = tostring(root, xml_declaration=True, encoding="ASCII",
    3551                            standalone=True)
    3552          self.assertEqual(result, _bytes(
    3553              "<?xml version='1.0' encoding='ASCII' standalone='yes'?>\n<root/>"))
    3554
    3555 -    def test_tostring_method_text_encoding(self):
    3556          tostring = self.etree.tostring
    3557          Element = self.etree.Element
    3558          SubElement = self.etree.SubElement
    3559
    3560          a = Element('a')
    3561          a.text = "A"
    3562          a.tail = "tail"
    3563          b = SubElement(a, 'b')
    3564          b.text = "B"
    3565          b.tail = _str("Søk på nettet")
    3566          c = SubElement(a, 'c')
    3567          c.text = "C"
    3568
    3569          result = tostring(a, method="text", encoding="UTF-16")
    3570
    3571          self.assertEqual(_str('ABSøk på nettetCtail').encode("UTF-16"),
    3572                            result)
    3573
    3574 -    def test_tostring_method_text_unicode(self):
    3575          tostring = self.etree.tostring
    3576          Element = self.etree.Element
    3577          SubElement = self.etree.SubElement
    3578
    3579          a = Element('a')
    3580          a.text = _str('Søk på nettetA')
    3581          a.tail = "tail"
    3582          b = SubElement(a, 'b')
    3583          b.text = "B"
    3584          b.tail = _str('Søk på nettetB')
    3585          c = SubElement(a, 'c')
    3586          c.text = "C"
    3587
    3588          self.assertRaises(UnicodeEncodeError,
    3589                            tostring, a, method="text")
    3590
    3591          self.assertEqual(
    3592              _str('Søk på nettetABSøk på nettetBCtail').encode('utf-8'),
    3593              tostring(a, encoding="UTF-8", method="text"))
    3594
    3595 -    def test_tounicode(self):
    3596          tounicode = self.etree.tounicode
    3597          Element = self.etree.Element
    3598          SubElement = self.etree.SubElement
    3599
    3600          a = Element('a')
    3601          b = SubElement(a, 'b')
    3602          c = SubElement(a, 'c')
    3603
    3604          self.assertTrue(isinstance(tounicode(a), _unicode))
    3605          self.assertEqual(_bytes('<a><b></b><c></c></a>'),
    3606                            canonicalize(tounicode(a)))
    3607
    3608 -    def test_tounicode_element(self):
    3609          tounicode = self.etree.tounicode
    3610          Element = self.etree.Element
    3611          SubElement = self.etree.SubElement
    3612
    3613          a = Element('a')
    3614          b = SubElement(a, 'b')
    3615          c = SubElement(a, 'c')
    3616          d = SubElement(c, 'd')
    3617          self.assertTrue(isinstance(tounicode(b), _unicode))
    3618          self.assertTrue(isinstance(tounicode(c), _unicode))
    3619          self.assertEqual(_bytes('<b></b>'),
    3620                            canonicalize(tounicode(b)))
    3621          self.assertEqual(_bytes('<c><d></d></c>'),
    3622                            canonicalize(tounicode(c)))
    3623
    3624 -    def test_tounicode_none(self):
    3625          tounicode = self.etree.tounicode
    3626          self.assertRaises(TypeError, self.etree.tounicode, None)
    3627
    3628 -    def test_tounicode_element_tail(self):
    3629          tounicode = self.etree.tounicode
    3630          Element = self.etree.Element
    3631          SubElement = self.etree.SubElement
    3632
    3633          a = Element('a')
    3634          b = SubElement(a, 'b')
    3635          c = SubElement(a, 'c')
    3636          d = SubElement(c, 'd')
    3637          b.tail = 'Foo'
    3638
    3639          self.assertTrue(isinstance(tounicode(b), _unicode))
    3640          self.assertTrue(tounicode(b) == '<b/>Foo' or
    3641                       tounicode(b) == '<b />Foo')
    3642
    3643 -    def test_tounicode_pretty(self):
    3644          tounicode = self.etree.tounicode
    3645          Element = self.etree.Element
    3646          SubElement = self.etree.SubElement
    3647
    3648          a = Element('a')
    3649          b = SubElement(a, 'b')
    3650          c = SubElement(a, 'c')
    3651
    3652          result = tounicode(a)
    3653          self.assertEqual(result, "<a><b/><c/></a>")
    3654
    3655          result = tounicode(a, pretty_print=False)
    3656          self.assertEqual(result, "<a><b/><c/></a>")
    3657
    3658          result = tounicode(a, pretty_print=True)
    3659          self.assertEqual(result, "<a>\n  <b/>\n  <c/>\n</a>\n")
    3660
    3661 -    def test_tostring_unicode(self):
    3662          tostring = self.etree.tostring
    3663          Element = self.etree.Element
    3664          SubElement = self.etree.SubElement
    3665
    3666          a = Element('a')
    3667          b = SubElement(a, 'b')
    3668          c = SubElement(a, 'c')
    3669
    3670          self.assertTrue(isinstance(tostring(a, encoding=_unicode), _unicode))
    3671          self.assertEqual(_bytes('<a><b></b><c></c></a>'),
    3672                            canonicalize(tostring(a, encoding=_unicode)))
    3673
    3674 -    def test_tostring_unicode_element(self):
    3675          tostring = self.etree.tostring
    3676          Element = self.etree.Element
    3677          SubElement = self.etree.SubElement
    3678
    3679          a = Element('a')
    3680          b = SubElement(a, 'b')
    3681          c = SubElement(a, 'c')
    3682          d = SubElement(c, 'd')
    3683          self.assertTrue(isinstance(tostring(b, encoding=_unicode), _unicode))
    3684          self.assertTrue(isinstance(tostring(c, encoding=_unicode), _unicode))
    3685          self.assertEqual(_bytes('<b></b>'),
    3686                            canonicalize(tostring(b, encoding=_unicode)))
    3687          self.assertEqual(_bytes('<c><d></d></c>'),
    3688                            canonicalize(tostring(c, encoding=_unicode)))
    3689
    3690 -    def test_tostring_unicode_none(self):
    3691          tostring = self.etree.tostring
    3692          self.assertRaises(TypeError, self.etree.tostring,
    3693                            None, encoding=_unicode)
    3694
    3695 -    def test_tostring_unicode_element_tail(self):
    3696          tostring = self.etree.tostring
    3697          Element = self.etree.Element
    3698          SubElement = self.etree.SubElement
    3699
    3700          a = Element('a')
    3701          b = SubElement(a, 'b')
    3702          c = SubElement(a, 'c')
    3703          d = SubElement(c, 'd')
    3704          b.tail = 'Foo'
    3705
    3706          self.assertTrue(isinstance(tostring(b, encoding=_unicode), _unicode))
    3707          self.assertTrue(tostring(b, encoding=_unicode) == '<b/>Foo' or
    3708                       tostring(b, encoding=_unicode) == '<b />Foo')
    3709
    3710 -    def test_tostring_unicode_pretty(self):
    3711          tostring = self.etree.tostring
    3712          Element = self.etree.Element
    3713          SubElement = self.etree.SubElement
    3714
    3715          a = Element('a')
    3716          b = SubElement(a, 'b')
    3717          c = SubElement(a, 'c')
    3718
    3719          result = tostring(a, encoding=_unicode)
    3720          self.assertEqual(result, "<a><b/><c/></a>")
    3721
    3722          result = tostring(a, encoding=_unicode, pretty_print=False)
    3723          self.assertEqual(result, "<a><b/><c/></a>")
    3724
    3725          result = tostring(a, encoding=_unicode, pretty_print=True)
    3726          self.assertEqual(result, "<a>\n  <b/>\n  <c/>\n</a>\n")
    3727
    3728 -    def test_pypy_proxy_collect(self):
    3729          root = etree.Element('parent')
    3730          etree.SubElement(root, 'child')
    3731
    3732          self.assertEqual(len(root), 1)
    3733          self.assertEqual(root[0].tag, 'child')
    3734
    3735          # in PyPy, GC used to kill the Python proxy instance without cleanup
    3736          gc.collect()
    3737          self.assertEqual(len(root), 1)
    3738          self.assertEqual(root[0].tag, 'child')
    3739
    3740 -    def test_element_refcycle(self):
    3741          class SubEl(etree.ElementBase):
    3742              pass
    3743
    3744          el1 = SubEl()
    3745          el2 = SubEl()
    3746          self.assertEqual('SubEl', el1.tag)
    3747          self.assertEqual('SubEl', el2.tag)
    3748          el1.other = el2
    3749          el2.other = el1
    3750
    3751          del el1, el2
    3752          gc.collect()
    3753          # not really testing anything here, but it shouldn't crash
    3754
    3755 -    def test_proxy_collect_siblings(self):
    3756          root = etree.Element('parent')
    3757          c1 = etree.SubElement(root, 'child1')
    3758          c2 = etree.SubElement(root, 'child2')
    3759
    3760          root.remove(c1)
    3761          root.remove(c2)
    3762          c1.addnext(c2)
    3763          del c1
    3764          # trigger deallocation attempt of c1
    3765          c2.getprevious()
    3766          # make sure it wasn't deallocated
    3767          self.assertEqual('child1', c2.getprevious().tag)
    3768
    3769 -    def test_proxy_collect_siblings_text(self):
    3770          root = etree.Element('parent')
    3771          c1 = etree.SubElement(root, 'child1')
    3772          c2 = etree.SubElement(root, 'child2')
    3773
    3774          root.remove(c1)
    3775          root.remove(c2)
    3776          c1.addnext(c2)
    3777          c1.tail = 'abc'
    3778          c2.tail = 'xyz'
    3779          del c1
    3780          # trigger deallocation attempt of c1
    3781          c2.getprevious()
    3782          # make sure it wasn't deallocated
    3783          self.assertEqual('child1', c2.getprevious().tag)
    3784          self.assertEqual('abc', c2.getprevious().tail)
    3785
    3786      # helper methods
    3787
    3788 -    def _writeElement(self, element, encoding='us-ascii', compression=0):
    3789          """Write out element for comparison.
    3790          """
    3791          ElementTree = self.etree.ElementTree
    3792          f = BytesIO()
    3793          tree = ElementTree(element=element)
    3794          tree.write(f, encoding=encoding, compression=compression)
    3795          data = f.getvalue()
    3796          if compression:
    3797              data = zlib.decompress(data)
    3798          return canonicalize(data)
    3799
    3800
    3801 -class _XIncludeTestCase(HelperTestCase):
    3802 -    def test_xinclude_text(self):
    3803          filename = fileInTestDir('test_broken.xml')
    3804          root = etree.XML(_bytes('''\
    3805          <doc xmlns:xi="http://www.w3.org/2001/XInclude">
    3806            <xi:include href="%s" parse="text"/>
    3807          </doc>
    3808          ''' % path2url(filename)))
    3809          old_text = root.text
    3810          content = read_file(filename)
    3811          old_tail = root[0].tail
    3812
    3813          self.include( etree.ElementTree(root) )
    3814          self.assertEqual(old_text + content + old_tail,
    3815                            root.text)
    3816
    3817 -    def test_xinclude(self):
    3818          tree = etree.parse(fileInTestDir('include/test_xinclude.xml'))
    3819          self.assertNotEqual(
    3820              'a',
    3821              tree.getroot()[1].tag)
    3822          # process xincludes
    3823          self.include( tree )
    3824          # check whether we find it replaced with included data
    3825          self.assertEqual(
    3826              'a',
    3827              tree.getroot()[1].tag)
    3828
    3829 -    def test_xinclude_resolver(self):
    3830          class res(etree.Resolver):
    3831              include_text = read_file(fileInTestDir('test.xml'))
    3832              called = {}
    3833              def resolve(self, url, id, context):
    3834                  if url.endswith(".dtd"):
    3835                      self.called["dtd"] = True
    3836                      return self.resolve_filename(
    3837                          fileInTestDir('test.dtd'), context)
    3838                  elif url.endswith("test_xinclude.xml"):
    3839                      self.called["input"] = True
    3840                      return None # delegate to default resolver
    3841                  else:
    3842                      self.called["include"] = True
    3843                      return self.resolve_string(self.include_text, context)
    3844
    3845          res_instance = res()
    3846          parser = etree.XMLParser(load_dtd = True)
    3847          parser.resolvers.add(res_instance)
    3848
    3849          tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
    3850                             parser = parser)
    3851
    3852          self.include(tree)
    3853
    3854          called = list(res_instance.called.items())
    3855          called.sort()
    3856          self.assertEqual(
    3857              [("dtd", True), ("include", True), ("input", True)],
    3858              called)
    3859
    3860 -    def test_xinclude_resolver_recursive(self):
    3861          data = textwrap.dedent('''
    3862          <doc xmlns:xi="http://www.w3.org/2001/XInclude">
    3863          <foo/>
    3864          <xi:include href="./test.xml" />
    3865          </doc>
    3866          ''')
    3867
    3868          class Resolver(etree.Resolver):
    3869              called = {}
    3870
    3871              def resolve(self, url, id, context):
    3872                  if url.endswith("test_xinclude.xml"):
    3873                      assert not self.called.get("input")
    3874                      self.called["input"] = True
    3875                      return None  # delegate to default resolver
    3876                  elif url.endswith('/test5.xml'):
    3877                      assert not self.called.get("DONE")
    3878                      self.called["DONE"] = True
    3879                      return self.resolve_string('<DONE/>', context)
    3880                  else:
    3881                      _, filename = url.rsplit('/', 1)
    3882                      assert not self.called.get(filename)
    3883                      self.called[filename] = True
    3884                      next_data = data.replace(
    3885                          'test.xml', 'test%d.xml' % len(self.called))
    3886                      return self.resolve_string(next_data, context)
    3887
    3888          res_instance = Resolver()
    3889          parser = etree.XMLParser(load_dtd=True)
    3890          parser.resolvers.add(res_instance)
    3891
    3892          tree = etree.parse(fileInTestDir('include/test_xinclude.xml'),
    3893                             parser=parser)
    3894
    3895          self.include(tree)
    3896
    3897          called = list(res_instance.called.items())
    3898          called.sort()
    3899          self.assertEqual(
    3900              [("DONE", True), ("input", True), ("test.xml", True),
    3901               ("test2.xml", True), ("test3.xml", True), ("test4.xml", True)],
    3902              called)
    3903
    3904
    3905 -class ETreeXIncludeTestCase(_XIncludeTestCase):
    3906 -    def include(self, tree):
    3907          tree.xinclude()
    3908
    3909
    3910 -class ElementIncludeTestCase(_XIncludeTestCase):
    3911      from lxml import ElementInclude
    3912 -    def include(self, tree):
    3913          self.ElementInclude.include(tree.getroot())
    3914
    3915
    3916 -class ETreeC14NTestCase(HelperTestCase):
    3917 -    def test_c14n(self):
    3918          tree = self.parse(_bytes('<a><b/></a>'))
    3919          f = BytesIO()
    3920          tree.write_c14n(f)
    3921          s = f.getvalue()
    3922          self.assertEqual(_bytes('<a><b></b></a>'),
    3923                            s)
    3924
    3925 -    def test_c14n_gzip(self):
    3926          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    3927          f = BytesIO()
    3928          tree.write_c14n(f, compression=9)
    3929          gzfile = gzip.GzipFile(fileobj=BytesIO(f.getvalue()))
    3930          try:
    3931              s = gzfile.read()
    3932          finally:
    3933              gzfile.close()
    3934          self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'),
    3935                            s)
    3936
    3937 -    def test_c14n_file(self):
    3938          tree = self.parse(_bytes('<a><b/></a>'))
    3939          handle, filename = tempfile.mkstemp()
    3940          try:
    3941              tree.write_c14n(filename)
    3942              data = read_file(filename, 'rb')
    3943          finally:
    3944              os.close(handle)
    3945              os.remove(filename)
    3946          self.assertEqual(_bytes('<a><b></b></a>'),
    3947                            data)
    3948
    3949 -    def test_c14n_file_gzip(self):
    3950          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    3951          handle, filename = tempfile.mkstemp()
    3952          try:
    3953              tree.write_c14n(filename, compression=9)
    3954              f = gzip.open(filename, 'rb')
    3955              try:
    3956                  data = f.read()
    3957              finally:
    3958                  f.close()
    3959          finally:
    3960              os.close(handle)
    3961              os.remove(filename)
    3962          self.assertEqual(_bytes('<a>'+'<b></b>'*200+'</a>'),
    3963                            data)
    3964
    3965 -    def test_c14n_with_comments(self):
    3966          tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
    3967          f = BytesIO()
    3968          tree.write_c14n(f)
    3969          s = f.getvalue()
    3970          self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
    3971                            s)
    3972          f = BytesIO()
    3973          tree.write_c14n(f, with_comments=True)
    3974          s = f.getvalue()
    3975          self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
    3976                            s)
    3977          f = BytesIO()
    3978          tree.write_c14n(f, with_comments=False)
    3979          s = f.getvalue()
    3980          self.assertEqual(_bytes('<a><b></b></a>'),
    3981                            s)
    3982
    3983 -    def test_c14n_tostring_with_comments(self):
    3984          tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
    3985          s = etree.tostring(tree, method='c14n')
    3986          self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
    3987                            s)
    3988          s = etree.tostring(tree, method='c14n', with_comments=True)
    3989          self.assertEqual(_bytes('<!--hi-->\n<a><!--ho--><b></b></a>\n<!--hu-->'),
    3990                            s)
    3991          s = etree.tostring(tree, method='c14n', with_comments=False)
    3992          self.assertEqual(_bytes('<a><b></b></a>'),
    3993                            s)
    3994
    3995 -    def test_c14n_element_tostring_with_comments(self):
    3996          tree = self.parse(_bytes('<!--hi--><a><!--ho--><b/></a><!--hu-->'))
    3997          s = etree.tostring(tree.getroot(), method='c14n')
    3998          self.assertEqual(_bytes('<a><!--ho--><b></b></a>'),
    3999                            s)
    4000          s = etree.tostring(tree.getroot(), method='c14n', with_comments=True)
    4001          self.assertEqual(_bytes('<a><!--ho--><b></b></a>'),
    4002                            s)
    4003          s = etree.tostring(tree.getroot(), method='c14n', with_comments=False)
    4004          self.assertEqual(_bytes('<a><b></b></a>'),
    4005                            s)
    4006
    4007 -    def test_c14n_exclusive(self):
    4008          tree = self.parse(_bytes(
    4009                  '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
    4010          f = BytesIO()
    4011          tree.write_c14n(f)
    4012          s = f.getvalue()
    4013          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    4014                            s)
    4015          f = BytesIO()
    4016          tree.write_c14n(f, exclusive=False)
    4017          s = f.getvalue()
    4018          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    4019                            s)
    4020          f = BytesIO()
    4021          tree.write_c14n(f, exclusive=True)
    4022          s = f.getvalue()
    4023          self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
    4024                            s)
    4025
    4026          f = BytesIO()
    4027          tree.write_c14n(f, exclusive=True, inclusive_ns_prefixes=['z'])
    4028          s = f.getvalue()
    4029          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:z="http://cde"><z:b></z:b></a>'),
    4030                            s)
    4031
    4032 -    def test_c14n_tostring_exclusive(self):
    4033          tree = self.parse(_bytes(
    4034                  '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
    4035          s = etree.tostring(tree, method='c14n')
    4036          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    4037                            s)
    4038          s = etree.tostring(tree, method='c14n', exclusive=False)
    4039          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    4040                            s)
    4041          s = etree.tostring(tree, method='c14n', exclusive=True)
    4042          self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
    4043                            s)
    4044
    4045          s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['y'])
    4046          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd"><z:b xmlns:z="http://cde"></z:b></a>'),
    4047                            s)
    4048
    4049 -    def test_c14n_element_tostring_exclusive(self):
    4050          tree = self.parse(_bytes(
    4051                  '<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
    4052          s = etree.tostring(tree.getroot(), method='c14n')
    4053          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    4054                            s)
    4055          s = etree.tostring(tree.getroot(), method='c14n', exclusive=False)
    4056          self.assertEqual(_bytes('<a xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    4057                            s)
    4058          s = etree.tostring(tree.getroot(), method='c14n', exclusive=True)
    4059          self.assertEqual(_bytes('<a xmlns="http://abc"><z:b xmlns:z="http://cde"></z:b></a>'),
    4060                            s)
    4061
    4062          s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=False)
    4063          self.assertEqual(_bytes('<z:b xmlns="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'),
    4064                            s)
    4065          s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True)
    4066          self.assertEqual(_bytes('<z:b xmlns:z="http://cde"></z:b>'),
    4067                            s)
    4068
    4069          s = etree.tostring(tree.getroot()[0], method='c14n', exclusive=True, inclusive_ns_prefixes=['y'])
    4070          self.assertEqual(_bytes('<z:b xmlns:y="http://bcd" xmlns:z="http://cde"></z:b>'),
    4071                            s)
    4072
    4073 -    def test_c14n_tostring_inclusive_ns_prefixes(self):
    4074          """ Regression test to fix memory allocation issues (use 3+ inclusive NS spaces)"""
    4075          tree = self.parse(_bytes(
    4076                  '<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b/></a>'))
    4077
    4078          s = etree.tostring(tree, method='c14n', exclusive=True, inclusive_ns_prefixes=['x', 'y', 'z'])
    4079          self.assertEqual(_bytes('<a xmlns:x="http://abc" xmlns:y="http://bcd" xmlns:z="http://cde"><z:b></z:b></a>'),
    4080                            s)
    4081
    4082
    4083 -class ETreeWriteTestCase(HelperTestCase):
    4084 -    def test_write(self):
    4085          tree = self.parse(_bytes('<a><b/></a>'))
    4086          f = BytesIO()
    4087          tree.write(f)
    4088          s = f.getvalue()
    4089          self.assertEqual(_bytes('<a><b/></a>'),
    4090                            s)
    4091
    4092 -    def test_write_gzip(self):
    4093          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    4094          f = BytesIO()
    4095          tree.write(f, compression=9)
    4096          gzfile = gzip.GzipFile(fileobj=BytesIO(f.getvalue()))
    4097          try:
    4098              s = gzfile.read()
    4099          finally:
    4100              gzfile.close()
    4101          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    4102                            s)
    4103
    4104 -    def test_write_gzip_level(self):
    4105          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    4106          f = BytesIO()
    4107          tree.write(f, compression=0)
    4108          s0 = f.getvalue()
    4109
    4110          f = BytesIO()
    4111          tree.write(f)
    4112          self.assertEqual(f.getvalue(), s0)
    4113
    4114          f = BytesIO()
    4115          tree.write(f, compression=1)
    4116          s = f.getvalue()
    4117          self.assertTrue(len(s) <= len(s0))
    4118          gzfile = gzip.GzipFile(fileobj=BytesIO(s))
    4119          try:
    4120              s1 = gzfile.read()
    4121          finally:
    4122              gzfile.close()
    4123
    4124          f = BytesIO()
    4125          tree.write(f, compression=9)
    4126          s = f.getvalue()
    4127          self.assertTrue(len(s) <= len(s0))
    4128          gzfile = gzip.GzipFile(fileobj=BytesIO(s))
    4129          try:
    4130              s9 = gzfile.read()
    4131          finally:
    4132              gzfile.close()
    4133
    4134          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    4135                            s0)
    4136          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    4137                            s1)
    4138          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    4139                            s9)
    4140
    4141 -    def test_write_file(self):
    4142          tree = self.parse(_bytes('<a><b/></a>'))
    4143          handle, filename = tempfile.mkstemp()
    4144          try:
    4145              tree.write(filename)
    4146              data = read_file(filename, 'rb')
    4147          finally:
    4148              os.close(handle)
    4149              os.remove(filename)
    4150          self.assertEqual(_bytes('<a><b/></a>'),
    4151                            data)
    4152
    4153 -    def test_write_file_gzip(self):
    4154          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    4155          handle, filename = tempfile.mkstemp()
    4156          try:
    4157              tree.write(filename, compression=9)
    4158              f = gzip.open(filename, 'rb')
    4159              try:
    4160                  data = f.read()
    4161              finally:
    4162                  f.close()
    4163          finally:
    4164              os.close(handle)
    4165              os.remove(filename)
    4166          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    4167                            data)
    4168
    4169 -    def test_write_file_gzip_parse(self):
    4170          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    4171          handle, filename = tempfile.mkstemp()
    4172          try:
    4173              tree.write(filename, compression=9)
    4174              data = etree.tostring(etree.parse(filename))
    4175          finally:
    4176              os.close(handle)
    4177              os.remove(filename)
    4178          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    4179                            data)
    4180
    4181 -    def test_write_file_gzipfile_parse(self):
    4182          tree = self.parse(_bytes('<a>'+'<b/>'*200+'</a>'))
    4183          handle, filename = tempfile.mkstemp()
    4184          try:
    4185              tree.write(filename, compression=9)
    4186              data = etree.tostring(etree.parse(
    4187                  gzip.GzipFile(filename)))
    4188          finally:
    4189              os.close(handle)
    4190              os.remove(filename)
    4191          self.assertEqual(_bytes('<a>'+'<b/>'*200+'</a>'),
    4192                            data)
    4193
    4194 -class ETreeErrorLogTest(HelperTestCase):
    4195      etree = etree
    4196
    4197 -    def test_parse_error_logging(self):
    4198          parse = self.etree.parse
    4199          f = BytesIO('<a><b></c></b></a>')
    4200          self.etree.clear_error_log()
    4201          try:
    4202              parse(f)
    4203              logs = None
    4204          except SyntaxError:
    4205              e = sys.exc_info()[1]
    4206              logs = e.error_log
    4207          f.close()
    4208          self.assertTrue([ log for log in logs
    4209                         if 'mismatch' in log.message ])
    4210          self.assertTrue([ log for log in logs
    4211                         if 'PARSER'   in log.domain_name])
    4212          self.assertTrue([ log for log in logs
    4213                         if 'ERR_TAG_NAME_MISMATCH' in log.type_name ])
    4214          self.assertTrue([ log for log in logs
    4215                         if 1 == log.line ])
    4216          self.assertTrue([ log for log in logs
    4217                         if 15 == log.column ])
    4218
    4219 -    def _test_python_error_logging(self):
    4220          """This can't really be tested as long as there isn't a way to
    4221          reset the logging setup ...
    4222          """
    4223          parse = self.etree.parse
    4224
    4225          messages = []
    4226          class Logger(self.etree.PyErrorLog):
    4227              def log(self, entry, message, *args):
    4228                  messages.append(message)
    4229
    4230          self.etree.use_global_python_log(Logger())
    4231          f = BytesIO('<a><b></c></b></a>')
    4232          try:
    4233              parse(f)
    4234          except SyntaxError:
    4235              pass
    4236          f.close()
    4237
    4238          self.assertTrue([ message for message in messages
    4239                         if 'mismatch' in message ])
    4240          self.assertTrue([ message for message in messages
    4241                         if ':PARSER:'   in message])
    4242          self.assertTrue([ message for message in messages
    4243                         if ':ERR_TAG_NAME_MISMATCH:' in message ])
    4244          self.assertTrue([ message for message in messages
    4245                         if ':1:15:' in message ])
    4246
    4247
    4248 -class XMLPullParserTest(unittest.TestCase):
    4249      etree = etree
    4250
    4251 -    def assert_event_tags(self, events, expected):
    4252          self.assertEqual([(action, elem.tag) for action, elem in events],
    4253                           expected)
    4254
    4255 -    def test_pull_from_simple_target(self):
    4256          class Target(object):
    4257              def start(self, tag, attrib):
    4258                  return 'start(%s)' % tag
    4259              def end(self, tag):
    4260                  return 'end(%s)' % tag
    4261              def close(self):
    4262                  return 'close()'
    4263
    4264          parser = self.etree.XMLPullParser(target=Target())
    4265          events = parser.read_events()
    4266
    4267          parser.feed('<root><element>')
    4268          self.assertFalse(list(events))
    4269          self.assertFalse(list(events))
    4270          parser.feed('</element><child>')
    4271          self.assertEqual([('end', 'end(element)')], list(events))
    4272          parser.feed('</child>')
    4273          self.assertEqual([('end', 'end(child)')], list(events))
    4274          parser.feed('</root>')
    4275          self.assertEqual([('end', 'end(root)')], list(events))
    4276          self.assertFalse(list(events))
    4277          self.assertEqual('close()', parser.close())
    4278
    4279 -    def test_pull_from_simple_target_start_end(self):
    4280          class Target(object):
    4281              def start(self, tag, attrib):
    4282                  return 'start(%s)' % tag
    4283              def end(self, tag):
    4284                  return 'end(%s)' % tag
    4285              def close(self):
    4286                  return 'close()'
    4287
    4288          parser = self.etree.XMLPullParser(
    4289              ['start', 'end'], target=Target())
    4290          events = parser.read_events()
    4291
    4292          parser.feed('<root><element>')
    4293          self.assertEqual(
    4294              [('start', 'start(root)'), ('start', 'start(element)')],
    4295              list(events))
    4296          self.assertFalse(list(events))
    4297          parser.feed('</element><child>')
    4298          self.assertEqual(
    4299              [('end', 'end(element)'), ('start', 'start(child)')],
    4300              list(events))
    4301          parser.feed('</child>')
    4302          self.assertEqual(
    4303              [('end', 'end(child)')],
    4304              list(events))
    4305          parser.feed('</root>')
    4306          self.assertEqual(
    4307              [('end', 'end(root)')],
    4308              list(events))
    4309          self.assertFalse(list(events))
    4310          self.assertEqual('close()', parser.close())
    4311
    4312 -    def test_pull_from_tree_builder(self):
    4313          parser = self.etree.XMLPullParser(
    4314              ['start', 'end'], target=etree.TreeBuilder())
    4315          events = parser.read_events()
    4316
    4317          parser.feed('<root><element>')
    4318          self.assert_event_tags(
    4319              events, [('start', 'root'), ('start', 'element')])
    4320          self.assertFalse(list(events))
    4321          parser.feed('</element><child>')
    4322          self.assert_event_tags(
    4323              events, [('end', 'element'), ('start', 'child')])
    4324          parser.feed('</child>')
    4325          self.assert_event_tags(
    4326              events, [('end', 'child')])
    4327          parser.feed('</root>')
    4328          self.assert_event_tags(
    4329              events, [('end', 'root')])
    4330          self.assertFalse(list(events))
    4331          root = parser.close()
    4332          self.assertEqual('root', root.tag)
    4333
    4334 -    def test_pull_from_tree_builder_subclass(self):
    4335          class Target(etree.TreeBuilder):
    4336              def end(self, tag):
    4337                  el = super(Target, self).end(tag)
    4338                  el.tag += '-huhu'
    4339                  return el
    4340
    4341          parser = self.etree.XMLPullParser(
    4342              ['start', 'end'], target=Target())
    4343          events = parser.read_events()
    4344
    4345          parser.feed('<root><element>')
    4346          self.assert_event_tags(
    4347              events, [('start', 'root'), ('start', 'element')])
    4348          self.assertFalse(list(events))
    4349          parser.feed('</element><child>')
    4350          self.assert_event_tags(
    4351              events, [('end', 'element-huhu'), ('start', 'child')])
    4352          parser.feed('</child>')
    4353          self.assert_event_tags(
    4354              events, [('end', 'child-huhu')])
    4355          parser.feed('</root>')
    4356          self.assert_event_tags(
    4357              events, [('end', 'root-huhu')])
    4358          self.assertFalse(list(events))
    4359          root = parser.close()
    4360          self.assertEqual('root-huhu', root.tag)
    4361
    4362
    4363 -def test_suite():
    4364      suite = unittest.TestSuite()
    4365      suite.addTests([unittest.makeSuite(ETreeOnlyTestCase)])
    4366      suite.addTests([unittest.makeSuite(ETreeXIncludeTestCase)])
    4367      suite.addTests([unittest.makeSuite(ElementIncludeTestCase)])
    4368      suite.addTests([unittest.makeSuite(ETreeC14NTestCase)])
    4369      suite.addTests([unittest.makeSuite(ETreeWriteTestCase)])
    4370      suite.addTests([unittest.makeSuite(ETreeErrorLogTest)])
    4371      suite.addTests([unittest.makeSuite(XMLPullParserTest)])
    4372      suite.addTests(doctest.DocTestSuite(etree))
    4373      suite.addTests(
    4374          [make_doctest('../../../doc/tutorial.txt')])
    4375      if sys.version_info >= (2,6):
    4376          # now requires the 'with' statement
    4377          suite.addTests(
    4378              [make_doctest('../../../doc/api.txt')])
    4379      suite.addTests(
    4380          [make_doctest('../../../doc/FAQ.txt')])
    4381      suite.addTests(
    4382          [make_doctest('../../../doc/parsing.txt')])
    4383      suite.addTests(
    4384          [make_doctest('../../../doc/resolvers.txt')])
    4385      return suite
    4386
    4387  if __name__ == '__main__':
    4388      print('to test use test.py %s' % __file__)
    4389