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