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