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