lxml.tests.test_elementtree

Package lxml :: Package tests :: Module test_elementtree |
[hide private]
[frames] | no frames]

# Source Code for Module lxml.tests.test_elementtree

       1  # -*- coding: utf-8 -*-
       2
       3  """
       4  Tests for the ElementTree API
       5
       6  Only test cases that apply equally well to etree and ElementTree
       7  belong here. Note that there is a second test module called test_io.py
       8  for IO related test cases.
       9  """
      10
      11  from __future__ import absolute_import
      12
      13  import copy
      14  import io
      15  import operator
      16  import os
      17  import re
      18  import sys
      19  import textwrap
      20  import unittest
      21  from contextlib import contextmanager
      22  from functools import wraps, partial
      23  from itertools import islice
      24
      25  from .common_imports import (
      26      BytesIO, etree, HelperTestCase,
      27      ElementTree, cElementTree, ET_VERSION, CET_VERSION,
      28      filter_by_version, fileInTestDir, canonicalize, tmpfile,
      29      _str, _bytes, unicode, next, IS_PYTHON2
      30  )
      31
      32  if cElementTree is not None and (CET_VERSION <= (1,0,7) or sys.version_info[0] >= 3):
      33      cElementTree = None
      34
      35  if ElementTree is not None:
      36      print("Comparing with ElementTree %s" % getattr(ElementTree, "VERSION", "?"))
      37
      38  if cElementTree is not None:
      39      print("Comparing with cElementTree %s" % getattr(cElementTree, "VERSION", "?"))
      40
      41
      42 -def et_needs_pyversion(*version):
      43      def wrap(method):
      44          @wraps(method)
      45          def testfunc(self, *args):
      46              if self.etree is not etree and sys.version_info < version:
      47                  raise unittest.SkipTest("requires ET in Python %s" % '.'.join(map(str, version)))
      48              return method(self, *args)
      49          return testfunc
      50      return wrap
      51
      52
      53 -class _ETreeTestCaseBase(HelperTestCase):
      54      etree = None
      55      required_versions_ET = {}
      56      required_versions_cET = {}
      57
      58 -    def XMLParser(self, **kwargs):
      59          try:
      60              XMLParser = self.etree.XMLParser
      61          except AttributeError:
      62              assert 'ElementTree' in self.etree.__name__
      63              XMLParser = self.etree.TreeBuilder
      64          return XMLParser(**kwargs)
      65
      66      try:
      67          HelperTestCase.assertRegex
      68      except AttributeError:
      69 -        def assertRegex(self, *args, **kwargs):
      70              return self.assertRegexpMatches(*args, **kwargs)
      71
      72      @et_needs_pyversion(3, 6)
      73 -    def test_interface(self):
      74          # Test element tree interface.
      75
      76          def check_string(string):
      77              len(string)
      78              for char in string:
      79                  self.assertEqual(len(char), 1,
      80                          msg="expected one-character string, got %r" % char)
      81              new_string = string + ""
      82              new_string = string + " "
      83              string[:0]
      84
      85          def check_mapping(mapping):
      86              len(mapping)
      87              keys = mapping.keys()
      88              items = mapping.items()
      89              for key in keys:
      90                  item = mapping[key]
      91              mapping["key"] = "value"
      92              self.assertEqual(mapping["key"], "value",
      93                      msg="expected value string, got %r" % mapping["key"])
      94
      95          def check_element(element):
      96              self.assertTrue(self.etree.iselement(element), msg="not an element")
      97              direlem = dir(element)
      98              for attr in 'tag', 'attrib', 'text', 'tail':
      99                  self.assertTrue(hasattr(element, attr),
     100                          msg='no %s member' % attr)
     101                  self.assertIn(attr, direlem,
     102                          msg='no %s visible by dir' % attr)
     103
     104              check_string(element.tag)
     105              check_mapping(element.attrib)
     106              if element.text is not None:
     107                  check_string(element.text)
     108              if element.tail is not None:
     109                  check_string(element.tail)
     110              for elem in element:
     111                  check_element(elem)
     112
     113          element = self.etree.Element("tag")
     114          check_element(element)
     115          tree = self.etree.ElementTree(element)
     116          check_element(tree.getroot())
     117          element = self.etree.Element(u"t\xe4g", key="value")
     118          tree = self.etree.ElementTree(element)
     119          # lxml and ET Py2: slightly different repr()
     120          #self.assertRegex(repr(element), r"^<Element 't\xe4g' at 0x.*>$")
     121          element = self.etree.Element("tag", key="value")
     122
     123          # Make sure all standard element methods exist.
     124
     125          def check_method(method):
     126              self.assertTrue(hasattr(method, '__call__'),
     127                      msg="%s not callable" % method)
     128
     129          check_method(element.append)
     130          check_method(element.extend)
     131          check_method(element.insert)
     132          check_method(element.remove)
     133          check_method(element.getchildren)
     134          check_method(element.find)
     135          check_method(element.iterfind)
     136          check_method(element.findall)
     137          check_method(element.findtext)
     138          check_method(element.clear)
     139          check_method(element.get)
     140          check_method(element.set)
     141          check_method(element.keys)
     142          check_method(element.items)
     143          check_method(element.iter)
     144          check_method(element.itertext)
     145          check_method(element.getiterator)
     146
     147          # These methods return an iterable. See bug 6472.
     148
     149          def check_iter(it):
     150              check_method(it.next if IS_PYTHON2 else it.__next__)
     151
     152          check_iter(element.iterfind("tag"))
     153          check_iter(element.iterfind("*"))
     154          check_iter(tree.iterfind("tag"))
     155          check_iter(tree.iterfind("*"))
     156
     157          # These aliases are provided:
     158
     159          # not an alias in lxml
     160          #self.assertEqual(self.etree.XML, self.etree.fromstring)
     161          self.assertEqual(self.etree.PI, self.etree.ProcessingInstruction)
     162
     163 -    def test_element(self):
     164          for i in range(10):
     165              e = self.etree.Element('foo')
     166              self.assertEqual(e.tag, 'foo')
     167              self.assertEqual(e.text, None)
     168              self.assertEqual(e.tail, None)
     169
     170 -    def test_simple(self):
     171          Element = self.etree.Element
     172
     173          root = Element('root')
     174          root.append(Element('one'))
     175          root.append(Element('two'))
     176          root.append(Element('three'))
     177          self.assertEqual(3, len(root))
     178          self.assertEqual('one', root[0].tag)
     179          self.assertEqual('two', root[1].tag)
     180          self.assertEqual('three', root[2].tag)
     181          self.assertRaises(IndexError, operator.getitem, root, 3)
     182
     183      # test weird dictionary interaction leading to segfault previously
     184 -    def test_weird_dict_interaction(self):
     185          root = self.etree.Element('root')
     186          self.assertEqual(root.tag, "root")
     187          add = self.etree.ElementTree(file=BytesIO('<foo>Foo</foo>'))
     188          self.assertEqual(add.getroot().tag, "foo")
     189          self.assertEqual(add.getroot().text, "Foo")
     190          root.append(self.etree.Element('baz'))
     191          self.assertEqual(root.tag, "root")
     192          self.assertEqual(root[0].tag, "baz")
     193
     194 -    def test_subelement(self):
     195          Element = self.etree.Element
     196          SubElement = self.etree.SubElement
     197
     198          root = Element('root')
     199          SubElement(root, 'one')
     200          SubElement(root, 'two')
     201          SubElement(root, 'three')
     202          self.assertEqual(3, len(root))
     203          self.assertEqual('one', root[0].tag)
     204          self.assertEqual('two', root[1].tag)
     205          self.assertEqual('three', root[2].tag)
     206
     207 -    def test_element_contains(self):
     208          Element = self.etree.Element
     209          SubElement = self.etree.SubElement
     210
     211          root1 = Element('root')
     212          SubElement(root1, 'one')
     213          self.assertTrue(root1[0] in root1)
     214
     215          root2 = Element('root')
     216          SubElement(root2, 'two')
     217          SubElement(root2, 'three')
     218          self.assertTrue(root2[0] in root2)
     219          self.assertTrue(root2[1] in root2)
     220
     221          self.assertFalse(root1[0] in root2)
     222          self.assertFalse(root2[0] in root1)
     223          self.assertFalse(None in root2)
     224
     225 -    def test_element_indexing_with_text(self):
     226          ElementTree = self.etree.ElementTree
     227
     228          f = BytesIO('<doc>Test<one>One</one></doc>')
     229          doc = ElementTree(file=f)
     230          root = doc.getroot()
     231          self.assertEqual(1, len(root))
     232          self.assertEqual('one', root[0].tag)
     233          self.assertRaises(IndexError, operator.getitem, root, 1)
     234
     235 -    def test_element_indexing_with_text2(self):
     236          ElementTree = self.etree.ElementTree
     237
     238          f = BytesIO('<doc><one>One</one><two>Two</two>hm<three>Three</three></doc>')
     239          doc = ElementTree(file=f)
     240          root = doc.getroot()
     241          self.assertEqual(3, len(root))
     242          self.assertEqual('one', root[0].tag)
     243          self.assertEqual('two', root[1].tag)
     244          self.assertEqual('three', root[2].tag)
     245
     246 -    def test_element_indexing_only_text(self):
     247          ElementTree = self.etree.ElementTree
     248
     249          f = BytesIO('<doc>Test</doc>')
     250          doc = ElementTree(file=f)
     251          root = doc.getroot()
     252          self.assertEqual(0, len(root))
     253
     254 -    def test_element_indexing_negative(self):
     255          Element = self.etree.Element
     256          SubElement = self.etree.SubElement
     257          a = Element('a')
     258          b = SubElement(a, 'b')
     259          c = SubElement(a, 'c')
     260          d = SubElement(a, 'd')
     261          self.assertEqual(d, a[-1])
     262          self.assertEqual(c, a[-2])
     263          self.assertEqual(b, a[-3])
     264          self.assertRaises(IndexError, operator.getitem, a, -4)
     265          a[-1] = e = Element('e')
     266          self.assertEqual(e, a[-1])
     267          del a[-1]
     268          self.assertEqual(2, len(a))
     269
     270 -    def test_elementtree(self):
     271          ElementTree = self.etree.ElementTree
     272
     273          f = BytesIO('<doc><one>One</one><two>Two</two></doc>')
     274          doc = ElementTree(file=f)
     275          root = doc.getroot()
     276          self.assertEqual(2, len(root))
     277          self.assertEqual('one', root[0].tag)
     278          self.assertEqual('two', root[1].tag)
     279
     280 -    def test_text(self):
     281          ElementTree = self.etree.ElementTree
     282
     283          f = BytesIO('<doc>This is a text</doc>')
     284          doc = ElementTree(file=f)
     285          root = doc.getroot()
     286          self.assertEqual('This is a text', root.text)
     287
     288 -    def test_text_empty(self):
     289          ElementTree = self.etree.ElementTree
     290
     291          f = BytesIO('<doc></doc>')
     292          doc = ElementTree(file=f)
     293          root = doc.getroot()
     294          self.assertEqual(None, root.text)
     295
     296 -    def test_text_other(self):
     297          ElementTree = self.etree.ElementTree
     298
     299          f = BytesIO('<doc><one>One</one></doc>')
     300          doc = ElementTree(file=f)
     301          root = doc.getroot()
     302          self.assertEqual(None, root.text)
     303          self.assertEqual('One', root[0].text)
     304
     305 -    def test_text_escape_in(self):
     306          ElementTree = self.etree.ElementTree
     307
     308          f = BytesIO('<doc>This is &gt; than a text</doc>')
     309          doc = ElementTree(file=f)
     310          root = doc.getroot()
     311          self.assertEqual('This is > than a text', root.text)
     312
     313 -    def test_text_escape_out(self):
     314          Element = self.etree.Element
     315
     316          a = Element("a")
     317          a.text = "<>&"
     318          self.assertXML(_bytes('<a>&lt;&gt;&amp;</a>'),
     319                         a)
     320
     321 -    def test_text_escape_tostring(self):
     322          tostring = self.etree.tostring
     323          Element  = self.etree.Element
     324
     325          a = Element("a")
     326          a.text = "<>&"
     327          self.assertEqual(_bytes('<a>&lt;&gt;&amp;</a>'),
     328                           tostring(a))
     329
     330 -    def test_text_str_subclass(self):
     331          Element = self.etree.Element
     332
     333          class strTest(str):
     334              pass
     335
     336          a = Element("a")
     337          a.text = strTest("text")
     338          self.assertXML(_bytes('<a>text</a>'),
     339                         a)
     340
     341 -    def test_tail(self):
     342          ElementTree = self.etree.ElementTree
     343
     344          f = BytesIO('<doc>This is <i>mixed</i> content.</doc>')
     345          doc = ElementTree(file=f)
     346          root = doc.getroot()
     347          self.assertEqual(1, len(root))
     348          self.assertEqual('This is ', root.text)
     349          self.assertEqual(None, root.tail)
     350          self.assertEqual('mixed', root[0].text)
     351          self.assertEqual(' content.', root[0].tail)
     352
     353 -    def test_tail_str_subclass(self):
     354          Element = self.etree.Element
     355          SubElement = self.etree.SubElement
     356
     357          class strTest(str):
     358              pass
     359
     360          a = Element("a")
     361          SubElement(a, "t").tail = strTest("tail")
     362          self.assertXML(_bytes('<a><t></t>tail</a>'),
     363                         a)
     364
     365 -    def _test_del_tail(self):
     366          # this is discouraged for ET compat, should not be tested...
     367          XML = self.etree.XML
     368
     369          root = XML(_bytes('<doc>This is <i>mixed</i> content.</doc>'))
     370          self.assertEqual(1, len(root))
     371          self.assertEqual('This is ', root.text)
     372          self.assertEqual(None, root.tail)
     373          self.assertEqual('mixed', root[0].text)
     374          self.assertEqual(' content.', root[0].tail)
     375
     376          del root[0].tail
     377
     378          self.assertEqual(1, len(root))
     379          self.assertEqual('This is ', root.text)
     380          self.assertEqual(None, root.tail)
     381          self.assertEqual('mixed', root[0].text)
     382          self.assertEqual(None, root[0].tail)
     383
     384          root[0].tail = "TAIL"
     385
     386          self.assertEqual(1, len(root))
     387          self.assertEqual('This is ', root.text)
     388          self.assertEqual(None, root.tail)
     389          self.assertEqual('mixed', root[0].text)
     390          self.assertEqual('TAIL', root[0].tail)
     391
     392 -    def test_ElementTree(self):
     393          Element = self.etree.Element
     394          ElementTree = self.etree.ElementTree
     395
     396          el = Element('hoi')
     397          doc = ElementTree(el)
     398          root = doc.getroot()
     399          self.assertEqual(None, root.text)
     400          self.assertEqual('hoi', root.tag)
     401
     402 -    def test_attrib(self):
     403          ElementTree = self.etree.ElementTree
     404
     405          f = BytesIO('<doc one="One" two="Two"/>')
     406          doc = ElementTree(file=f)
     407          root = doc.getroot()
     408          self.assertEqual('One', root.attrib['one'])
     409          self.assertEqual('Two', root.attrib['two'])
     410          self.assertRaises(KeyError, operator.getitem, root.attrib, 'three')
     411
     412 -    def test_attrib_get(self):
     413          ElementTree = self.etree.ElementTree
     414
     415          f = BytesIO('<doc one="One" two="Two"/>')
     416          doc = ElementTree(file=f)
     417          root = doc.getroot()
     418          self.assertEqual('One', root.attrib.get('one'))
     419          self.assertEqual('Two', root.attrib.get('two'))
     420          self.assertEqual(None, root.attrib.get('three'))
     421          self.assertEqual('foo', root.attrib.get('three', 'foo'))
     422
     423 -    def test_attrib_dict(self):
     424          ElementTree = self.etree.ElementTree
     425
     426          f = BytesIO('<doc one="One" two="Two"/>')
     427          doc = ElementTree(file=f)
     428          root = doc.getroot()
     429          attrib = dict(root.attrib)
     430          self.assertEqual('One', attrib['one'])
     431          self.assertEqual('Two', attrib['two'])
     432          self.assertRaises(KeyError, operator.getitem, attrib, 'three')
     433
     434 -    def test_attrib_copy(self):
     435          ElementTree = self.etree.ElementTree
     436
     437          f = BytesIO('<doc one="One" two="Two"/>')
     438          doc = ElementTree(file=f)
     439          root = doc.getroot()
     440          attrib = copy.copy(root.attrib)
     441          self.assertEqual('One', attrib['one'])
     442          self.assertEqual('Two', attrib['two'])
     443          self.assertRaises(KeyError, operator.getitem, attrib, 'three')
     444
     445 -    def test_attrib_deepcopy(self):
     446          ElementTree = self.etree.ElementTree
     447
     448          f = BytesIO('<doc one="One" two="Two"/>')
     449          doc = ElementTree(file=f)
     450          root = doc.getroot()
     451          attrib = copy.deepcopy(root.attrib)
     452          self.assertEqual('One', attrib['one'])
     453          self.assertEqual('Two', attrib['two'])
     454          self.assertRaises(KeyError, operator.getitem, attrib, 'three')
     455
     456 -    def test_attributes_get(self):
     457          ElementTree = self.etree.ElementTree
     458
     459          f = BytesIO('<doc one="One" two="Two"/>')
     460          doc = ElementTree(file=f)
     461          root = doc.getroot()
     462          self.assertEqual('One', root.get('one'))
     463          self.assertEqual('Two', root.get('two'))
     464          self.assertEqual(None, root.get('three'))
     465          self.assertEqual('foo', root.get('three', 'foo'))
     466
     467 -    def test_attrib_clear(self):
     468          XML = self.etree.XML
     469
     470          root = XML(_bytes('<doc one="One" two="Two"/>'))
     471          self.assertEqual('One', root.get('one'))
     472          self.assertEqual('Two', root.get('two'))
     473          root.attrib.clear()
     474          self.assertEqual(None, root.get('one'))
     475          self.assertEqual(None, root.get('two'))
     476
     477 -    def test_attrib_set_clear(self):
     478          Element = self.etree.Element
     479
     480          root = Element("root", one="One")
     481          root.set("two", "Two")
     482          self.assertEqual('One', root.get('one'))
     483          self.assertEqual('Two', root.get('two'))
     484          root.attrib.clear()
     485          self.assertEqual(None, root.get('one'))
     486          self.assertEqual(None, root.get('two'))
     487
     488 -    def test_attrib_ns_clear(self):
     489          Element = self.etree.Element
     490          SubElement = self.etree.SubElement
     491
     492          attribNS = '{http://foo/bar}x'
     493
     494          parent = Element('parent')
     495          parent.set(attribNS, 'a')
     496          child = SubElement(parent, 'child')
     497          child.set(attribNS, 'b')
     498
     499          self.assertEqual('a', parent.get(attribNS))
     500          self.assertEqual('b', child.get(attribNS))
     501
     502          parent.clear()
     503          self.assertEqual(None, parent.get(attribNS))
     504          self.assertEqual('b', child.get(attribNS))
     505
     506 -    def test_attrib_pop(self):
     507          ElementTree = self.etree.ElementTree
     508
     509          f = BytesIO('<doc one="One" two="Two"/>')
     510          doc = ElementTree(file=f)
     511          root = doc.getroot()
     512          self.assertEqual('One', root.attrib['one'])
     513          self.assertEqual('Two', root.attrib['two'])
     514
     515          self.assertEqual('One', root.attrib.pop('one'))
     516
     517          self.assertEqual(None, root.attrib.get('one'))
     518          self.assertEqual('Two', root.attrib['two'])
     519
     520 -    def test_attrib_pop_unknown(self):
     521          root = self.etree.XML(_bytes('<doc one="One" two="Two"/>'))
     522          self.assertRaises(KeyError, root.attrib.pop, 'NONE')
     523
     524          self.assertEqual('One', root.attrib['one'])
     525          self.assertEqual('Two', root.attrib['two'])
     526
     527 -    def test_attrib_pop_default(self):
     528          root = self.etree.XML(_bytes('<doc one="One" two="Two"/>'))
     529          self.assertEqual('Three', root.attrib.pop('three', 'Three'))
     530
     531 -    def test_attrib_pop_empty_default(self):
     532          root = self.etree.XML(_bytes('<doc/>'))
     533          self.assertEqual('Three', root.attrib.pop('three', 'Three'))
     534
     535 -    def test_attrib_pop_invalid_args(self):
     536          root = self.etree.XML(_bytes('<doc one="One" two="Two"/>'))
     537          self.assertRaises(TypeError, root.attrib.pop, 'One', None, None)
     538
     539 -    def test_attribute_update_dict(self):
     540          XML = self.etree.XML
     541
     542          root = XML(_bytes('<doc alpha="Alpha" beta="Beta"/>'))
     543          items = list(root.attrib.items())
     544          items.sort()
     545          self.assertEqual(
     546              [('alpha', 'Alpha'), ('beta', 'Beta')],
     547              items)
     548
     549          root.attrib.update({'alpha' : 'test', 'gamma' : 'Gamma'})
     550
     551          items = list(root.attrib.items())
     552          items.sort()
     553          self.assertEqual(
     554              [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')],
     555              items)
     556
     557 -    def test_attribute_update_sequence(self):
     558          XML = self.etree.XML
     559
     560          root = XML(_bytes('<doc alpha="Alpha" beta="Beta"/>'))
     561          items = list(root.attrib.items())
     562          items.sort()
     563          self.assertEqual(
     564              [('alpha', 'Alpha'), ('beta', 'Beta')],
     565              items)
     566
     567          root.attrib.update({'alpha' : 'test', 'gamma' : 'Gamma'}.items())
     568
     569          items = list(root.attrib.items())
     570          items.sort()
     571          self.assertEqual(
     572              [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')],
     573              items)
     574
     575 -    def test_attribute_update_iter(self):
     576          XML = self.etree.XML
     577
     578          root = XML(_bytes('<doc alpha="Alpha" beta="Beta"/>'))
     579          items = list(root.attrib.items())
     580          items.sort()
     581          self.assertEqual(
     582              [('alpha', 'Alpha'), ('beta', 'Beta')],
     583              items)
     584
     585          root.attrib.update(iter({'alpha' : 'test', 'gamma' : 'Gamma'}.items()))
     586
     587          items = list(root.attrib.items())
     588          items.sort()
     589          self.assertEqual(
     590              [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')],
     591              items)
     592
     593 -    def test_attribute_update_attrib(self):
     594          XML = self.etree.XML
     595
     596          root = XML(_bytes('<doc alpha="Alpha" beta="Beta"/>'))
     597          items = list(root.attrib.items())
     598          items.sort()
     599          self.assertEqual(
     600              [('alpha', 'Alpha'), ('beta', 'Beta')],
     601                                                    items)
     602
     603          other = XML(_bytes('<doc alpha="test" gamma="Gamma"/>'))
     604          root.attrib.update(other.attrib)
     605
     606          items = list(root.attrib.items())
     607          items.sort()
     608          self.assertEqual(
     609              [('alpha', 'test'), ('beta', 'Beta'), ('gamma', 'Gamma')],
     610                                                                       items)
     611
     612 -    def test_attribute_keys(self):
     613          XML = self.etree.XML
     614
     615          root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
     616          keys = list(root.attrib.keys())
     617          keys.sort()
     618          self.assertEqual(['alpha', 'beta', 'gamma'], keys)
     619
     620 -    def test_attribute_keys2(self):
     621          XML = self.etree.XML
     622
     623          root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
     624          keys = list(root.keys())
     625          keys.sort()
     626          self.assertEqual(['alpha', 'beta', 'gamma'], keys)
     627
     628 -    def test_attribute_items2(self):
     629          XML = self.etree.XML
     630
     631          root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
     632          items = list(root.items())
     633          items.sort()
     634          self.assertEqual(
     635              [('alpha','Alpha'), ('beta','Beta'), ('gamma','Gamma')],
     636              items)
     637
     638 -    def test_attribute_keys_ns(self):
     639          XML = self.etree.XML
     640
     641          root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
     642          keys = list(root.keys())
     643          keys.sort()
     644          self.assertEqual(['bar', '{http://ns.codespeak.net/test}baz'],
     645                            keys)
     646
     647 -    def test_attribute_values(self):
     648          XML = self.etree.XML
     649
     650          root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
     651          values = list(root.attrib.values())
     652          values.sort()
     653          self.assertEqual(['Alpha', 'Beta', 'Gamma'], values)
     654
     655 -    def test_attribute_values_ns(self):
     656          XML = self.etree.XML
     657
     658          root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
     659          values = list(root.attrib.values())
     660          values.sort()
     661          self.assertEqual(
     662              ['Bar', 'Baz'], values)
     663
     664 -    def test_attribute_items(self):
     665          XML = self.etree.XML
     666
     667          root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma"/>'))
     668          items = list(root.attrib.items())
     669          items.sort()
     670          self.assertEqual([
     671              ('alpha', 'Alpha'),
     672              ('beta', 'Beta'),
     673              ('gamma', 'Gamma'),
     674              ],
     675              items)
     676
     677 -    def test_attribute_items_ns(self):
     678          XML = self.etree.XML
     679
     680          root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
     681          items = list(root.attrib.items())
     682          items.sort()
     683          self.assertEqual(
     684              [('bar', 'Bar'), ('{http://ns.codespeak.net/test}baz', 'Baz')],
     685              items)
     686
     687 -    def test_attribute_str(self):
     688          XML = self.etree.XML
     689
     690          expected = "{'{http://ns.codespeak.net/test}baz': 'Baz', 'bar': 'Bar'}"
     691          alternative = "{'bar': 'Bar', '{http://ns.codespeak.net/test}baz': 'Baz'}"
     692
     693          root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
     694          try:
     695              self.assertEqual(expected, str(root.attrib))
     696          except AssertionError:
     697              self.assertEqual(alternative, str(root.attrib))
     698
     699 -    def test_attribute_contains(self):
     700          XML = self.etree.XML
     701
     702          root = XML(_bytes('<foo bar="Bar" xmlns:ns="http://ns.codespeak.net/test" ns:baz="Baz" />'))
     703          self.assertEqual(
     704              True, 'bar' in root.attrib)
     705          self.assertEqual(
     706              False, 'baz' in root.attrib)
     707          self.assertEqual(
     708              False, 'hah' in root.attrib)
     709          self.assertEqual(
     710              True,
     711              '{http://ns.codespeak.net/test}baz' in root.attrib)
     712
     713 -    def test_attribute_set(self):
     714          Element = self.etree.Element
     715
     716          root = Element("root")
     717          root.set("attr", "TEST")
     718          self.assertEqual("TEST", root.get("attr"))
     719
     720 -    def test_attrib_as_attrib(self):
     721          Element = self.etree.Element
     722
     723          root = Element("root")
     724          root.set("attr", "TEST")
     725          self.assertEqual("TEST", root.attrib["attr"])
     726
     727          root2 = Element("root2", root.attrib)
     728          self.assertEqual("TEST", root2.attrib["attr"])
     729
     730 -    def test_attribute_iterator(self):
     731          XML = self.etree.XML
     732
     733          root = XML(_bytes('<doc alpha="Alpha" beta="Beta" gamma="Gamma" />'))
     734          result = []
     735          for key in root.attrib:
     736              result.append(key)
     737          result.sort()
     738          self.assertEqual(['alpha', 'beta', 'gamma'], result)
     739
     740 -    def test_attribute_manipulation(self):
     741          Element = self.etree.Element
     742
     743          a = Element('a')
     744          a.attrib['foo'] = 'Foo'
     745          a.attrib['bar'] = 'Bar'
     746          self.assertEqual('Foo', a.attrib['foo'])
     747          del a.attrib['foo']
     748          self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
     749
     750 -    def test_del_attribute_ns(self):
     751          Element = self.etree.Element
     752
     753          a = Element('a')
     754          a.attrib['{http://a/}foo'] = 'Foo'
     755          a.attrib['{http://a/}bar'] = 'Bar'
     756          self.assertEqual(None, a.get('foo'))
     757          self.assertEqual('Foo', a.get('{http://a/}foo'))
     758          self.assertEqual('Foo', a.attrib['{http://a/}foo'])
     759
     760          self.assertRaises(KeyError, operator.delitem, a.attrib, 'foo')
     761          self.assertEqual('Foo', a.attrib['{http://a/}foo'])
     762
     763          del a.attrib['{http://a/}foo']
     764          self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
     765
     766 -    def test_del_attribute_ns_parsed(self):
     767          XML = self.etree.XML
     768
     769          a = XML(_bytes('<a xmlns:nsa="http://a/" nsa:foo="FooNS" foo="Foo" />'))
     770
     771          self.assertEqual('Foo', a.attrib['foo'])
     772          self.assertEqual('FooNS', a.attrib['{http://a/}foo'])
     773
     774          del a.attrib['foo']
     775          self.assertEqual('FooNS', a.attrib['{http://a/}foo'])
     776          self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
     777          self.assertRaises(KeyError, operator.delitem, a.attrib, 'foo')
     778
     779          del a.attrib['{http://a/}foo']
     780          self.assertRaises(KeyError, operator.getitem, a.attrib, '{http://a/}foo')
     781          self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
     782
     783          a = XML(_bytes('<a xmlns:nsa="http://a/" foo="Foo" nsa:foo="FooNS" />'))
     784
     785          self.assertEqual('Foo', a.attrib['foo'])
     786          self.assertEqual('FooNS', a.attrib['{http://a/}foo'])
     787
     788          del a.attrib['foo']
     789          self.assertEqual('FooNS', a.attrib['{http://a/}foo'])
     790          self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
     791
     792          del a.attrib['{http://a/}foo']
     793          self.assertRaises(KeyError, operator.getitem, a.attrib, '{http://a/}foo')
     794          self.assertRaises(KeyError, operator.getitem, a.attrib, 'foo')
     795
     796 -    def test_XML(self):
     797          XML = self.etree.XML
     798
     799          root = XML(_bytes('<doc>This is a text.</doc>'))
     800          self.assertEqual(0, len(root))
     801          self.assertEqual('This is a text.', root.text)
     802
     803 -    def test_XMLID(self):
     804          XMLID = self.etree.XMLID
     805          XML   = self.etree.XML
     806          xml_text = _bytes('''
     807          <document>
     808            <h1 id="chapter1">...</h1>
     809            <p id="note1" class="note">...</p>
     810            <p>Regular paragraph.</p>
     811            <p xml:id="xmlid">XML:ID paragraph.</p>
     812            <p id="warn1" class="warning">...</p>
     813          </document>
     814          ''')
     815
     816          root, dic = XMLID(xml_text)
     817          root2 = XML(xml_text)
     818          self.assertEqual(self._writeElement(root),
     819                            self._writeElement(root2))
     820          expected = {
     821              "chapter1" : root[0],
     822              "note1"    : root[1],
     823              "warn1"    : root[4]
     824              }
     825          self.assertEqual(dic, expected)
     826
     827 -    def test_fromstring(self):
     828          fromstring = self.etree.fromstring
     829
     830          root = fromstring('<doc>This is a text.</doc>')
     831          self.assertEqual(0, len(root))
     832          self.assertEqual('This is a text.', root.text)
     833
     834      required_versions_ET['test_fromstringlist'] = (1,3)
     835 -    def test_fromstringlist(self):
     836          fromstringlist = self.etree.fromstringlist
     837
     838          root = fromstringlist(["<do", "c>T", "hi", "s is",
     839                                 " a text.<", "/doc", ">"])
     840          self.assertEqual(0, len(root))
     841          self.assertEqual('This is a text.', root.text)
     842
     843      required_versions_ET['test_fromstringlist_characters'] = (1,3)
     844 -    def test_fromstringlist_characters(self):
     845          fromstringlist = self.etree.fromstringlist
     846
     847          root = fromstringlist(list('<doc>This is a text.</doc>'))
     848          self.assertEqual(0, len(root))
     849          self.assertEqual('This is a text.', root.text)
     850
     851      required_versions_ET['test_fromstringlist_single'] = (1,3)
     852 -    def test_fromstringlist_single(self):
     853          fromstringlist = self.etree.fromstringlist
     854
     855          root = fromstringlist(['<doc>This is a text.</doc>'])
     856          self.assertEqual(0, len(root))
     857          self.assertEqual('This is a text.', root.text)
     858
     859 -    def test_iselement(self):
     860          iselement = self.etree.iselement
     861          Element = self.etree.Element
     862          ElementTree = self.etree.ElementTree
     863          XML = self.etree.XML
     864          Comment = self.etree.Comment
     865          ProcessingInstruction = self.etree.ProcessingInstruction
     866
     867          el = Element('hoi')
     868          self.assertTrue(iselement(el))
     869
     870          el2 = XML(_bytes('<foo/>'))
     871          self.assertTrue(iselement(el2))
     872
     873          tree = ElementTree(element=Element('dag'))
     874          self.assertTrue(not iselement(tree))
     875          self.assertTrue(iselement(tree.getroot()))
     876
     877          c = Comment('test')
     878          self.assertTrue(iselement(c))
     879
     880          p = ProcessingInstruction("test", "some text")
     881          self.assertTrue(iselement(p))
     882
     883 -    def test_iteration(self):
     884          XML = self.etree.XML
     885
     886          root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
     887          result = []
     888          for el in root:
     889              result.append(el.tag)
     890          self.assertEqual(['one', 'two', 'three'], result)
     891
     892 -    def test_iteration_empty(self):
     893          XML = self.etree.XML
     894
     895          root = XML(_bytes('<doc></doc>'))
     896          result = []
     897          for el in root:
     898              result.append(el.tag)
     899          self.assertEqual([], result)
     900
     901 -    def test_iteration_text_only(self):
     902          XML = self.etree.XML
     903
     904          root = XML(_bytes('<doc>Text</doc>'))
     905          result = []
     906          for el in root:
     907              result.append(el.tag)
     908          self.assertEqual([], result)
     909
     910 -    def test_iteration_set_tail_empty(self):
     911          # this would cause a crash in the past
     912          fromstring = self.etree.fromstring
     913          root = fromstring('<html><p></p>x</html>')
     914          for elem in root:
     915              elem.tail = ''
     916
     917 -    def test_iteration_clear_tail(self):
     918          # this would cause a crash in the past
     919          fromstring = self.etree.fromstring
     920          root = fromstring('<html><p></p>x</html>')
     921          for elem in root:
     922              elem.tail = None
     923
     924 -    def test_iteration_reversed(self):
     925          XML = self.etree.XML
     926          root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
     927          result = []
     928          for el in reversed(root):
     929              result.append(el.tag)
     930          self.assertEqual(['three', 'two', 'one'], result)
     931
     932 -    def test_iteration_subelement(self):
     933          XML = self.etree.XML
     934
     935          root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
     936          result = []
     937          add = True
     938          for el in root:
     939              result.append(el.tag)
     940              if add:
     941                  self.etree.SubElement(root, 'four')
     942                  add = False
     943          self.assertEqual(['one', 'two', 'three', 'four'], result)
     944
     945 -    def test_iteration_del_child(self):
     946          XML = self.etree.XML
     947
     948          root = XML(_bytes('<doc><one/><two>Two</two>Hm<three/></doc>'))
     949          result = []
     950          for el in root:
     951              result.append(el.tag)
     952              del root[-1]
     953          self.assertEqual(['one', 'two'], result)
     954
     955 -    def test_iteration_double(self):
     956          XML = self.etree.XML
     957
     958          root = XML(_bytes('<doc><one/><two/></doc>'))
     959          result = []
     960          for el0 in root:
     961              result.append(el0.tag)
     962              for el1 in root:
     963                  result.append(el1.tag)
     964          self.assertEqual(['one','one', 'two', 'two', 'one', 'two'], result)
     965
     966      required_versions_ET['test_itertext'] = (1,3)
     967 -    def test_itertext(self):
     968          # ET 1.3+
     969          XML = self.etree.XML
     970          root = XML(_bytes("<root>RTEXT<a></a>ATAIL<b/><c>CTEXT</c>CTAIL</root>"))
     971
     972          text = list(root.itertext())
     973          self.assertEqual(["RTEXT", "ATAIL", "CTEXT", "CTAIL"],
     974                            text)
     975
     976      required_versions_ET['test_itertext_child'] = (1,3)
     977 -    def test_itertext_child(self):
     978          # ET 1.3+
     979          XML = self.etree.XML
     980          root = XML(_bytes("<root>RTEXT<a></a>ATAIL<b/><c>CTEXT</c>CTAIL</root>"))
     981
     982          text = list(root[2].itertext())
     983          self.assertEqual(["CTEXT"],
     984                            text)
     985
     986 -    def test_findall(self):
     987          XML = self.etree.XML
     988          root = XML(_bytes('<a><b><c/></b><b/><c><b/></c></a>'))
     989          self.assertEqual(len(list(root.findall("c"))), 1)
     990          self.assertEqual(len(list(root.findall(".//c"))), 2)
     991          self.assertEqual(len(list(root.findall(".//b"))), 3)
     992          self.assertEqual(len(list(root.findall(".//b"))[0]), 1)
     993          self.assertEqual(len(list(root.findall(".//b"))[1]), 0)
     994          self.assertEqual(len(list(root.findall(".//b"))[2]), 0)
     995
     996 -    def test_findall_ns(self):
     997          XML = self.etree.XML
     998          root = XML(_bytes('<a xmlns:x="X" xmlns:y="Y"><x:b><c/></x:b><b/><c><x:b/><b/></c><b/></a>'))
     999          self.assertEqual(len(list(root.findall(".//{X}b"))), 2)
    1000          self.assertEqual(len(list(root.findall(".//b"))), 3)
    1001          self.assertEqual(len(list(root.findall("b"))), 2)
    1002
    1003      @et_needs_pyversion(3, 8, 0, 'alpha', 4)
    1004 -    def test_findall_wildcard(self):
    1005          def summarize_list(l):
    1006              return [el.tag for el in l]
    1007
    1008          root = self.etree.XML('''
    1009              <a xmlns:x="X" xmlns:y="Y">
    1010                  <x:b><c/></x:b>
    1011                  <b/>
    1012                  <c><x:b/><b/></c><y:b/>
    1013              </a>''')
    1014          root.append(self.etree.Comment('test'))
    1015
    1016          self.assertEqual(summarize_list(root.findall("{*}b")),
    1017                           ['{X}b', 'b', '{Y}b'])
    1018          self.assertEqual(summarize_list(root.findall("{*}c")),
    1019                           ['c'])
    1020          self.assertEqual(summarize_list(root.findall("{X}*")),
    1021                           ['{X}b'])
    1022          self.assertEqual(summarize_list(root.findall("{Y}*")),
    1023                           ['{Y}b'])
    1024          self.assertEqual(summarize_list(root.findall("{}*")),
    1025                           ['b', 'c'])
    1026          self.assertEqual(summarize_list(root.findall("{}b")),  # only for consistency
    1027                           ['b'])
    1028          self.assertEqual(summarize_list(root.findall("{}b")),
    1029                           summarize_list(root.findall("b")))
    1030          self.assertEqual(summarize_list(root.findall("{*}*")),
    1031                           ['{X}b', 'b', 'c', '{Y}b'])
    1032          self.assertEqual(summarize_list(root.findall("{*}*")
    1033                           + ([] if self.etree is etree else [root[-1]])),
    1034                           summarize_list(root.findall("*")))
    1035
    1036          self.assertEqual(summarize_list(root.findall(".//{*}b")),
    1037                           ['{X}b', 'b', '{X}b', 'b', '{Y}b'])
    1038          self.assertEqual(summarize_list(root.findall(".//{*}c")),
    1039                           ['c', 'c'])
    1040          self.assertEqual(summarize_list(root.findall(".//{X}*")),
    1041                           ['{X}b', '{X}b'])
    1042          self.assertEqual(summarize_list(root.findall(".//{Y}*")),
    1043                           ['{Y}b'])
    1044          self.assertEqual(summarize_list(root.findall(".//{}*")),
    1045                           ['c', 'b', 'c', 'b'])
    1046          self.assertEqual(summarize_list(root.findall(".//{}b")),
    1047                           ['b', 'b'])
    1048
    1049 -    def test_element_with_attributes_keywords(self):
    1050          Element = self.etree.Element
    1051
    1052          el = Element('tag', foo='Foo', bar='Bar')
    1053          self.assertEqual('Foo', el.attrib['foo'])
    1054          self.assertEqual('Bar', el.attrib['bar'])
    1055
    1056 -    def test_element_with_attributes(self):
    1057          Element = self.etree.Element
    1058
    1059          el = Element('tag', {'foo': 'Foo', 'bar': 'Bar'})
    1060          self.assertEqual('Foo', el.attrib['foo'])
    1061          self.assertEqual('Bar', el.attrib['bar'])
    1062
    1063 -    def test_element_with_attributes_extra(self):
    1064          Element = self.etree.Element
    1065
    1066          el = Element('tag', {'foo': 'Foo', 'bar': 'Bar'}, baz='Baz')
    1067          self.assertEqual('Foo', el.attrib['foo'])
    1068          self.assertEqual('Bar', el.attrib['bar'])
    1069          self.assertEqual('Baz', el.attrib['baz'])
    1070
    1071 -    def test_element_with_attributes_extra_duplicate(self):
    1072          Element = self.etree.Element
    1073
    1074          el = Element('tag', {'foo': 'Foo', 'bar': 'Bar'}, bar='Baz')
    1075          self.assertEqual('Foo', el.attrib['foo'])
    1076          self.assertEqual('Baz', el.attrib['bar'])
    1077
    1078 -    def test_element_with_attributes_ns(self):
    1079          Element = self.etree.Element
    1080
    1081          el = Element('tag', {'{ns1}foo':'Foo', '{ns2}bar':'Bar'})
    1082          self.assertEqual('Foo', el.attrib['{ns1}foo'])
    1083          self.assertEqual('Bar', el.attrib['{ns2}bar'])
    1084
    1085 -    def test_subelement_with_attributes(self):
    1086          Element =  self.etree.Element
    1087          SubElement = self.etree.SubElement
    1088
    1089          el = Element('tag')
    1090          SubElement(el, 'foo', {'foo':'Foo'}, baz="Baz")
    1091          self.assertEqual("Baz", el[0].attrib['baz'])
    1092          self.assertEqual('Foo', el[0].attrib['foo'])
    1093
    1094 -    def test_subelement_with_attributes_ns(self):
    1095          Element = self.etree.Element
    1096          SubElement = self.etree.SubElement
    1097
    1098          el = Element('tag')
    1099          SubElement(el, 'foo', {'{ns1}foo':'Foo', '{ns2}bar':'Bar'})
    1100          self.assertEqual('Foo', el[0].attrib['{ns1}foo'])
    1101          self.assertEqual('Bar', el[0].attrib['{ns2}bar'])
    1102
    1103 -    def test_write(self):
    1104          ElementTree = self.etree.ElementTree
    1105          XML = self.etree.XML
    1106
    1107          for i in range(10):
    1108              f = BytesIO()
    1109              root = XML(_bytes('<doc%s>This is a test.</doc%s>' % (i, i)))
    1110              tree = ElementTree(element=root)
    1111              tree.write(f)
    1112              data = f.getvalue()
    1113              self.assertEqual(
    1114                  _bytes('<doc%s>This is a test.</doc%s>' % (i, i)),
    1115                  canonicalize(data))
    1116
    1117      required_versions_ET['test_write_method_html'] = (1,3)
    1118 -    def test_write_method_html(self):
    1119          ElementTree = self.etree.ElementTree
    1120          Element = self.etree.Element
    1121          SubElement = self.etree.SubElement
    1122
    1123          html = Element('html')
    1124          body = SubElement(html, 'body')
    1125          p = SubElement(body, 'p')
    1126          p.text = "html"
    1127          SubElement(p, 'br').tail = "test"
    1128
    1129          tree = ElementTree(element=html)
    1130          f = BytesIO()
    1131          tree.write(f, method="html")
    1132          data = f.getvalue().replace(_bytes('\n'),_bytes(''))
    1133
    1134          self.assertEqual(_bytes('<html><body><p>html<br>test</p></body></html>'),
    1135                            data)
    1136
    1137      required_versions_ET['test_write_method_text'] = (1,3)
    1138 -    def test_write_method_text(self):
    1139          ElementTree = self.etree.ElementTree
    1140          Element = self.etree.Element
    1141          SubElement = self.etree.SubElement
    1142
    1143          a = Element('a')
    1144          a.text = "A"
    1145          a.tail = "tail"
    1146          b = SubElement(a, 'b')
    1147          b.text = "B"
    1148          b.tail = "TAIL"
    1149          c = SubElement(a, 'c')
    1150          c.text = "C"
    1151
    1152          tree = ElementTree(element=a)
    1153          f = BytesIO()
    1154          tree.write(f, method="text")
    1155          data = f.getvalue()
    1156
    1157          self.assertEqual(_bytes('ABTAILCtail'),
    1158                            data)
    1159
    1160 -    def test_write_fail(self):
    1161          ElementTree = self.etree.ElementTree
    1162          XML = self.etree.XML
    1163
    1164          tree = ElementTree( XML(_bytes('<doc>This is a test.</doc>')) )
    1165          self.assertRaises(IOError, tree.write,
    1166                            "definitely////\\-\\nonexisting\\-\\////FILE")
    1167
    1168      # this could trigger a crash, apparently because the document
    1169      # reference was prematurely garbage collected
    1170 -    def test_crash(self):
    1171          Element = self.etree.Element
    1172
    1173          element = Element('tag')
    1174          for i in range(10):
    1175              element.attrib['key'] = 'value'
    1176              value = element.attrib['key']
    1177              self.assertEqual(value, 'value')
    1178
    1179      # from doctest; for some reason this caused crashes too
    1180 -    def test_write_ElementTreeDoctest(self):
    1181          Element = self.etree.Element
    1182          ElementTree = self.etree.ElementTree
    1183
    1184          f = BytesIO()
    1185          for i in range(10):
    1186              element = Element('tag%s' % i)
    1187              self._check_element(element)
    1188              tree = ElementTree(element)
    1189              tree.write(f)
    1190              self._check_element_tree(tree)
    1191
    1192 -    def test_subelement_reference(self):
    1193          Element = self.etree.Element
    1194          SubElement = self.etree.SubElement
    1195
    1196          el = Element('foo')
    1197          el2 = SubElement(el, 'bar')
    1198          el3 = SubElement(el2, 'baz')
    1199
    1200          al = Element('foo2')
    1201          al2 = SubElement(al, 'bar2')
    1202          al3 = SubElement(al2, 'baz2')
    1203
    1204          # now move al2 into el
    1205          el.append(al2)
    1206
    1207          # now change al3 directly
    1208          al3.text = 'baz2-modified'
    1209
    1210          # it should have changed through this route too
    1211          self.assertEqual(
    1212              'baz2-modified',
    1213              el[1][0].text)
    1214
    1215 -    def test_set_text(self):
    1216          Element = self.etree.Element
    1217          SubElement = self.etree.SubElement
    1218
    1219          a = Element('a')
    1220          b = SubElement(a, 'b')
    1221          a.text = 'hoi'
    1222          self.assertEqual(
    1223              'hoi',
    1224              a.text)
    1225          self.assertEqual(
    1226              'b',
    1227              a[0].tag)
    1228
    1229 -    def test_set_text2(self):
    1230          Element = self.etree.Element
    1231          SubElement = self.etree.SubElement
    1232
    1233          a = Element('a')
    1234          a.text = 'hoi'
    1235          b = SubElement(a ,'b')
    1236          self.assertEqual(
    1237              'hoi',
    1238              a.text)
    1239          self.assertEqual(
    1240              'b',
    1241              a[0].tag)
    1242
    1243 -    def test_set_text_none(self):
    1244          Element = self.etree.Element
    1245
    1246          a = Element('a')
    1247
    1248          a.text = 'foo'
    1249          a.text = None
    1250
    1251          self.assertEqual(
    1252              None,
    1253              a.text)
    1254          self.assertXML(_bytes('<a></a>'), a)
    1255
    1256 -    def test_set_text_empty(self):
    1257          Element = self.etree.Element
    1258
    1259          a = Element('a')
    1260          self.assertEqual(None, a.text)
    1261
    1262          a.text = ''
    1263          self.assertEqual('', a.text)
    1264          self.assertXML(_bytes('<a></a>'), a)
    1265
    1266 -    def test_tail1(self):
    1267          Element = self.etree.Element
    1268          SubElement = self.etree.SubElement
    1269
    1270          a = Element('a')
    1271          a.tail = 'dag'
    1272          self.assertEqual('dag',
    1273                            a.tail)
    1274          b = SubElement(a, 'b')
    1275          b.tail = 'hoi'
    1276          self.assertEqual('hoi',
    1277                            b.tail)
    1278          self.assertEqual('dag',
    1279                            a.tail)
    1280
    1281 -    def test_tail_append(self):
    1282          Element = self.etree.Element
    1283
    1284          a = Element('a')
    1285          b = Element('b')
    1286          b.tail = 'b_tail'
    1287          a.append(b)
    1288          self.assertEqual('b_tail',
    1289                            b.tail)
    1290
    1291 -    def test_tail_set_twice(self):
    1292          Element = self.etree.Element
    1293          SubElement = self.etree.SubElement
    1294
    1295          a = Element('a')
    1296          b = SubElement(a, 'b')
    1297          b.tail = 'foo'
    1298          b.tail = 'bar'
    1299          self.assertEqual('bar',
    1300                            b.tail)
    1301          self.assertXML(_bytes('<a><b></b>bar</a>'), a)
    1302
    1303 -    def test_tail_set_none(self):
    1304          Element = self.etree.Element
    1305          a = Element('a')
    1306          a.tail = 'foo'
    1307          a.tail = None
    1308          self.assertEqual(
    1309              None,
    1310              a.tail)
    1311          self.assertXML(_bytes('<a></a>'), a)
    1312
    1313      required_versions_ET['test_extend'] = (1,3)
    1314 -    def test_extend(self):
    1315          root = self.etree.Element('foo')
    1316          for i in range(3):
    1317              element = self.etree.SubElement(root, 'a%s' % i)
    1318              element.text = "text%d" % i
    1319              element.tail = "tail%d" % i
    1320
    1321          elements = []
    1322          for i in range(3):
    1323              new_element = self.etree.Element("test%s" % i)
    1324              new_element.text = "TEXT%s" % i
    1325              new_element.tail = "TAIL%s" % i
    1326              elements.append(new_element)
    1327
    1328          root.extend(elements)
    1329
    1330          self.assertEqual(
    1331              ["a0", "a1", "a2", "test0", "test1", "test2"],
    1332              [ el.tag for el in root ])
    1333          self.assertEqual(
    1334              ["text0", "text1", "text2", "TEXT0", "TEXT1", "TEXT2"],
    1335              [ el.text for el in root ])
    1336          self.assertEqual(
    1337              ["tail0", "tail1", "tail2", "TAIL0", "TAIL1", "TAIL2"],
    1338              [ el.tail for el in root ])
    1339
    1340 -    def test_comment(self):
    1341          Element = self.etree.Element
    1342          SubElement = self.etree.SubElement
    1343          Comment = self.etree.Comment
    1344
    1345          a = Element('a')
    1346          a.append(Comment('foo'))
    1347          self.assertEqual(a[0].tag, Comment)
    1348          self.assertEqual(a[0].text, 'foo')
    1349
    1350      # ElementTree < 1.3 adds whitespace around comments
    1351      required_versions_ET['test_comment_text'] = (1,3)
    1352 -    def test_comment_text(self):
    1353          Element = self.etree.Element
    1354          SubElement = self.etree.SubElement
    1355          Comment = self.etree.Comment
    1356          tostring = self.etree.tostring
    1357
    1358          a = Element('a')
    1359          a.append(Comment('foo'))
    1360          self.assertEqual(a[0].text, 'foo')
    1361
    1362          self.assertEqual(
    1363              _bytes('<a><!--foo--></a>'),
    1364              tostring(a))
    1365
    1366          a[0].text = "TEST"
    1367          self.assertEqual(a[0].text, 'TEST')
    1368
    1369          self.assertEqual(
    1370              _bytes('<a><!--TEST--></a>'),
    1371              tostring(a))
    1372
    1373      # ElementTree < 1.3 adds whitespace around comments
    1374      required_versions_ET['test_comment_whitespace'] = (1,3)
    1375 -    def test_comment_whitespace(self):
    1376          Element = self.etree.Element
    1377          SubElement = self.etree.SubElement
    1378          Comment = self.etree.Comment
    1379          tostring = self.etree.tostring
    1380
    1381          a = Element('a')
    1382          a.append(Comment(' foo  '))
    1383          self.assertEqual(a[0].text, ' foo  ')
    1384          self.assertEqual(
    1385              _bytes('<a><!-- foo  --></a>'),
    1386              tostring(a))
    1387
    1388 -    def test_comment_nonsense(self):
    1389          Comment = self.etree.Comment
    1390          c = Comment('foo')
    1391          self.assertEqual({}, c.attrib)
    1392          self.assertEqual([], list(c.keys()))
    1393          self.assertEqual([], list(c.items()))
    1394          self.assertEqual(None, c.get('hoi'))
    1395          self.assertEqual(0, len(c))
    1396          # should not iterate
    1397          for i in c:
    1398              pass
    1399
    1400 -    def test_pi(self):
    1401          # lxml.etree separates target and text
    1402          Element = self.etree.Element
    1403          SubElement = self.etree.SubElement
    1404          ProcessingInstruction = self.etree.ProcessingInstruction
    1405
    1406          a = Element('a')
    1407          a.append(ProcessingInstruction('foo', 'some more text'))
    1408          self.assertEqual(a[0].tag, ProcessingInstruction)
    1409          self.assertXML(_bytes("<a><?foo some more text?></a>"),
    1410                         a)
    1411
    1412 -    def test_processinginstruction(self):
    1413          # lxml.etree separates target and text
    1414          Element = self.etree.Element
    1415          SubElement = self.etree.SubElement
    1416          ProcessingInstruction = self.etree.PI
    1417
    1418          a = Element('a')
    1419          a.append(ProcessingInstruction('foo', 'some more text'))
    1420          self.assertEqual(a[0].tag, ProcessingInstruction)
    1421          self.assertXML(_bytes("<a><?foo some more text?></a>"),
    1422                         a)
    1423
    1424 -    def test_pi_nonsense(self):
    1425          ProcessingInstruction = self.etree.ProcessingInstruction
    1426          pi = ProcessingInstruction('foo')
    1427          self.assertEqual({}, pi.attrib)
    1428          self.assertEqual([], list(pi.keys()))
    1429          self.assertEqual([], list(pi.items()))
    1430          self.assertEqual(None, pi.get('hoi'))
    1431          self.assertEqual(0, len(pi))
    1432          # should not iterate
    1433          for i in pi:
    1434              pass
    1435
    1436 -    def test_setitem(self):
    1437          Element = self.etree.Element
    1438          SubElement = self.etree.SubElement
    1439
    1440          a = Element('a')
    1441          b = SubElement(a, 'b')
    1442          c = Element('c')
    1443          a[0] = c
    1444          self.assertEqual(
    1445              c,
    1446              a[0])
    1447          self.assertXML(_bytes('<a><c></c></a>'),
    1448                         a)
    1449          self.assertXML(_bytes('<b></b>'),
    1450                         b)
    1451
    1452 -    def test_setitem2(self):
    1453          Element = self.etree.Element
    1454          SubElement = self.etree.SubElement
    1455
    1456          a = Element('a')
    1457          for i in range(5):
    1458              b = SubElement(a, 'b%s' % i)
    1459              c = SubElement(b, 'c')
    1460          for i in range(5):
    1461              d = Element('d')
    1462              e = SubElement(d, 'e')
    1463              a[i] = d
    1464          self.assertXML(
    1465              _bytes('<a><d><e></e></d><d><e></e></d><d><e></e></d><d><e></e></d><d><e></e></d></a>'),
    1466              a)
    1467          self.assertXML(_bytes('<c></c>'),
    1468                         c)
    1469
    1470 -    def test_setitem_replace(self):
    1471          Element = self.etree.Element
    1472          SubElement = self.etree.SubElement
    1473
    1474          a = Element('a')
    1475          SubElement(a, 'b')
    1476          d = Element('d')
    1477          a[0] = d
    1478          self.assertXML(_bytes('<a><d></d></a>'), a)
    1479
    1480 -    def test_setitem_indexerror(self):
    1481          Element = self.etree.Element
    1482          SubElement = self.etree.SubElement
    1483
    1484          a = Element('a')
    1485          b = SubElement(a, 'b')
    1486
    1487          self.assertRaises(IndexError, operator.setitem, a, 1, Element('c'))
    1488
    1489 -    def test_setitem_tail(self):
    1490          Element = self.etree.Element
    1491          SubElement = self.etree.SubElement
    1492
    1493          a = Element('a')
    1494          b = SubElement(a, 'b')
    1495          b.tail = 'B2'
    1496          c = Element('c')
    1497          c.tail = 'C2'
    1498
    1499          a[0] = c
    1500          self.assertXML(
    1501              _bytes('<a><c></c>C2</a>'),
    1502              a)
    1503
    1504 -    def test_tag_write(self):
    1505          Element = self.etree.Element
    1506          SubElement = self.etree.SubElement
    1507
    1508          a = Element('a')
    1509          b = SubElement(a, 'b')
    1510
    1511          a.tag = 'c'
    1512
    1513          self.assertEqual(
    1514              'c',
    1515              a.tag)
    1516
    1517          self.assertXML(
    1518              _bytes('<c><b></b></c>'),
    1519              a)
    1520
    1521 -    def test_tag_reset_ns(self):
    1522          Element = self.etree.Element
    1523          SubElement = self.etree.SubElement
    1524          tostring = self.etree.tostring
    1525
    1526          a = Element('{a}a')
    1527          b1 = SubElement(a, '{a}b')
    1528          b2 = SubElement(a, '{b}b')
    1529
    1530          self.assertEqual('{a}b',  b1.tag)
    1531
    1532          b1.tag = 'c'
    1533
    1534          # can't use C14N here!
    1535          self.assertEqual('c', b1.tag)
    1536          self.assertEqual(_bytes('<c'), tostring(b1)[:2])
    1537          self.assertTrue(_bytes('<c') in tostring(a))
    1538
    1539 -    def test_tag_reset_root_ns(self):
    1540          Element = self.etree.Element
    1541          SubElement = self.etree.SubElement
    1542          tostring = self.etree.tostring
    1543
    1544          a = Element('{a}a')
    1545          b1 = SubElement(a, '{a}b')
    1546          b2 = SubElement(a, '{b}b')
    1547
    1548          a.tag = 'c'
    1549
    1550          self.assertEqual(
    1551              'c',
    1552              a.tag)
    1553
    1554          # can't use C14N here!
    1555          self.assertEqual('c',  a.tag)
    1556          self.assertEqual(_bytes('<c'), tostring(a)[:2])
    1557
    1558 -    def test_tag_str_subclass(self):
    1559          Element = self.etree.Element
    1560
    1561          class strTest(str):
    1562              pass
    1563
    1564          a = Element("a")
    1565          a.tag = strTest("TAG")
    1566          self.assertXML(_bytes('<TAG></TAG>'),
    1567                         a)
    1568
    1569 -    def test_delitem(self):
    1570          Element = self.etree.Element
    1571          SubElement = self.etree.SubElement
    1572
    1573          a = Element('a')
    1574          b = SubElement(a, 'b')
    1575          c = SubElement(a, 'c')
    1576          d = SubElement(a, 'd')
    1577
    1578          del a[1]
    1579          self.assertXML(
    1580              _bytes('<a><b></b><d></d></a>'),
    1581              a)
    1582
    1583          del a[0]
    1584          self.assertXML(
    1585              _bytes('<a><d></d></a>'),
    1586              a)
    1587
    1588          del a[0]
    1589          self.assertXML(
    1590              _bytes('<a></a>'),
    1591              a)
    1592          # move deleted element into other tree afterwards
    1593          other = Element('other')
    1594          other.append(c)
    1595          self.assertXML(
    1596              _bytes('<other><c></c></other>'),
    1597              other)
    1598
    1599 -    def test_del_insert(self):
    1600          Element = self.etree.Element
    1601          SubElement = self.etree.SubElement
    1602
    1603          a = Element('a')
    1604          b = SubElement(a, 'b')
    1605          bs = SubElement(b, 'bs')
    1606          c = SubElement(a, 'c')
    1607          cs = SubElement(c, 'cs')
    1608
    1609          el = a[0]
    1610          self.assertXML(
    1611              _bytes('<a><b><bs></bs></b><c><cs></cs></c></a>'),
    1612              a)
    1613          self.assertXML(_bytes('<b><bs></bs></b>'), b)
    1614          self.assertXML(_bytes('<c><cs></cs></c>'), c)
    1615
    1616          del a[0]
    1617          self.assertXML(
    1618              _bytes('<a><c><cs></cs></c></a>'),
    1619              a)
    1620          self.assertXML(_bytes('<b><bs></bs></b>'), b)
    1621          self.assertXML(_bytes('<c><cs></cs></c>'), c)
    1622
    1623          a.insert(0, el)
    1624          self.assertXML(
    1625              _bytes('<a><b><bs></bs></b><c><cs></cs></c></a>'),
    1626              a)
    1627          self.assertXML(_bytes('<b><bs></bs></b>'), b)
    1628          self.assertXML(_bytes('<c><cs></cs></c>'), c)
    1629
    1630 -    def test_del_setitem(self):
    1631          Element = self.etree.Element
    1632          SubElement = self.etree.SubElement
    1633
    1634          a = Element('a')
    1635          b = SubElement(a, 'b')
    1636          bs = SubElement(b, 'bs')
    1637          c = SubElement(a, 'c')
    1638          cs = SubElement(c, 'cs')
    1639
    1640          el = a[0]
    1641          del a[0]
    1642          a[0] = el
    1643          self.assertXML(
    1644              _bytes('<a><b><bs></bs></b></a>'),
    1645              a)
    1646          self.assertXML(_bytes('<b><bs></bs></b>'), b)
    1647          self.assertXML(_bytes('<c><cs></cs></c>'), c)
    1648
    1649 -    def test_del_setslice(self):
    1650          Element = self.etree.Element
    1651          SubElement = self.etree.SubElement
    1652
    1653          a = Element('a')
    1654          b = SubElement(a, 'b')
    1655          bs = SubElement(b, 'bs')
    1656          c = SubElement(a, 'c')
    1657          cs = SubElement(c, 'cs')
    1658
    1659          el = a[0]
    1660          del a[0]
    1661          a[0:0] = [el]
    1662          self.assertXML(
    1663              _bytes('<a><b><bs></bs></b><c><cs></cs></c></a>'),
    1664              a)
    1665          self.assertXML(_bytes('<b><bs></bs></b>'), b)
    1666          self.assertXML(_bytes('<c><cs></cs></c>'), c)
    1667
    1668 -    def test_replace_slice_tail(self):
    1669          XML = self.etree.XML
    1670          a = XML(_bytes('<a><b></b>B2<c></c>C2</a>'))
    1671          b, c = a
    1672
    1673          a[:] = []
    1674
    1675          self.assertEqual("B2", b.tail)
    1676          self.assertEqual("C2", c.tail)
    1677
    1678 -    def test_merge_namespaced_subtree_as_slice(self):
    1679          XML = self.etree.XML
    1680          root = XML(_bytes(
    1681              '<foo><bar xmlns:baz="http://huhu"><puh><baz:bump1 /><baz:bump2 /></puh></bar></foo>'))
    1682          root[:] = root.findall('.//puh') # delete bar from hierarchy
    1683
    1684          # previously, this lost a namespace declaration on bump2
    1685          result = self.etree.tostring(root)
    1686          foo = self.etree.fromstring(result)
    1687
    1688          self.assertEqual('puh', foo[0].tag)
    1689          self.assertEqual('{http://huhu}bump1', foo[0][0].tag)
    1690          self.assertEqual('{http://huhu}bump2', foo[0][1].tag)
    1691
    1692 -    def test_delitem_tail_dealloc(self):
    1693          ElementTree = self.etree.ElementTree
    1694          f = BytesIO('<a><b></b>B2<c></c>C2</a>')
    1695          doc = ElementTree(file=f)
    1696          a = doc.getroot()
    1697          del a[0]
    1698          self.assertXML(
    1699              _bytes('<a><c></c>C2</a>'),
    1700              a)
    1701
    1702 -    def test_delitem_tail(self):
    1703          ElementTree = self.etree.ElementTree
    1704          f = BytesIO('<a><b></b>B2<c></c>C2</a>')
    1705          doc = ElementTree(file=f)
    1706          a = doc.getroot()
    1707          b, c = a
    1708          del a[0]
    1709          self.assertXML(
    1710              _bytes('<a><c></c>C2</a>'),
    1711              a)
    1712          self.assertEqual("B2", b.tail)
    1713          self.assertEqual("C2", c.tail)
    1714
    1715 -    def test_clear(self):
    1716          Element = self.etree.Element
    1717
    1718          a = Element('a')
    1719          a.text = 'foo'
    1720          a.tail = 'bar'
    1721          a.set('hoi', 'dag')
    1722          a.clear()
    1723          self.assertEqual(None, a.text)
    1724          self.assertEqual(None, a.tail)
    1725          self.assertEqual(None, a.get('hoi'))
    1726          self.assertEqual('a', a.tag)
    1727
    1728 -    def test_clear_sub(self):
    1729          Element = self.etree.Element
    1730          SubElement = self.etree.SubElement
    1731
    1732          a = Element('a')
    1733          a.text = 'foo'
    1734          a.tail = 'bar'
    1735          a.set('hoi', 'dag')
    1736          b = SubElement(a, 'b')
    1737          c = SubElement(b, 'c')
    1738          a.clear()
    1739          self.assertEqual(None, a.text)
    1740          self.assertEqual(None, a.tail)
    1741          self.assertEqual(None, a.get('hoi'))
    1742          self.assertEqual('a', a.tag)
    1743          self.assertEqual(0, len(a))
    1744          self.assertXML(_bytes('<a></a>'),
    1745                         a)
    1746          self.assertXML(_bytes('<b><c></c></b>'),
    1747                         b)
    1748
    1749 -    def test_clear_tail(self):
    1750          ElementTree = self.etree.ElementTree
    1751          f = BytesIO('<a><b></b>B2<c></c>C2</a>')
    1752          doc = ElementTree(file=f)
    1753          a = doc.getroot()
    1754          a.clear()
    1755          self.assertXML(
    1756              _bytes('<a></a>'),
    1757              a)
    1758
    1759 -    def test_insert(self):
    1760          Element = self.etree.Element
    1761          SubElement = self.etree.SubElement
    1762
    1763          a = Element('a')
    1764          b = SubElement(a, 'b')
    1765          c = SubElement(a, 'c')
    1766          d = Element('d')
    1767          a.insert(0, d)
    1768
    1769          self.assertEqual(
    1770              d,
    1771              a[0])
    1772
    1773          self.assertXML(
    1774              _bytes('<a><d></d><b></b><c></c></a>'),
    1775              a)
    1776
    1777          e = Element('e')
    1778          a.insert(2, e)
    1779          self.assertEqual(
    1780              e,
    1781              a[2])
    1782          self.assertXML(
    1783              _bytes('<a><d></d><b></b><e></e><c></c></a>'),
    1784              a)
    1785
    1786 -    def test_insert_name_interning(self):
    1787          # See GH#268 / LP#1773749.
    1788          Element = self.etree.Element
    1789          SubElement = self.etree.SubElement
    1790
    1791          # Use unique names to make sure they are new in the tag name dict.
    1792          import uuid
    1793          names = dict((k, 'tag-' + str(uuid.uuid4())) for k in 'abcde')
    1794
    1795          a = Element(names['a'])
    1796          b = SubElement(a, names['b'])
    1797          c = SubElement(a, names['c'])
    1798          d = Element(names['d'])
    1799          a.insert(0, d)
    1800
    1801          self.assertEqual(
    1802              d,
    1803              a[0])
    1804
    1805          self.assertXML(
    1806              _bytes('<%(a)s><%(d)s></%(d)s><%(b)s></%(b)s><%(c)s></%(c)s></%(a)s>' % names),
    1807              a)
    1808
    1809          e = Element(names['e'])
    1810          a.insert(2, e)
    1811          self.assertEqual(
    1812              e,
    1813              a[2])
    1814          self.assertXML(
    1815              _bytes('<%(a)s><%(d)s></%(d)s><%(b)s></%(b)s><%(e)s></%(e)s><%(c)s></%(c)s></%(a)s>' % names),
    1816              a)
    1817
    1818 -    def test_insert_beyond_index(self):
    1819          Element = self.etree.Element
    1820          SubElement = self.etree.SubElement
    1821
    1822          a = Element('a')
    1823          b = SubElement(a, 'b')
    1824          c = Element('c')
    1825
    1826          a.insert(2, c)
    1827          self.assertEqual(
    1828              c,
    1829              a[1])
    1830          self.assertXML(
    1831              _bytes('<a><b></b><c></c></a>'),
    1832              a)
    1833
    1834 -    def test_insert_negative(self):
    1835          Element = self.etree.Element
    1836          SubElement = self.etree.SubElement
    1837
    1838          a = Element('a')
    1839          b = SubElement(a, 'b')
    1840          c = SubElement(a, 'c')
    1841
    1842          d = Element('d')
    1843          a.insert(-1, d)
    1844          self.assertEqual(
    1845              d,
    1846              a[-2])
    1847          self.assertXML(
    1848              _bytes('<a><b></b><d></d><c></c></a>'),
    1849              a)
    1850
    1851 -    def test_insert_tail(self):
    1852          Element = self.etree.Element
    1853          SubElement = self.etree.SubElement
    1854
    1855          a = Element('a')
    1856          b = SubElement(a, 'b')
    1857
    1858          c = Element('c')
    1859          c.tail = 'C2'
    1860
    1861          a.insert(0, c)
    1862          self.assertXML(
    1863              _bytes('<a><c></c>C2<b></b></a>'),
    1864              a)
    1865
    1866 -    def test_remove(self):
    1867          Element = self.etree.Element
    1868          SubElement = self.etree.SubElement
    1869
    1870          a = Element('a')
    1871          b = SubElement(a, 'b')
    1872          c = SubElement(a, 'c')
    1873
    1874          a.remove(b)
    1875          self.assertEqual(
    1876              c,
    1877              a[0])
    1878          self.assertXML(
    1879              _bytes('<a><c></c></a>'),
    1880              a)
    1881
    1882 -    def test_remove_ns(self):
    1883          Element = self.etree.Element
    1884          SubElement = self.etree.SubElement
    1885
    1886          a = Element('{http://test}a')
    1887          b = SubElement(a, '{http://test}b')
    1888          c = SubElement(a, '{http://test}c')
    1889
    1890          a.remove(b)
    1891          self.assertXML(
    1892              _bytes('<ns0:a xmlns:ns0="http://test"><ns0:c></ns0:c></ns0:a>'),
    1893              a)
    1894          self.assertXML(
    1895              _bytes('<ns0:b xmlns:ns0="http://test"></ns0:b>'),
    1896              b)
    1897
    1898 -    def test_remove_nonexisting(self):
    1899          Element = self.etree.Element
    1900          SubElement = self.etree.SubElement
    1901
    1902          a = Element('a')
    1903          b = SubElement(a, 'b')
    1904          c = SubElement(a, 'c')
    1905          d = Element('d')
    1906          self.assertRaises(
    1907              ValueError, a.remove, d)
    1908
    1909 -    def test_remove_tail(self):
    1910          Element = self.etree.Element
    1911          SubElement = self.etree.SubElement
    1912
    1913          a = Element('a')
    1914          b = SubElement(a, 'b')
    1915          b.tail = 'b2'
    1916          a.remove(b)
    1917          self.assertXML(
    1918              _bytes('<a></a>'),
    1919              a)
    1920          self.assertEqual('b2', b.tail)
    1921
    1922 -    def test_remove_while_iterating(self):
    1923          # There is no guarantee that this "works", but it should
    1924          # remove at least one child and not crash.
    1925          Element = self.etree.Element
    1926          SubElement = self.etree.SubElement
    1927
    1928          a = Element('a')
    1929          SubElement(a, 'b')
    1930          SubElement(a, 'c')
    1931          SubElement(a, 'd')
    1932          for el in a:
    1933              a.remove(el)
    1934          self.assertLess(len(a), 3)
    1935
    1936 -    def test_getchildren(self):
    1937          Element = self.etree.Element
    1938          SubElement = self.etree.SubElement
    1939
    1940          a = Element('a')
    1941          b = SubElement(a, 'b')
    1942          c = SubElement(a, 'c')
    1943          d = SubElement(b, 'd')
    1944          e = SubElement(c, 'e')
    1945          self.assertXML(
    1946              _bytes('<a><b><d></d></b><c><e></e></c></a>'),
    1947              a)
    1948          self.assertEqual(
    1949              [b, c],
    1950              a.getchildren())
    1951          self.assertEqual(
    1952              [d],
    1953              b.getchildren())
    1954          self.assertEqual(
    1955              [],
    1956              d.getchildren())
    1957
    1958 -    def test_makeelement(self):
    1959          Element = self.etree.Element
    1960
    1961          a = Element('a')
    1962          b = a.makeelement('c', {'hoi':'dag'})
    1963          self.assertXML(
    1964              _bytes('<c hoi="dag"></c>'),
    1965              b)
    1966
    1967      required_versions_ET['test_iter'] = (1,3)
    1968 -    def test_iter(self):
    1969          Element = self.etree.Element
    1970          SubElement = self.etree.SubElement
    1971
    1972          a = Element('a')
    1973          b = SubElement(a, 'b')
    1974          c = SubElement(a, 'c')
    1975          d = SubElement(b, 'd')
    1976          e = SubElement(c, 'e')
    1977
    1978          self.assertEqual(
    1979              [a, b, d, c, e],
    1980              list(a.iter()))
    1981          self.assertEqual(
    1982              [d],
    1983              list(d.iter()))
    1984
    1985 -    def test_iter_remove_tail(self):
    1986          Element = self.etree.Element
    1987          SubElement = self.etree.SubElement
    1988
    1989          a = Element('a')
    1990          a.text = 'a'
    1991          a.tail = 'a1' * 100
    1992          b = SubElement(a, 'b')
    1993          b.text = 'b'
    1994          b.tail = 'b1' * 100
    1995          c = SubElement(a, 'c')
    1996          c.text = 'c'
    1997          c.tail = 'c1' * 100
    1998          d = SubElement(b, 'd')
    1999          d.text = 'd'
    2000          d.tail = 'd1' * 100
    2001          e = SubElement(c, 'e')
    2002          e.text = 'e'
    2003          e.tail = 'e1' * 100
    2004
    2005          for el in a.iter():
    2006              el.tail = None
    2007          el = None
    2008
    2009          self.assertEqual(
    2010              [None] * 5,
    2011              [el.tail for el in a.iter()])
    2012
    2013 -    def test_getiterator(self):
    2014          Element = self.etree.Element
    2015          SubElement = self.etree.SubElement
    2016
    2017          a = Element('a')
    2018          b = SubElement(a, 'b')
    2019          c = SubElement(a, 'c')
    2020          d = SubElement(b, 'd')
    2021          e = SubElement(c, 'e')
    2022
    2023          self.assertEqual(
    2024              [a, b, d, c, e],
    2025              list(a.getiterator()))
    2026          self.assertEqual(
    2027              [d],
    2028              list(d.getiterator()))
    2029
    2030 -    def test_getiterator_empty(self):
    2031          Element = self.etree.Element
    2032          SubElement = self.etree.SubElement
    2033
    2034          a = Element('a')
    2035          b = SubElement(a, 'b')
    2036          c = SubElement(a, 'c')
    2037          d = SubElement(b, 'd')
    2038          e = SubElement(c, 'e')
    2039
    2040          self.assertEqual(
    2041              [],
    2042              list(a.getiterator('none')))
    2043          self.assertEqual(
    2044              [],
    2045              list(e.getiterator('none')))
    2046          self.assertEqual(
    2047              [e],
    2048              list(e.getiterator()))
    2049
    2050 -    def test_getiterator_filter(self):
    2051          Element = self.etree.Element
    2052          SubElement = self.etree.SubElement
    2053
    2054          a = Element('a')
    2055          b = SubElement(a, 'b')
    2056          c = SubElement(a, 'c')
    2057          d = SubElement(b, 'd')
    2058          e = SubElement(c, 'e')
    2059
    2060          self.assertEqual(
    2061              [a],
    2062              list(a.getiterator('a')))
    2063          a2 = SubElement(e, 'a')
    2064          self.assertEqual(
    2065              [a, a2],
    2066              list(a.getiterator('a')))
    2067          self.assertEqual(
    2068              [a2],
    2069              list(c.getiterator('a')))
    2070
    2071 -    def test_getiterator_filter_all(self):
    2072          Element = self.etree.Element
    2073          SubElement = self.etree.SubElement
    2074
    2075          a = Element('a')
    2076          b = SubElement(a, 'b')
    2077          c = SubElement(a, 'c')
    2078          d = SubElement(b, 'd')
    2079          e = SubElement(c, 'e')
    2080
    2081          self.assertEqual(
    2082              [a, b, d, c, e],
    2083              list(a.getiterator('*')))
    2084
    2085 -    def test_getiterator_filter_comment(self):
    2086          Element = self.etree.Element
    2087          Comment = self.etree.Comment
    2088          SubElement = self.etree.SubElement
    2089
    2090          a = Element('a')
    2091          b = SubElement(a, 'b')
    2092          comment_b = Comment("TEST-b")
    2093          b.append(comment_b)
    2094
    2095          self.assertEqual(
    2096              [comment_b],
    2097              list(a.getiterator(Comment)))
    2098
    2099          comment_a = Comment("TEST-a")
    2100          a.append(comment_a)
    2101
    2102          self.assertEqual(
    2103              [comment_b, comment_a],
    2104              list(a.getiterator(Comment)))
    2105
    2106          self.assertEqual(
    2107              [comment_b],
    2108              list(b.getiterator(Comment)))
    2109
    2110 -    def test_getiterator_filter_pi(self):
    2111          Element = self.etree.Element
    2112          PI = self.etree.ProcessingInstruction
    2113          SubElement = self.etree.SubElement
    2114
    2115          a = Element('a')
    2116          b = SubElement(a, 'b')
    2117          pi_b = PI("TEST-b")
    2118          b.append(pi_b)
    2119
    2120          self.assertEqual(
    2121              [pi_b],
    2122              list(a.getiterator(PI)))
    2123
    2124          pi_a = PI("TEST-a")
    2125          a.append(pi_a)
    2126
    2127          self.assertEqual(
    2128              [pi_b, pi_a],
    2129              list(a.getiterator(PI)))
    2130
    2131          self.assertEqual(
    2132              [pi_b],
    2133              list(b.getiterator(PI)))
    2134
    2135 -    def test_getiterator_with_text(self):
    2136          Element = self.etree.Element
    2137          SubElement = self.etree.SubElement
    2138
    2139          a = Element('a')
    2140          a.text = 'a'
    2141          b = SubElement(a, 'b')
    2142          b.text = 'b'
    2143          b.tail = 'b1'
    2144          c = SubElement(a, 'c')
    2145          c.text = 'c'
    2146          c.tail = 'c1'
    2147          d = SubElement(b, 'd')
    2148          d.text = 'd'
    2149          d.tail = 'd1'
    2150          e = SubElement(c, 'e')
    2151          e.text = 'e'
    2152          e.tail = 'e1'
    2153
    2154          self.assertEqual(
    2155              [a, b, d, c, e],
    2156              list(a.getiterator()))
    2157          #self.assertEqual(
    2158          #    [d],
    2159          #    list(d.getiterator()))
    2160
    2161 -    def test_getiterator_filter_with_text(self):
    2162          Element = self.etree.Element
    2163          SubElement = self.etree.SubElement
    2164
    2165          a = Element('a')
    2166          a.text = 'a'
    2167          b = SubElement(a, 'b')
    2168          b.text = 'b'
    2169          b.tail = 'b1'
    2170          c = SubElement(a, 'c')
    2171          c.text = 'c'
    2172          c.tail = 'c1'
    2173          d = SubElement(b, 'd')
    2174          d.text = 'd'
    2175          d.tail = 'd1'
    2176          e = SubElement(c, 'e')
    2177          e.text = 'e'
    2178          e.tail = 'e1'
    2179
    2180          self.assertEqual(
    2181              [a],
    2182              list(a.getiterator('a')))
    2183          a2 = SubElement(e, 'a')
    2184          self.assertEqual(
    2185              [a, a2],
    2186              list(a.getiterator('a')))
    2187          self.assertEqual(
    2188              [a2],
    2189              list(e.getiterator('a')))
    2190
    2191 -    def test_getslice(self):
    2192          Element = self.etree.Element
    2193          SubElement = self.etree.SubElement
    2194
    2195          a = Element('a')
    2196          b = SubElement(a, 'b')
    2197          c = SubElement(a, 'c')
    2198          d = SubElement(a, 'd')
    2199
    2200          self.assertEqual(
    2201              [b, c],
    2202              a[0:2])
    2203          self.assertEqual(
    2204              [b, c, d],
    2205              a[:])
    2206          self.assertEqual(
    2207              [b, c, d],
    2208              a[:10])
    2209          self.assertEqual(
    2210              [b],
    2211              a[0:1])
    2212          self.assertEqual(
    2213              [],
    2214              a[10:12])
    2215
    2216 -    def test_getslice_negative(self):
    2217          Element = self.etree.Element
    2218          SubElement = self.etree.SubElement
    2219
    2220          a = Element('a')
    2221          b = SubElement(a, 'b')
    2222          c = SubElement(a, 'c')
    2223          d = SubElement(a, 'd')
    2224
    2225          self.assertEqual(
    2226              [d],
    2227              a[-1:])
    2228          self.assertEqual(
    2229              [c, d],
    2230              a[-2:])
    2231          self.assertEqual(
    2232              [c],
    2233              a[-2:-1])
    2234          self.assertEqual(
    2235              [b, c],
    2236              a[-3:-1])
    2237          self.assertEqual(
    2238              [b, c],
    2239              a[-3:2])
    2240
    2241 -    def test_getslice_step(self):
    2242          Element = self.etree.Element
    2243          SubElement = self.etree.SubElement
    2244
    2245          a = Element('a')
    2246          b = SubElement(a, 'b')
    2247          c = SubElement(a, 'c')
    2248          d = SubElement(a, 'd')
    2249          e = SubElement(a, 'e')
    2250
    2251          self.assertEqual(
    2252              [e,d,c,b],
    2253              a[::-1])
    2254          self.assertEqual(
    2255              [b,d],
    2256              a[::2])
    2257          self.assertEqual(
    2258              [e,c],
    2259              a[::-2])
    2260          self.assertEqual(
    2261              [d,c],
    2262              a[-2:0:-1])
    2263          self.assertEqual(
    2264              [e],
    2265              a[:1:-2])
    2266
    2267 -    def test_getslice_text(self):
    2268          ElementTree = self.etree.ElementTree
    2269
    2270          f = BytesIO('<a><b>B</b>B1<c>C</c>C1</a>')
    2271          doc = ElementTree(file=f)
    2272          a = doc.getroot()
    2273          b = a[0]
    2274          c = a[1]
    2275          self.assertEqual(
    2276              [b, c],
    2277              a[:])
    2278          self.assertEqual(
    2279              [b],
    2280              a[0:1])
    2281          self.assertEqual(
    2282              [c],
    2283              a[1:])
    2284
    2285 -    def test_comment_getitem_getslice(self):
    2286          Element = self.etree.Element
    2287          Comment = self.etree.Comment
    2288          SubElement = self.etree.SubElement
    2289
    2290          a = Element('a')
    2291          b = SubElement(a, 'b')
    2292          foo = Comment('foo')
    2293          a.append(foo)
    2294          c = SubElement(a, 'c')
    2295          self.assertEqual(
    2296              [b, foo, c],
    2297              a[:])
    2298          self.assertEqual(
    2299              foo,
    2300              a[1])
    2301          a[1] = new = Element('new')
    2302          self.assertEqual(
    2303              new,
    2304              a[1])
    2305          self.assertXML(
    2306              _bytes('<a><b></b><new></new><c></c></a>'),
    2307              a)
    2308
    2309 -    def test_delslice(self):
    2310          Element = self.etree.Element
    2311          SubElement = self.etree.SubElement
    2312
    2313          a = Element('a')
    2314          b = SubElement(a, 'b')
    2315          c = SubElement(a, 'c')
    2316          d = SubElement(a, 'd')
    2317          e = SubElement(a, 'e')
    2318
    2319          del a[1:3]
    2320          self.assertEqual(
    2321              [b, e],
    2322              list(a))
    2323
    2324 -    def test_delslice_negative1(self):
    2325          Element = self.etree.Element
    2326          SubElement = self.etree.SubElement
    2327
    2328          a = Element('a')
    2329          b = SubElement(a, 'b')
    2330          c = SubElement(a, 'c')
    2331          d = SubElement(a, 'd')
    2332          e = SubElement(a, 'e')
    2333
    2334          del a[1:-1]
    2335          self.assertEqual(
    2336              [b, e],
    2337              list(a))
    2338
    2339 -    def test_delslice_negative2(self):
    2340          Element = self.etree.Element
    2341          SubElement = self.etree.SubElement
    2342
    2343          a = Element('a')
    2344          b = SubElement(a, 'b')
    2345          c = SubElement(a, 'c')
    2346          d = SubElement(a, 'd')
    2347          e = SubElement(a, 'e')
    2348
    2349          del a[-3:-1]
    2350          self.assertEqual(
    2351              [b, e],
    2352              list(a))
    2353
    2354 -    def test_delslice_step(self):
    2355          Element = self.etree.Element
    2356          SubElement = self.etree.SubElement
    2357
    2358          a = Element('a')
    2359          b = SubElement(a, 'b')
    2360          c = SubElement(a, 'c')
    2361          d = SubElement(a, 'd')
    2362          e = SubElement(a, 'e')
    2363
    2364          del a[1::2]
    2365          self.assertEqual(
    2366              [b, d],
    2367              list(a))
    2368
    2369 -    def test_delslice_step_negative(self):
    2370          Element = self.etree.Element
    2371          SubElement = self.etree.SubElement
    2372
    2373          a = Element('a')
    2374          b = SubElement(a, 'b')
    2375          c = SubElement(a, 'c')
    2376          d = SubElement(a, 'd')
    2377          e = SubElement(a, 'e')
    2378
    2379          del a[::-1]
    2380          self.assertEqual(
    2381              [],
    2382              list(a))
    2383
    2384 -    def test_delslice_step_negative2(self):
    2385          Element = self.etree.Element
    2386          SubElement = self.etree.SubElement
    2387
    2388          a = Element('a')
    2389          b = SubElement(a, 'b')
    2390          c = SubElement(a, 'c')
    2391          d = SubElement(a, 'd')
    2392          e = SubElement(a, 'e')
    2393
    2394          del a[::-2]
    2395          self.assertEqual(
    2396              [b, d],
    2397              list(a))
    2398
    2399 -    def test_delslice_child_tail_dealloc(self):
    2400          ElementTree = self.etree.ElementTree
    2401          f = BytesIO('<a><b></b>B2<c></c>C2<d></d>D2<e></e>E2</a>')
    2402          doc = ElementTree(file=f)
    2403          a = doc.getroot()
    2404          del a[1:3]
    2405          self.assertXML(
    2406              _bytes('<a><b></b>B2<e></e>E2</a>'),
    2407              a)
    2408
    2409 -    def test_delslice_child_tail(self):
    2410          ElementTree = self.etree.ElementTree
    2411          f = BytesIO('<a><b></b>B2<c></c>C2<d></d>D2<e></e>E2</a>')
    2412          doc = ElementTree(file=f)
    2413          a = doc.getroot()
    2414          b, c, d, e = a
    2415          del a[1:3]
    2416          self.assertXML(
    2417              _bytes('<a><b></b>B2<e></e>E2</a>'),
    2418              a)
    2419          self.assertEqual("B2", b.tail)
    2420          self.assertEqual("C2", c.tail)
    2421          self.assertEqual("D2", d.tail)
    2422          self.assertEqual("E2", e.tail)
    2423
    2424 -    def test_delslice_tail(self):
    2425          XML = self.etree.XML
    2426          a = XML(_bytes('<a><b></b>B2<c></c>C2</a>'))
    2427          b, c = a
    2428
    2429          del a[:]
    2430
    2431          self.assertEqual("B2", b.tail)
    2432          self.assertEqual("C2", c.tail)
    2433
    2434 -    def test_delslice_memory(self):
    2435          # this could trigger a crash
    2436          Element = self.etree.Element
    2437          SubElement = self.etree.SubElement
    2438          a = Element('a')
    2439          b = SubElement(a, 'b')
    2440          c = SubElement(b, 'c')
    2441          del b # no more reference to b
    2442          del a[:]
    2443          self.assertEqual('c', c.tag)
    2444
    2445 -    def test_setslice(self):
    2446          Element = self.etree.Element
    2447          SubElement = self.etree.SubElement
    2448
    2449          a = Element('a')
    2450          b = SubElement(a, 'b')
    2451          c = SubElement(a, 'c')
    2452          d = SubElement(a, 'd')
    2453
    2454          e = Element('e')
    2455          f = Element('f')
    2456          g = Element('g')
    2457
    2458          s = [e, f, g]
    2459          a[1:2] = s
    2460          self.assertEqual(
    2461              [b, e, f, g, d],
    2462              list(a))
    2463
    2464 -    def test_setslice_all(self):
    2465          Element = self.etree.Element
    2466          SubElement = self.etree.SubElement
    2467
    2468          a = Element('a')
    2469          b = SubElement(a, 'b')
    2470          c = SubElement(a, 'c')
    2471
    2472          e = Element('e')
    2473          f = Element('f')
    2474          g = Element('g')
    2475
    2476          s = [e, f, g]
    2477          a[:] = s
    2478          self.assertEqual(
    2479              [e, f, g],
    2480              list(a))
    2481
    2482 -    def test_setslice_all_empty(self):
    2483          Element = self.etree.Element
    2484          SubElement = self.etree.SubElement
    2485
    2486          a = Element('a')
    2487
    2488          e = Element('e')
    2489          f = Element('f')
    2490          g = Element('g')
    2491
    2492          s = [e, f, g]
    2493          a[:] = s
    2494          self.assertEqual(
    2495              [e, f, g],
    2496              list(a))
    2497
    2498 -    def test_setslice_all_replace(self):
    2499          Element = self.etree.Element
    2500          SubElement = self.etree.SubElement
    2501
    2502          a = Element('a')
    2503          b = SubElement(a, 'b')
    2504          c = SubElement(a, 'c')
    2505          d = SubElement(a, 'd')
    2506
    2507          s = [b, c, d]
    2508          a[:] = s
    2509          self.assertEqual(
    2510              [b, c, d],
    2511              list(a))
    2512
    2513 -    def test_setslice_all_replace_reversed(self):
    2514          Element = self.etree.Element
    2515          SubElement = self.etree.SubElement
    2516
    2517          a = Element('a')
    2518          b = SubElement(a, 'b')
    2519          c = SubElement(a, 'c')
    2520          d = SubElement(a, 'd')
    2521
    2522          s = [d, c, b]
    2523          a[:] = s
    2524          self.assertEqual(
    2525              [d, c, b],
    2526              list(a))
    2527
    2528 -    def test_setslice_all_replace_reversed_ns1(self):
    2529          Element = self.etree.Element
    2530          SubElement = self.etree.SubElement
    2531
    2532          a = Element('{ns}a')
    2533          b = SubElement(a, '{ns}b', {'{ns1}a1': 'test'})
    2534          c = SubElement(a, '{ns}c', {'{ns2}a2': 'test'})
    2535          d = SubElement(a, '{ns}d', {'{ns3}a3': 'test'})
    2536
    2537          s = [d, c, b]
    2538          a[:] = s
    2539          self.assertEqual(
    2540              [d, c, b],
    2541              list(a))
    2542          self.assertEqual(
    2543              ['{ns}d', '{ns}c', '{ns}b'],
    2544              [ child.tag for child in a ])
    2545
    2546          self.assertEqual(
    2547              [['{ns3}a3'], ['{ns2}a2'], ['{ns1}a1']],
    2548              [ list(child.attrib.keys()) for child in a ])
    2549
    2550 -    def test_setslice_all_replace_reversed_ns2(self):
    2551          Element = self.etree.Element
    2552          SubElement = self.etree.SubElement
    2553
    2554          a = Element('{ns}a')
    2555          b = SubElement(a, '{ns1}b', {'{ns}a1': 'test'})
    2556          c = SubElement(a, '{ns2}c', {'{ns}a2': 'test'})
    2557          d = SubElement(a, '{ns3}d', {'{ns}a3': 'test'})
    2558
    2559          s = [d, c, b]
    2560          a[:] = s
    2561          self.assertEqual(
    2562              [d, c, b],
    2563              list(a))
    2564          self.assertEqual(
    2565              ['{ns3}d', '{ns2}c', '{ns1}b'],
    2566              [ child.tag for child in a ])
    2567
    2568          self.assertEqual(
    2569              [['{ns}a3'], ['{ns}a2'], ['{ns}a1']],
    2570              [ list(child.attrib.keys()) for child in a ])
    2571
    2572 -    def test_setslice_end(self):
    2573          Element = self.etree.Element
    2574          SubElement = self.etree.SubElement
    2575
    2576          a = Element('a')
    2577          b = SubElement(a, 'b')
    2578          c = SubElement(a, 'c')
    2579
    2580          e = Element('e')
    2581          f = Element('f')
    2582          g = Element('g')
    2583          h = Element('h')
    2584
    2585          s = [e, f]
    2586          a[99:] = s
    2587          self.assertEqual(
    2588              [b, c, e, f],
    2589              list(a))
    2590
    2591          s = [g, h]
    2592          a[:0] = s
    2593          self.assertEqual(
    2594              [g, h, b, c, e, f],
    2595              list(a))
    2596
    2597 -    def test_setslice_end_exact(self):
    2598          Element = self.etree.Element
    2599          SubElement = self.etree.SubElement
    2600
    2601          a = Element('a')
    2602          b = SubElement(a, 'b')
    2603          c = SubElement(a, 'c')
    2604          d = SubElement(a, 'd')
    2605
    2606          e = Element('e')
    2607          f = Element('f')
    2608          g = Element('g')
    2609
    2610          s = [e, f, g]
    2611          a[3:] = s
    2612          self.assertEqual(
    2613              [b, c, d, e, f, g],
    2614              list(a))
    2615
    2616 -    def test_setslice_single(self):
    2617          Element = self.etree.Element
    2618          SubElement = self.etree.SubElement
    2619
    2620          a = Element('a')
    2621          b = SubElement(a, 'b')
    2622          c = SubElement(a, 'c')
    2623
    2624          e = Element('e')
    2625          f = Element('f')
    2626
    2627          s = [e]
    2628          a[0:1] = s
    2629          self.assertEqual(
    2630              [e, c],
    2631              list(a))
    2632
    2633          s = [f]
    2634          a[1:2] = s
    2635          self.assertEqual(
    2636              [e, f],
    2637              list(a))
    2638
    2639 -    def test_setslice_tail(self):
    2640          ElementTree = self.etree.ElementTree
    2641          Element = self.etree.Element
    2642          f = BytesIO('<a><b></b>B2<c></c>C2<d></d>D2<e></e>E2</a>')
    2643          doc = ElementTree(file=f)
    2644          a = doc.getroot()
    2645          x = Element('x')
    2646          y = Element('y')
    2647          z = Element('z')
    2648          x.tail = 'X2'
    2649          y.tail = 'Y2'
    2650          z.tail = 'Z2'
    2651          a[1:3] = [x, y, z]
    2652          self.assertXML(
    2653              _bytes('<a><b></b>B2<x></x>X2<y></y>Y2<z></z>Z2<e></e>E2</a>'),
    2654              a)
    2655
    2656 -    def test_setslice_negative(self):
    2657          Element = self.etree.Element
    2658          SubElement = self.etree.SubElement
    2659
    2660          a = Element('a')
    2661          b = SubElement(a, 'b')
    2662          c = SubElement(a, 'c')
    2663          d = SubElement(a, 'd')
    2664
    2665          x = Element('x')
    2666          y = Element('y')
    2667
    2668          a[1:-1] = [x, y]
    2669          self.assertEqual(
    2670              [b, x, y, d],
    2671              list(a))
    2672
    2673 -    def test_setslice_negative2(self):
    2674          Element = self.etree.Element
    2675          SubElement = self.etree.SubElement
    2676
    2677          a = Element('a')
    2678          b = SubElement(a, 'b')
    2679          c = SubElement(a, 'c')
    2680          d = SubElement(a, 'd')
    2681
    2682          x = Element('x')
    2683          y = Element('y')
    2684
    2685          a[1:-2] = [x, y]
    2686          self.assertEqual(
    2687              [b, x, y, c, d],
    2688              list(a))
    2689
    2690 -    def test_setslice_empty(self):
    2691          Element = self.etree.Element
    2692
    2693          a = Element('a')
    2694
    2695          b = Element('b')
    2696          c = Element('c')
    2697
    2698          a[:] = [b, c]
    2699          self.assertEqual(
    2700              [b, c],
    2701              list(a))
    2702
    2703 -    def test_tail_elementtree_root(self):
    2704          Element = self.etree.Element
    2705          ElementTree = self.etree.ElementTree
    2706
    2707          a = Element('a')
    2708          a.tail = 'A2'
    2709          t = ElementTree(element=a)
    2710          self.assertEqual('A2',
    2711                            a.tail)
    2712
    2713 -    def test_elementtree_getiterator(self):
    2714          Element = self.etree.Element
    2715          SubElement = self.etree.SubElement
    2716          ElementTree = self.etree.ElementTree
    2717
    2718          a = Element('a')
    2719          b = SubElement(a, 'b')
    2720          c = SubElement(a, 'c')
    2721          d = SubElement(b, 'd')
    2722          e = SubElement(c, 'e')
    2723          t = ElementTree(element=a)
    2724
    2725          self.assertEqual(
    2726              [a, b, d, c, e],
    2727              list(t.getiterator()))
    2728
    2729 -    def test_elementtree_getiterator_filter(self):
    2730          Element = self.etree.Element
    2731          SubElement = self.etree.SubElement
    2732          ElementTree = self.etree.ElementTree
    2733          a = Element('a')
    2734          b = SubElement(a, 'b')
    2735          c = SubElement(a, 'c')
    2736          d = SubElement(b, 'd')
    2737          e = SubElement(c, 'e')
    2738          t = ElementTree(element=a)
    2739
    2740          self.assertEqual(
    2741              [a],
    2742              list(t.getiterator('a')))
    2743          a2 = SubElement(e, 'a')
    2744          self.assertEqual(
    2745              [a, a2],
    2746              list(t.getiterator('a')))
    2747
    2748 -    def test_ns_access(self):
    2749          ElementTree = self.etree.ElementTree
    2750          ns = 'http://xml.infrae.com/1'
    2751          f = BytesIO('<x:a xmlns:x="%s"><x:b></x:b></x:a>' % ns)
    2752          t = ElementTree(file=f)
    2753          a = t.getroot()
    2754          self.assertEqual('{%s}a' % ns,
    2755                            a.tag)
    2756          self.assertEqual('{%s}b' % ns,
    2757                            a[0].tag)
    2758
    2759 -    def test_ns_access2(self):
    2760          ElementTree = self.etree.ElementTree
    2761          ns = 'http://xml.infrae.com/1'
    2762          ns2 = 'http://xml.infrae.com/2'
    2763          f = BytesIO('<x:a xmlns:x="%s" xmlns:y="%s"><x:b></x:b><y:b></y:b></x:a>' % (ns, ns2))
    2764          t = ElementTree(file=f)
    2765          a = t.getroot()
    2766          self.assertEqual('{%s}a' % ns,
    2767                            a.tag)
    2768          self.assertEqual('{%s}b' % ns,
    2769                            a[0].tag)
    2770          self.assertEqual('{%s}b' % ns2,
    2771                            a[1].tag)
    2772
    2773 -    def test_ns_setting(self):
    2774          Element = self.etree.Element
    2775          SubElement = self.etree.SubElement
    2776          ns = 'http://xml.infrae.com/1'
    2777          ns2 = 'http://xml.infrae.com/2'
    2778          a = Element('{%s}a' % ns)
    2779          b = SubElement(a, '{%s}b' % ns2)
    2780          c = SubElement(a, '{%s}c' % ns)
    2781          self.assertEqual('{%s}a' % ns,
    2782                            a.tag)
    2783          self.assertEqual('{%s}b' % ns2,
    2784                            b.tag)
    2785          self.assertEqual('{%s}c' % ns,
    2786                            c.tag)
    2787          self.assertEqual('{%s}a' % ns,
    2788                            a.tag)
    2789          self.assertEqual('{%s}b' % ns2,
    2790                            b.tag)
    2791          self.assertEqual('{%s}c' % ns,
    2792                            c.tag)
    2793
    2794 -    def test_ns_tag_parse(self):
    2795          Element = self.etree.Element
    2796          SubElement = self.etree.SubElement
    2797          ElementTree = self.etree.ElementTree
    2798
    2799          ns = 'http://xml.infrae.com/1'
    2800          ns2 = 'http://xml.infrae.com/2'
    2801          f = BytesIO('<a xmlns="%s" xmlns:x="%s"><x:b></x:b><b></b></a>' % (ns, ns2))
    2802          t = ElementTree(file=f)
    2803
    2804          a = t.getroot()
    2805          self.assertEqual('{%s}a' % ns,
    2806                            a.tag)
    2807          self.assertEqual('{%s}b' % ns2,
    2808                            a[0].tag)
    2809          self.assertEqual('{%s}b' % ns,
    2810                            a[1].tag)
    2811
    2812 -    def test_ns_attr(self):
    2813          Element = self.etree.Element
    2814          ns = 'http://xml.infrae.com/1'
    2815          ns2 = 'http://xml.infrae.com/2'
    2816          a = Element('a')
    2817          a.set('{%s}foo' % ns, 'Foo')
    2818          a.set('{%s}bar' % ns2, 'Bar')
    2819          self.assertEqual(
    2820              'Foo',
    2821              a.get('{%s}foo' % ns))
    2822          self.assertEqual(
    2823              'Bar',
    2824              a.get('{%s}bar' % ns2))
    2825          try:
    2826              self.assertXML(
    2827                  _bytes('<a xmlns:ns0="%s" xmlns:ns1="%s" ns0:foo="Foo" ns1:bar="Bar"></a>' % (ns, ns2)),
    2828                  a)
    2829          except AssertionError:
    2830              self.assertXML(
    2831                  _bytes('<a xmlns:ns0="%s" xmlns:ns1="%s" ns1:foo="Foo" ns0:bar="Bar"></a>' % (ns2, ns)),
    2832                  a)
    2833
    2834 -    def test_ns_move(self):
    2835          Element = self.etree.Element
    2836          one = self.etree.fromstring(
    2837              _bytes('<foo><bar xmlns:ns="http://a.b.c"><ns:baz/></bar></foo>'))
    2838          baz = one[0][0]
    2839
    2840          two = Element('root')
    2841          two.append(baz)
    2842          # removing the originating document could cause a crash/error before
    2843          # as namespace is not moved along with it
    2844          del one, baz
    2845          self.assertEqual('{http://a.b.c}baz', two[0].tag)
    2846
    2847 -    def test_ns_decl_tostring(self):
    2848          tostring = self.etree.tostring
    2849          root = self.etree.XML(
    2850              _bytes('<foo><bar xmlns:ns="http://a.b.c"><ns:baz/></bar></foo>'))
    2851          baz = root[0][0]
    2852
    2853          nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"),
    2854                              tostring(baz))
    2855          self.assertEqual([_bytes("http://a.b.c")], nsdecl)
    2856
    2857 -    def test_ns_decl_tostring_default(self):
    2858          tostring = self.etree.tostring
    2859          root = self.etree.XML(
    2860              _bytes('<foo><bar xmlns="http://a.b.c"><baz/></bar></foo>'))
    2861          baz = root[0][0]
    2862
    2863          nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"),
    2864                              tostring(baz))
    2865          self.assertEqual([_bytes("http://a.b.c")], nsdecl)
    2866
    2867 -    def test_ns_decl_tostring_root(self):
    2868          tostring = self.etree.tostring
    2869          root = self.etree.XML(
    2870              _bytes('<foo xmlns:ns="http://a.b.c"><bar><ns:baz/></bar></foo>'))
    2871          baz = root[0][0]
    2872
    2873          nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"),
    2874                              tostring(baz))
    2875
    2876          self.assertEqual([_bytes("http://a.b.c")], nsdecl)
    2877
    2878 -    def test_ns_decl_tostring_element(self):
    2879          Element = self.etree.Element
    2880          SubElement = self.etree.SubElement
    2881
    2882          root = Element("foo")
    2883          bar = SubElement(root, "{http://a.b.c}bar")
    2884          baz = SubElement(bar, "{http://a.b.c}baz")
    2885
    2886          nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"),
    2887                              self.etree.tostring(baz))
    2888
    2889          self.assertEqual([_bytes("http://a.b.c")], nsdecl)
    2890
    2891 -    def test_attribute_xmlns_move(self):
    2892          Element = self.etree.Element
    2893
    2894          root = Element('element')
    2895
    2896          subelement = Element('subelement',
    2897                               {"{http://www.w3.org/XML/1998/namespace}id": "foo"})
    2898          self.assertEqual(1, len(subelement.attrib))
    2899          self.assertEqual(
    2900              "foo",
    2901              subelement.get("{http://www.w3.org/XML/1998/namespace}id"))
    2902
    2903          root.append(subelement)
    2904          self.assertEqual(1, len(subelement.attrib))
    2905          self.assertEqual(
    2906              list({"{http://www.w3.org/XML/1998/namespace}id" : "foo"}.items()),
    2907              list(subelement.attrib.items()))
    2908          self.assertEqual(
    2909              "foo",
    2910              subelement.get("{http://www.w3.org/XML/1998/namespace}id"))
    2911
    2912 -    def test_namespaces_after_serialize(self):
    2913          parse = self.etree.parse
    2914          tostring = self.etree.tostring
    2915
    2916          ns_href = "http://a.b.c"
    2917          one = parse(
    2918              BytesIO('<foo><bar xmlns:ns="%s"><ns:baz/></bar></foo>' % ns_href))
    2919          baz = one.getroot()[0][0]
    2920
    2921          parsed = parse(BytesIO( tostring(baz) )).getroot()
    2922          self.assertEqual('{%s}baz' % ns_href, parsed.tag)
    2923
    2924 -    def test_attribute_namespace_roundtrip(self):
    2925          fromstring = self.etree.fromstring
    2926          tostring = self.etree.tostring
    2927
    2928          ns_href = "http://a.b.c"
    2929          xml = _bytes('<root xmlns="%s" xmlns:x="%s"><el x:a="test" /></root>' % (
    2930                  ns_href,ns_href))
    2931          root = fromstring(xml)
    2932          self.assertEqual('test', root[0].get('{%s}a' % ns_href))
    2933
    2934          xml2 = tostring(root)
    2935          self.assertTrue(_bytes(':a=') in xml2, xml2)
    2936
    2937          root2 = fromstring(xml2)
    2938          self.assertEqual('test', root2[0].get('{%s}a' % ns_href))
    2939
    2940 -    def test_attribute_namespace_roundtrip_replaced(self):
    2941          fromstring = self.etree.fromstring
    2942          tostring = self.etree.tostring
    2943
    2944          ns_href = "http://a.b.c"
    2945          xml = _bytes('<root xmlns="%s" xmlns:x="%s"><el x:a="test" /></root>' % (
    2946                  ns_href,ns_href))
    2947          root = fromstring(xml)
    2948          self.assertEqual('test', root[0].get('{%s}a' % ns_href))
    2949
    2950          root[0].set('{%s}a' % ns_href, 'TEST')
    2951
    2952          xml2 = tostring(root)
    2953          self.assertTrue(_bytes(':a=') in xml2, xml2)
    2954
    2955          root2 = fromstring(xml2)
    2956          self.assertEqual('TEST', root2[0].get('{%s}a' % ns_href))
    2957
    2958      required_versions_ET['test_register_namespace'] = (1,3)
    2959 -    def test_register_namespace(self):
    2960          # ET 1.3+
    2961          Element = self.etree.Element
    2962          prefix = 'TESTPREFIX'
    2963          namespace = 'http://seriously.unknown/namespace/URI'
    2964
    2965          el = Element('{%s}test' % namespace)
    2966          self.assertEqual(_bytes('<ns0:test xmlns:ns0="%s"></ns0:test>' % namespace),
    2967              self._writeElement(el))
    2968
    2969          self.etree.register_namespace(prefix, namespace)
    2970          el = Element('{%s}test' % namespace)
    2971          self.assertEqual(_bytes('<%s:test xmlns:%s="%s"></%s:test>' % (
    2972              prefix, prefix, namespace, prefix)),
    2973              self._writeElement(el))
    2974
    2975          self.assertRaises(ValueError, self.etree.register_namespace, 'ns25', namespace)
    2976
    2977 -    def test_tostring(self):
    2978          tostring = self.etree.tostring
    2979          Element = self.etree.Element
    2980          SubElement = self.etree.SubElement
    2981
    2982          a = Element('a')
    2983          b = SubElement(a, 'b')
    2984          c = SubElement(a, 'c')
    2985
    2986          self.assertEqual(_bytes('<a><b></b><c></c></a>'),
    2987                            canonicalize(tostring(a)))
    2988
    2989 -    def test_tostring_element(self):
    2990          tostring = self.etree.tostring
    2991          Element = self.etree.Element
    2992          SubElement = self.etree.SubElement
    2993
    2994          a = Element('a')
    2995          b = SubElement(a, 'b')
    2996          c = SubElement(a, 'c')
    2997          d = SubElement(c, 'd')
    2998          self.assertEqual(_bytes('<b></b>'),
    2999                            canonicalize(tostring(b)))
    3000          self.assertEqual(_bytes('<c><d></d></c>'),
    3001                            canonicalize(tostring(c)))
    3002
    3003 -    def test_tostring_element_tail(self):
    3004          tostring = self.etree.tostring
    3005          Element = self.etree.Element
    3006          SubElement = self.etree.SubElement
    3007
    3008          a = Element('a')
    3009          b = SubElement(a, 'b')
    3010          c = SubElement(a, 'c')
    3011          d = SubElement(c, 'd')
    3012          b.tail = 'Foo'
    3013
    3014          self.assertTrue(tostring(b) == _bytes('<b/>Foo') or
    3015                       tostring(b) == _bytes('<b />Foo'))
    3016
    3017      required_versions_ET['test_tostring_method_html'] = (1,3)
    3018 -    def test_tostring_method_html(self):
    3019          tostring = self.etree.tostring
    3020          Element = self.etree.Element
    3021          SubElement = self.etree.SubElement
    3022
    3023          html = Element('html')
    3024          body = SubElement(html, 'body')
    3025          p = SubElement(body, 'p')
    3026          p.text = "html"
    3027          SubElement(p, 'br').tail = "test"
    3028
    3029          self.assertEqual(_bytes('<html><body><p>html<br>test</p></body></html>'),
    3030                            tostring(html, method="html"))
    3031
    3032      required_versions_ET['test_tostring_method_text'] = (1,3)
    3033 -    def test_tostring_method_text(self):
    3034          tostring = self.etree.tostring
    3035          Element = self.etree.Element
    3036          SubElement = self.etree.SubElement
    3037
    3038          a = Element('a')
    3039          a.text = "A"
    3040          a.tail = "tail"
    3041          b = SubElement(a, 'b')
    3042          b.text = "B"
    3043          b.tail = "TAIL"
    3044          c = SubElement(a, 'c')
    3045          c.text = "C"
    3046
    3047          self.assertEqual(_bytes('ABTAILCtail'),
    3048                            tostring(a, method="text"))
    3049
    3050 -    def test_iterparse(self):
    3051          iterparse = self.etree.iterparse
    3052          f = BytesIO('<a><b></b><c/></a>')
    3053
    3054          iterator = iterparse(f)
    3055          self.assertEqual(None,
    3056                            iterator.root)
    3057          events = list(iterator)
    3058          root = iterator.root
    3059          self.assertEqual(
    3060              [('end', root[0]), ('end', root[1]), ('end', root)],
    3061              events)
    3062
    3063 -    def test_iterparse_incomplete(self):
    3064          iterparse = self.etree.iterparse
    3065          f = BytesIO('<a><b></b><c/></a>')
    3066
    3067          iterator = iterparse(f)
    3068          self.assertEqual(None,
    3069                            iterator.root)
    3070          event, element = next(iter(iterator))
    3071          self.assertEqual('end', event)
    3072          self.assertEqual('b', element.tag)
    3073
    3074 -    def test_iterparse_file(self):
    3075          iterparse = self.etree.iterparse
    3076          iterator = iterparse(fileInTestDir("test.xml"))
    3077          self.assertEqual(None,
    3078                            iterator.root)
    3079          events = list(iterator)
    3080          root = iterator.root
    3081          self.assertEqual(
    3082              [('end', root[0]), ('end', root)],
    3083              events)
    3084
    3085 -    def test_iterparse_start(self):
    3086          iterparse = self.etree.iterparse
    3087          f = BytesIO('<a><b></b><c/></a>')
    3088
    3089          iterator = iterparse(f, events=('start',))
    3090          events = list(iterator)
    3091          root = iterator.root
    3092          self.assertEqual(
    3093              [('start', root), ('start', root[0]), ('start', root[1])],
    3094              events)
    3095
    3096 -    def test_iterparse_start_end(self):
    3097          iterparse = self.etree.iterparse
    3098          f = BytesIO('<a><b></b><c/></a>')
    3099
    3100          iterator = iterparse(f, events=('start','end'))
    3101          events = list(iterator)
    3102          root = iterator.root
    3103          self.assertEqual(
    3104              [('start', root), ('start', root[0]), ('end', root[0]),
    3105               ('start', root[1]), ('end', root[1]), ('end', root)],
    3106              events)
    3107
    3108 -    def test_iterparse_clear(self):
    3109          iterparse = self.etree.iterparse
    3110          f = BytesIO('<a><b></b><c/></a>')
    3111
    3112          iterator = iterparse(f)
    3113          for event, elem in iterator:
    3114              elem.clear()
    3115
    3116          root = iterator.root
    3117          self.assertEqual(0,
    3118                            len(root))
    3119
    3120 -    def test_iterparse_large(self):
    3121          iterparse = self.etree.iterparse
    3122          CHILD_COUNT = 12345
    3123          f = BytesIO('<a>%s</a>' % ('<b>test</b>'*CHILD_COUNT))
    3124
    3125          i = 0
    3126          for key in iterparse(f):
    3127              event, element = key
    3128              i += 1
    3129          self.assertEqual(i, CHILD_COUNT + 1)
    3130
    3131 -    def test_iterparse_set_ns_attribute(self):
    3132          iterparse = self.etree.iterparse
    3133          f = BytesIO('<a xmlns="http://ns1/"><b><c xmlns="http://ns2/"/></b></a>')
    3134
    3135          attr_name = '{http://testns/}bla'
    3136          events = []
    3137          iterator = iterparse(f, events=('start','end','start-ns','end-ns'))
    3138          for event, elem in iterator:
    3139              events.append(event)
    3140              if event == 'start':
    3141                  if elem.tag != '{http://ns1/}a':
    3142                      elem.set(attr_name, 'value')
    3143
    3144          self.assertEqual(
    3145              ['start-ns', 'start', 'start', 'start-ns', 'start',
    3146               'end', 'end-ns', 'end', 'end', 'end-ns'],
    3147              events)
    3148
    3149          root = iterator.root
    3150          self.assertEqual(
    3151              None,
    3152              root.get(attr_name))
    3153          self.assertEqual(
    3154              'value',
    3155              root[0].get(attr_name))
    3156
    3157 -    def test_iterparse_only_end_ns(self):
    3158          iterparse = self.etree.iterparse
    3159          f = BytesIO('<a xmlns="http://ns1/"><b><c xmlns="http://ns2/"/></b></a>')
    3160
    3161          attr_name = '{http://testns/}bla'
    3162          events = []
    3163          iterator = iterparse(f, events=('start','end','start-ns','end-ns'))
    3164          for event, elem in iterator:
    3165              events.append(event)
    3166              if event == 'start':
    3167                  if elem.tag != '{http://ns1/}a':
    3168                      elem.set(attr_name, 'value')
    3169
    3170          self.assertEqual(
    3171              ['start-ns', 'start', 'start', 'start-ns', 'start',
    3172               'end', 'end-ns', 'end', 'end', 'end-ns'],
    3173              events)
    3174
    3175          root = iterator.root
    3176          self.assertEqual(
    3177              None,
    3178              root.get(attr_name))
    3179          self.assertEqual(
    3180              'value',
    3181              root[0].get(attr_name))
    3182
    3183 -    def test_iterparse_getiterator(self):
    3184          iterparse = self.etree.iterparse
    3185          f = BytesIO('<a><b><d/></b><c/></a>')
    3186
    3187          counts = []
    3188          for event, elem in iterparse(f):
    3189              counts.append(len(list(elem.getiterator())))
    3190          self.assertEqual(
    3191              [1,2,1,4],
    3192              counts)
    3193
    3194 -    def test_iterparse_move_elements(self):
    3195          iterparse = self.etree.iterparse
    3196          f = BytesIO('<a><b><d/></b><c/></a>')
    3197
    3198          for event, node in etree.iterparse(f): pass
    3199
    3200          root = etree.Element('new_root', {})
    3201          root[:] = node[:]
    3202
    3203          self.assertEqual(
    3204              ['b', 'c'],
    3205              [ el.tag for el in root ])
    3206
    3207 -    def test_iterparse_cdata(self):
    3208          tostring = self.etree.tostring
    3209          f = BytesIO('<root><![CDATA[test]]></root>')
    3210          context = self.etree.iterparse(f)
    3211          content = [ el.text for event,el in context ]
    3212
    3213          self.assertEqual(['test'], content)
    3214          self.assertEqual(_bytes('<root>test</root>'),
    3215                            tostring(context.root))
    3216
    3217 -    def test_parse_file(self):
    3218          parse = self.etree.parse
    3219          # from file
    3220          tree = parse(fileInTestDir('test.xml'))
    3221          self.assertXML(
    3222              _bytes('<a><b></b></a>'),
    3223              tree.getroot())
    3224
    3225 -    def test_parse_file_nonexistent(self):
    3226          parse = self.etree.parse
    3227          self.assertRaises(IOError, parse, fileInTestDir('notthere.xml'))
    3228
    3229 -    def test_parse_error_none(self):
    3230          parse = self.etree.parse
    3231          self.assertRaises(TypeError, parse, None)
    3232
    3233      required_versions_ET['test_parse_error'] = (1,3)
    3234 -    def test_parse_error(self):
    3235          # ET < 1.3 raises ExpatError
    3236          parse = self.etree.parse
    3237          f = BytesIO('<a><b></c></b></a>')
    3238          self.assertRaises(SyntaxError, parse, f)
    3239          f.close()
    3240
    3241      required_versions_ET['test_parse_error_from_file'] = (1,3)
    3242 -    def test_parse_error_from_file(self):
    3243          parse = self.etree.parse
    3244          # from file
    3245          f = open(fileInTestDir('test_broken.xml'), 'rb')
    3246          self.assertRaises(SyntaxError, parse, f)
    3247          f.close()
    3248
    3249 -    def test_parse_file_object(self):
    3250          parse = self.etree.parse
    3251          # from file object
    3252          f = open(fileInTestDir('test.xml'), 'rb')
    3253          tree = parse(f)
    3254          f.close()
    3255          self.assertXML(
    3256              _bytes('<a><b></b></a>'),
    3257              tree.getroot())
    3258
    3259 -    def test_parse_stringio(self):
    3260          parse = self.etree.parse
    3261          f = BytesIO('<a><b></b></a>')
    3262          tree = parse(f)
    3263          f.close()
    3264          self.assertXML(
    3265              _bytes('<a><b></b></a>'),
    3266              tree.getroot()
    3267             )
    3268
    3269 -    def test_parse_cdata(self):
    3270          tostring = self.etree.tostring
    3271          root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'))
    3272
    3273          self.assertEqual('test', root.text)
    3274          self.assertEqual(_bytes('<root>test</root>'),
    3275                            tostring(root))
    3276
    3277 -    def test_parse_with_encoding(self):
    3278          # this can fail in libxml2 <= 2.6.22
    3279          parse = self.etree.parse
    3280          tree = parse(BytesIO('<?xml version="1.0" encoding="ascii"?><html/>'))
    3281          self.assertXML(_bytes('<html></html>'),
    3282                         tree.getroot())
    3283
    3284 -    def test_encoding(self):
    3285          Element = self.etree.Element
    3286
    3287          a = Element('a')
    3288          a.text = _str('Søk på nettet')
    3289          self.assertXML(
    3290              _str('<a>Søk på nettet</a>').encode('UTF-8'),
    3291              a, 'utf-8')
    3292
    3293 -    def test_encoding_exact(self):
    3294          ElementTree = self.etree.ElementTree
    3295          Element = self.etree.Element
    3296
    3297          a = Element('a')
    3298          a.text = _str('Søk på nettet')
    3299
    3300          f = BytesIO()
    3301          tree = ElementTree(element=a)
    3302          tree.write(f, encoding='utf-8')
    3303          self.assertEqual(_str('<a>Søk på nettet</a>').encode('UTF-8'),
    3304                            f.getvalue().replace(_bytes('\n'),_bytes('')))
    3305
    3306 -    def test_parse_file_encoding(self):
    3307          parse = self.etree.parse
    3308          # from file
    3309          tree = parse(fileInTestDir('test-string.xml'))
    3310          self.assertXML(
    3311              _str('<a>Søk på nettet</a>').encode('UTF-8'),
    3312              tree.getroot(), 'UTF-8')
    3313
    3314 -    def test_parse_file_object_encoding(self):
    3315          parse = self.etree.parse
    3316          # from file object
    3317          f = open(fileInTestDir('test-string.xml'), 'rb')
    3318          tree = parse(f)
    3319          f.close()
    3320          self.assertXML(
    3321              _str('<a>Søk på nettet</a>').encode('UTF-8'),
    3322              tree.getroot(), 'UTF-8')
    3323
    3324 -    def test_encoding_8bit_latin1(self):
    3325          ElementTree = self.etree.ElementTree
    3326          Element = self.etree.Element
    3327
    3328          a = Element('a')
    3329          a.text = _str('Søk på nettet')
    3330
    3331          f = BytesIO()
    3332          tree = ElementTree(element=a)
    3333          tree.write(f, encoding='iso-8859-1')
    3334          result = f.getvalue()
    3335          declaration = _bytes("<?xml version=\'1.0\' encoding=\'iso-8859-1\'?>")
    3336          self.assertEncodingDeclaration(result, _bytes('iso-8859-1'))
    3337          result = result.split(_bytes('?>'), 1)[-1].replace(_bytes('\n'),_bytes(''))
    3338          self.assertEqual(_str('<a>Søk på nettet</a>').encode('iso-8859-1'),
    3339                            result)
    3340
    3341      required_versions_ET['test_parse_encoding_8bit_explicit'] = (1,3)
    3342 -    def test_parse_encoding_8bit_explicit(self):
    3343          XMLParser = self.XMLParser
    3344
    3345          text = _str('Søk på nettet')
    3346          xml_latin1 = (_str('<a>%s</a>') % text).encode('iso-8859-1')
    3347
    3348          self.assertRaises(self.etree.ParseError,
    3349                            self.etree.parse,
    3350                            BytesIO(xml_latin1))
    3351
    3352          tree = self.etree.parse(BytesIO(xml_latin1),
    3353                                  XMLParser(encoding="iso-8859-1"))
    3354          a = tree.getroot()
    3355          self.assertEqual(a.text, text)
    3356
    3357      required_versions_ET['test_parse_encoding_8bit_override'] = (1,3)
    3358 -    def test_parse_encoding_8bit_override(self):
    3359          XMLParser = self.XMLParser
    3360
    3361          text = _str('Søk på nettet')
    3362          wrong_declaration = _str("<?xml version='1.0' encoding='UTF-8'?>")
    3363          xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
    3364                        ).encode('iso-8859-1')
    3365
    3366          self.assertRaises(self.etree.ParseError,
    3367                            self.etree.parse,
    3368                            BytesIO(xml_latin1))
    3369
    3370          tree = self.etree.parse(BytesIO(xml_latin1),
    3371                                  XMLParser(encoding="iso-8859-1"))
    3372          a = tree.getroot()
    3373          self.assertEqual(a.text, text)
    3374
    3375 -    def _test_wrong_unicode_encoding(self):
    3376          # raise error on wrong encoding declaration in unicode strings
    3377          XML = self.etree.XML
    3378          test_utf = (_str('<?xml version="1.0" encoding="iso-8859-1"?>') +
    3379                      _str('<a>Søk på nettet</a>'))
    3380          self.assertRaises(SyntaxError, XML, test_utf)
    3381
    3382 -    def test_encoding_write_default_encoding(self):
    3383          ElementTree = self.etree.ElementTree
    3384          Element = self.etree.Element
    3385
    3386          a = Element('a')
    3387          a.text = _str('Søk på nettet')
    3388
    3389          f = BytesIO()
    3390          tree = ElementTree(element=a)
    3391          tree.write(f)
    3392          data = f.getvalue().replace(_bytes('\n'),_bytes(''))
    3393          self.assertEqual(
    3394              _str('<a>Søk på nettet</a>').encode('ASCII', 'xmlcharrefreplace'),
    3395              data)
    3396
    3397 -    def test_encoding_tostring(self):
    3398          Element = self.etree.Element
    3399          tostring = self.etree.tostring
    3400
    3401          a = Element('a')
    3402          a.text = _str('Søk på nettet')
    3403          self.assertEqual(_str('<a>Søk på nettet</a>').encode('UTF-8'),
    3404                           tostring(a, encoding='utf-8'))
    3405
    3406 -    def test_encoding_tostring_unknown(self):
    3407          Element = self.etree.Element
    3408          tostring = self.etree.tostring
    3409
    3410          a = Element('a')
    3411          a.text = _str('Søk på nettet')
    3412          self.assertRaises(LookupError, tostring, a,
    3413                            encoding='Invalid Encoding')
    3414
    3415 -    def test_encoding_tostring_sub(self):
    3416          Element = self.etree.Element
    3417          SubElement = self.etree.SubElement
    3418          tostring = self.etree.tostring
    3419
    3420          a = Element('a')
    3421          b = SubElement(a, 'b')
    3422          b.text = _str('Søk på nettet')
    3423          self.assertEqual(_str('<b>Søk på nettet</b>').encode('UTF-8'),
    3424                           tostring(b, encoding='utf-8'))
    3425
    3426 -    def test_encoding_tostring_sub_tail(self):
    3427          Element = self.etree.Element
    3428          SubElement = self.etree.SubElement
    3429          tostring = self.etree.tostring
    3430
    3431          a = Element('a')
    3432          b = SubElement(a, 'b')
    3433          b.text = _str('Søk på nettet')
    3434          b.tail = _str('Søk')
    3435          self.assertEqual(_str('<b>Søk på nettet</b>Søk').encode('UTF-8'),
    3436                           tostring(b, encoding='utf-8'))
    3437
    3438 -    def test_encoding_tostring_default_encoding(self):
    3439          Element = self.etree.Element
    3440          SubElement = self.etree.SubElement
    3441          tostring = self.etree.tostring
    3442
    3443          a = Element('a')
    3444          a.text = _str('Søk på nettet')
    3445
    3446          expected = _bytes('<a>S&#248;k p&#229; nettet</a>')
    3447          self.assertEqual(
    3448              expected,
    3449              tostring(a))
    3450
    3451 -    def test_encoding_sub_tostring_default_encoding(self):
    3452          Element = self.etree.Element
    3453          SubElement = self.etree.SubElement
    3454          tostring = self.etree.tostring
    3455
    3456          a = Element('a')
    3457          b = SubElement(a, 'b')
    3458          b.text = _str('Søk på nettet')
    3459
    3460          expected = _bytes('<b>S&#248;k p&#229; nettet</b>')
    3461          self.assertEqual(
    3462              expected,
    3463              tostring(b))
    3464
    3465 -    def test_encoding_8bit_xml(self):
    3466          utext = _str('Søk på nettet')
    3467          uxml = _str('<p>%s</p>') % utext
    3468          prologue = _bytes('<?xml version="1.0" encoding="iso-8859-1" ?>')
    3469          isoxml = prologue + uxml.encode('iso-8859-1')
    3470          tree = self.etree.XML(isoxml)
    3471          self.assertEqual(utext, tree.text)
    3472
    3473 -    def test_encoding_utf8_bom(self):
    3474          utext = _str('Søk på nettet')
    3475          uxml = (_str('<?xml version="1.0" encoding="UTF-8"?>') +
    3476                  _str('<p>%s</p>') % utext)
    3477          bom = _bytes('\\xEF\\xBB\\xBF').decode("unicode_escape").encode("latin1")
    3478          xml = bom + uxml.encode("utf-8")
    3479          tree = etree.XML(xml)
    3480          self.assertEqual(utext, tree.text)
    3481
    3482 -    def test_encoding_8bit_parse_stringio(self):
    3483          utext = _str('Søk på nettet')
    3484          uxml = _str('<p>%s</p>') % utext
    3485          prologue = _bytes('<?xml version="1.0" encoding="iso-8859-1" ?>')
    3486          isoxml = prologue + uxml.encode('iso-8859-1')
    3487          el = self.etree.parse(BytesIO(isoxml)).getroot()
    3488          self.assertEqual(utext, el.text)
    3489
    3490 -    def test_deepcopy_elementtree(self):
    3491          Element = self.etree.Element
    3492          ElementTree = self.etree.ElementTree
    3493
    3494          a = Element('a')
    3495          a.text = "Foo"
    3496          atree = ElementTree(a)
    3497
    3498          btree = copy.deepcopy(atree)
    3499          self.assertEqual("Foo", atree.getroot().text)
    3500          self.assertEqual("Foo", btree.getroot().text)
    3501          self.assertFalse(btree is atree)
    3502          self.assertFalse(btree.getroot() is atree.getroot())
    3503
    3504 -    def test_deepcopy(self):
    3505          Element = self.etree.Element
    3506
    3507          a = Element('a')
    3508          a.text = 'Foo'
    3509
    3510          b = copy.deepcopy(a)
    3511          self.assertEqual('Foo', b.text)
    3512
    3513          b.text = 'Bar'
    3514          self.assertEqual('Bar', b.text)
    3515          self.assertEqual('Foo', a.text)
    3516
    3517          del a
    3518          self.assertEqual('Bar', b.text)
    3519
    3520 -    def test_deepcopy_tail(self):
    3521          Element = self.etree.Element
    3522
    3523          a = Element('a')
    3524          a.tail = 'Foo'
    3525
    3526          b = copy.deepcopy(a)
    3527          self.assertEqual('Foo', b.tail)
    3528
    3529          b.tail = 'Bar'
    3530          self.assertEqual('Bar', b.tail)
    3531          self.assertEqual('Foo', a.tail)
    3532
    3533          del a
    3534          self.assertEqual('Bar', b.tail)
    3535
    3536 -    def test_deepcopy_subelement(self):
    3537          Element = self.etree.Element
    3538          SubElement = self.etree.SubElement
    3539
    3540          root = Element('root')
    3541          a = SubElement(root, 'a')
    3542          a.text = 'FooText'
    3543          a.tail = 'FooTail'
    3544
    3545          b = copy.deepcopy(a)
    3546          self.assertEqual('FooText', b.text)
    3547          self.assertEqual('FooTail', b.tail)
    3548
    3549          b.text = 'BarText'
    3550          b.tail = 'BarTail'
    3551          self.assertEqual('BarTail', b.tail)
    3552          self.assertEqual('FooTail', a.tail)
    3553          self.assertEqual('BarText', b.text)
    3554          self.assertEqual('FooText', a.text)
    3555
    3556          del a
    3557          self.assertEqual('BarTail', b.tail)
    3558          self.assertEqual('BarText', b.text)
    3559
    3560 -    def test_deepcopy_namespaces(self):
    3561          root = self.etree.XML(_bytes('''<doc xmlns="dns" xmlns:t="tns">
    3562          <parent><node t:foo="bar" /></parent>
    3563          </doc>'''))
    3564          self.assertEqual(
    3565              root[0][0].get('{tns}foo'),
    3566              copy.deepcopy(root[0])[0].get('{tns}foo') )
    3567          self.assertEqual(
    3568              root[0][0].get('{tns}foo'),
    3569              copy.deepcopy(root[0][0]).get('{tns}foo') )
    3570
    3571 -    def test_deepcopy_append(self):
    3572          # previously caused a crash
    3573          Element = self.etree.Element
    3574          tostring = self.etree.tostring
    3575
    3576          a = Element('a')
    3577          b = copy.deepcopy(a)
    3578          a.append( Element('C') )
    3579          b.append( Element('X') )
    3580
    3581          self.assertEqual(_bytes('<a><C/></a>'),
    3582                            tostring(a).replace(_bytes(' '), _bytes('')))
    3583          self.assertEqual(_bytes('<a><X/></a>'),
    3584                            tostring(b).replace(_bytes(' '), _bytes('')))
    3585
    3586 -    def test_deepcopy_comment(self):
    3587          # previously caused a crash
    3588          # not supported by ET < 1.3!
    3589          Comment = self.etree.Comment
    3590
    3591          a = Comment("ONE")
    3592          b = copy.deepcopy(a)
    3593          b.text = "ANOTHER"
    3594
    3595          self.assertEqual('ONE',     a.text)
    3596          self.assertEqual('ANOTHER', b.text)
    3597
    3598 -    def test_shallowcopy(self):
    3599          Element = self.etree.Element
    3600
    3601          a = Element('a')
    3602          a.text = 'Foo'
    3603
    3604          b = copy.copy(a)
    3605          self.assertEqual('Foo', b.text)
    3606
    3607          b.text = 'Bar'
    3608          self.assertEqual('Bar', b.text)
    3609          self.assertEqual('Foo', a.text)
    3610          # XXX ElementTree will share nodes, but lxml.etree won't..
    3611
    3612 -    def test_shallowcopy_elementtree(self):
    3613          Element = self.etree.Element
    3614          ElementTree = self.etree.ElementTree
    3615
    3616          a = Element('a')
    3617          a.text = 'Foo'
    3618          atree = ElementTree(a)
    3619
    3620          btree = copy.copy(atree)
    3621          self.assertFalse(btree is atree)
    3622          self.assertTrue(btree.getroot() is atree.getroot())
    3623          self.assertEqual('Foo', atree.getroot().text)
    3624
    3625 -    def _test_element_boolean(self):
    3626          # deprecated as of ET 1.3/lxml 2.0
    3627          etree = self.etree
    3628          e = etree.Element('foo')
    3629          self.assertEqual(False, bool(e))
    3630          etree.SubElement(e, 'bar')
    3631          self.assertEqual(True, bool(e))
    3632          e = etree.Element('foo')
    3633          e.text = 'hey'
    3634          self.assertEqual(False, bool(e))
    3635          e = etree.Element('foo')
    3636          e.tail = 'bar'
    3637          self.assertEqual(False, bool(e))
    3638          e = etree.Element('foo')
    3639          e.set('bar', 'Bar')
    3640          self.assertEqual(False, bool(e))
    3641
    3642 -    def test_multiple_elementrees(self):
    3643          etree = self.etree
    3644
    3645          a = etree.Element('a')
    3646          b = etree.SubElement(a, 'b')
    3647
    3648          t = etree.ElementTree(a)
    3649          self.assertEqual(self._rootstring(t), _bytes('<a><b/></a>'))
    3650
    3651          t1 = etree.ElementTree(a)
    3652          self.assertEqual(self._rootstring(t1), _bytes('<a><b/></a>'))
    3653          self.assertEqual(self._rootstring(t),  _bytes('<a><b/></a>'))
    3654
    3655          t2 = etree.ElementTree(b)
    3656          self.assertEqual(self._rootstring(t2), _bytes('<b/>'))
    3657          self.assertEqual(self._rootstring(t1), _bytes('<a><b/></a>'))
    3658          self.assertEqual(self._rootstring(t),  _bytes('<a><b/></a>'))
    3659
    3660 -    def test_qname(self):
    3661          etree = self.etree
    3662          qname = etree.QName('myns', 'a')
    3663          a1 = etree.Element(qname)
    3664          a2 = etree.SubElement(a1, qname)
    3665          self.assertEqual(a1.tag, "{myns}a")
    3666          self.assertEqual(a2.tag, "{myns}a")
    3667
    3668 -    def test_qname_cmp(self):
    3669          etree = self.etree
    3670          qname1 = etree.QName('myns', 'a')
    3671          qname2 = etree.QName('myns', 'a')
    3672          self.assertEqual(qname1, "{myns}a")
    3673          self.assertEqual("{myns}a", qname2)
    3674          self.assertEqual(qname1, qname1)
    3675          self.assertEqual(qname1, qname2)
    3676
    3677 -    def test_qname_attribute_getset(self):
    3678          etree = self.etree
    3679          qname = etree.QName('myns', 'a')
    3680
    3681          a = etree.Element(qname)
    3682          a.set(qname, "value")
    3683
    3684          self.assertEqual(a.get(qname), "value")
    3685          self.assertEqual(a.get("{myns}a"), "value")
    3686
    3687 -    def test_qname_attrib(self):
    3688          etree = self.etree
    3689          qname = etree.QName('myns', 'a')
    3690
    3691          a = etree.Element(qname)
    3692          a.attrib[qname] = "value"
    3693
    3694          self.assertEqual(a.attrib[qname], "value")
    3695          self.assertEqual(a.attrib.get(qname), "value")
    3696
    3697          self.assertEqual(a.attrib["{myns}a"], "value")
    3698          self.assertEqual(a.attrib.get("{myns}a"), "value")
    3699
    3700 -    def test_qname_attribute_resolve(self):
    3701          etree = self.etree
    3702          qname = etree.QName('http://myns', 'a')
    3703          a = etree.Element(qname)
    3704          a.set(qname, qname)
    3705
    3706          self.assertXML(
    3707              _bytes('<ns0:a xmlns:ns0="http://myns" ns0:a="ns0:a"></ns0:a>'),
    3708              a)
    3709
    3710 -    def test_qname_attribute_resolve_new(self):
    3711          etree = self.etree
    3712          qname = etree.QName('http://myns', 'a')
    3713          a = etree.Element('a')
    3714          a.set('a', qname)
    3715
    3716          self.assertXML(
    3717              _bytes('<a xmlns:ns0="http://myns" a="ns0:a"></a>'),
    3718              a)
    3719
    3720 -    def test_qname_attrib_resolve(self):
    3721          etree = self.etree
    3722          qname = etree.QName('http://myns', 'a')
    3723          a = etree.Element(qname)
    3724          a.attrib[qname] = qname
    3725
    3726          self.assertXML(
    3727              _bytes('<ns0:a xmlns:ns0="http://myns" ns0:a="ns0:a"></ns0:a>'),
    3728              a)
    3729
    3730 -    def test_parser_version(self):
    3731          etree = self.etree
    3732          parser = etree.XMLParser()
    3733          if hasattr(parser, "version"):
    3734              # ElementTree 1.3+, cET
    3735              self.assertTrue(re.match("[^ ]+ [0-9.]+", parser.version))
    3736
    3737      # feed parser interface
    3738
    3739 -    def test_feed_parser_bytes(self):
    3740          parser = self.XMLParser()
    3741
    3742          parser.feed(_bytes('<?xml version='))
    3743          parser.feed(_bytes('"1.0"?><ro'))
    3744          parser.feed(_bytes('ot><'))
    3745          parser.feed(_bytes('a test="works"/'))
    3746          parser.feed(_bytes('></root'))
    3747          parser.feed(_bytes('>'))
    3748
    3749          root = parser.close()
    3750
    3751          self.assertEqual(root.tag, "root")
    3752          self.assertEqual(root[0].tag, "a")
    3753          self.assertEqual(root[0].get("test"), "works")
    3754
    3755 -    def test_feed_parser_unicode(self):
    3756          parser = self.XMLParser()
    3757
    3758          parser.feed(_str('<ro'))
    3759          parser.feed(_str('ot><'))
    3760          parser.feed(_str('a test="works"/'))
    3761          parser.feed(_str('></root'))
    3762          parser.feed(_str('>'))
    3763
    3764          root = parser.close()
    3765
    3766          self.assertEqual(root.tag, "root")
    3767          self.assertEqual(root[0].tag, "a")
    3768          self.assertEqual(root[0].get("test"), "works")
    3769
    3770      required_versions_ET['test_feed_parser_error_close_empty'] = (1,3)
    3771 -    def test_feed_parser_error_close_empty(self):
    3772          ParseError = self.etree.ParseError
    3773          parser = self.XMLParser()
    3774          self.assertRaises(ParseError, parser.close)
    3775
    3776      required_versions_ET['test_feed_parser_error_close_incomplete'] = (1,3)
    3777 -    def test_feed_parser_error_close_incomplete(self):
    3778          ParseError = self.etree.ParseError
    3779          parser = self.XMLParser()
    3780
    3781          parser.feed('<?xml version=')
    3782          parser.feed('"1.0"?><ro')
    3783
    3784          self.assertRaises(ParseError, parser.close)
    3785
    3786      required_versions_ET['test_feed_parser_error_broken'] = (1,3)
    3787 -    def test_feed_parser_error_broken(self):
    3788          ParseError = self.etree.ParseError
    3789          parser = self.XMLParser()
    3790
    3791          parser.feed('<?xml version=')
    3792          parser.feed('"1.0"?><ro')
    3793          try:
    3794              parser.feed('<><><><><><><')
    3795          except ParseError:
    3796              # can raise, but not required before close()
    3797              pass
    3798
    3799          self.assertRaises(ParseError, parser.close)
    3800
    3801      required_versions_ET['test_feed_parser_error_position'] = (1,3)
    3802 -    def test_feed_parser_error_position(self):
    3803          ParseError = self.etree.ParseError
    3804          parser = self.XMLParser()
    3805          try:
    3806              parser.close()
    3807          except ParseError:
    3808              e = sys.exc_info()[1]
    3809              self.assertNotEqual(None, e.code)
    3810              self.assertNotEqual(0, e.code)
    3811              self.assertTrue(isinstance(e.position, tuple))
    3812              self.assertTrue(e.position >= (0, 0))
    3813
    3814      # parser target interface
    3815
    3816      required_versions_ET['test_parser_target_property'] = (1,3)
    3817 -    def test_parser_target_property(self):
    3818          class Target(object):
    3819              pass
    3820
    3821          target = Target()
    3822          parser = self.XMLParser(target=target)
    3823
    3824          self.assertEqual(target, parser.target)
    3825
    3826 -    def test_parser_target_tag(self):
    3827          assertEqual = self.assertEqual
    3828          assertFalse  = self.assertFalse
    3829
    3830          events = []
    3831          class Target(object):
    3832              def start(self, tag, attrib):
    3833                  events.append("start")
    3834                  assertFalse(attrib)
    3835                  assertEqual("TAG", tag)
    3836              def end(self, tag):
    3837                  events.append("end")
    3838                  assertEqual("TAG", tag)
    3839              def close(self):
    3840                  return "DONE"
    3841
    3842          parser = self.XMLParser(target=Target())
    3843
    3844          parser.feed("<TAG/>")
    3845          done = parser.close()
    3846
    3847          self.assertEqual("DONE", done)
    3848          self.assertEqual(["start", "end"], events)
    3849
    3850 -    def test_parser_target_error_in_start(self):
    3851          assertEqual = self.assertEqual
    3852
    3853          events = []
    3854          class Target(object):
    3855              def start(self, tag, attrib):
    3856                  events.append("start")
    3857                  assertEqual("TAG", tag)
    3858                  raise ValueError("TEST")
    3859              def end(self, tag):
    3860                  events.append("end")
    3861                  assertEqual("TAG", tag)
    3862              def close(self):
    3863                  return "DONE"
    3864
    3865          parser = self.XMLParser(target=Target())
    3866
    3867          try:
    3868              parser.feed("<TAG/>")
    3869          except ValueError:
    3870              self.assertTrue('TEST' in str(sys.exc_info()[1]))
    3871          else:
    3872              self.assertTrue(False)
    3873          if 'lxml' in self.etree.__name__:
    3874              self.assertEqual(["start"], events)
    3875          else:
    3876              # cElementTree calls end() as well
    3877              self.assertTrue("start" in events)
    3878
    3879 -    def test_parser_target_error_in_end(self):
    3880          assertEqual = self.assertEqual
    3881
    3882          events = []
    3883          class Target(object):
    3884              def start(self, tag, attrib):
    3885                  events.append("start")
    3886                  assertEqual("TAG", tag)
    3887              def end(self, tag):
    3888                  events.append("end")
    3889                  assertEqual("TAG", tag)
    3890                  raise ValueError("TEST")
    3891              def close(self):
    3892                  return "DONE"
    3893
    3894          parser = self.XMLParser(target=Target())
    3895
    3896          try:
    3897              parser.feed("<TAG/>")
    3898          except ValueError:
    3899              self.assertTrue('TEST' in str(sys.exc_info()[1]))
    3900          else:
    3901              self.assertTrue(False)
    3902          self.assertEqual(["start", "end"], events)
    3903
    3904 -    def test_parser_target_error_in_close(self):
    3905          assertEqual = self.assertEqual
    3906
    3907          events = []
    3908          class Target(object):
    3909              def start(self, tag, attrib):
    3910                  events.append("start")
    3911                  assertEqual("TAG", tag)
    3912              def end(self, tag):
    3913                  events.append("end")
    3914                  assertEqual("TAG", tag)
    3915              def close(self):
    3916                  raise ValueError("TEST")
    3917
    3918          parser = self.XMLParser(target=Target())
    3919
    3920          try:
    3921              parser.feed("<TAG/>")
    3922              parser.close()
    3923          except ValueError:
    3924              self.assertTrue('TEST' in str(sys.exc_info()[1]))
    3925          else:
    3926              self.assertTrue(False)
    3927          self.assertEqual(["start", "end"], events)
    3928
    3929 -    def test_parser_target_error_in_start_and_close(self):
    3930          assertEqual = self.assertEqual
    3931
    3932          events = []
    3933          class Target(object):
    3934              def start(self, tag, attrib):
    3935                  events.append("start")
    3936                  assertEqual("TAG", tag)
    3937                  raise IndexError("TEST-IE")
    3938              def end(self, tag):
    3939                  events.append("end")
    3940                  assertEqual("TAG", tag)
    3941              def close(self):
    3942                  raise ValueError("TEST-VE")
    3943
    3944          parser = self.XMLParser(target=Target())
    3945
    3946          try:
    3947              parser.feed("<TAG/>")
    3948              parser.close()
    3949          except IndexError:
    3950              if 'lxml' in self.etree.__name__:
    3951                  # we try not to swallow the initial exception in Py2
    3952                  self.assertTrue(sys.version_info[0] < 3)
    3953              self.assertTrue('TEST-IE' in str(sys.exc_info()[1]))
    3954          except ValueError:
    3955              if 'lxml' in self.etree.__name__:
    3956                  self.assertTrue(sys.version_info[0] >= 3)
    3957              self.assertTrue('TEST-VE' in str(sys.exc_info()[1]))
    3958          else:
    3959              self.assertTrue(False)
    3960
    3961          if 'lxml' in self.etree.__name__:
    3962              self.assertEqual(["start"], events)
    3963          else:
    3964              # cElementTree calls end() as well
    3965              self.assertTrue("start" in events)
    3966
    3967 -    def test_elementtree_parser_target(self):
    3968          assertEqual = self.assertEqual
    3969          assertFalse  = self.assertFalse
    3970          Element = self.etree.Element
    3971
    3972          events = []
    3973          class Target(object):
    3974              def start(self, tag, attrib):
    3975                  events.append("start")
    3976                  assertFalse(attrib)
    3977                  assertEqual("TAG", tag)
    3978              def end(self, tag):
    3979                  events.append("end")
    3980                  assertEqual("TAG", tag)
    3981              def close(self):
    3982                  return Element("DONE")
    3983
    3984          parser = self.XMLParser(target=Target())
    3985          tree = self.etree.ElementTree()
    3986          tree.parse(BytesIO("<TAG/>"), parser=parser)
    3987
    3988          self.assertEqual("DONE", tree.getroot().tag)
    3989          self.assertEqual(["start", "end"], events)
    3990
    3991 -    def test_parser_target_attrib(self):
    3992          assertEqual = self.assertEqual
    3993
    3994          events = []
    3995          class Target(object):
    3996              def start(self, tag, attrib):
    3997                  events.append("start-" + tag)
    3998                  for name, value in attrib.items():
    3999                      assertEqual(tag + name, value)
    4000              def end(self, tag):
    4001                  events.append("end-" + tag)
    4002              def close(self):
    4003                  return "DONE"
    4004
    4005          parser = self.XMLParser(target=Target())
    4006
    4007          parser.feed('<root a="roota" b="rootb"><sub c="subc"/></root>')
    4008          done = parser.close()
    4009
    4010          self.assertEqual("DONE", done)
    4011          self.assertEqual(["start-root", "start-sub", "end-sub", "end-root"],
    4012                            events)
    4013
    4014 -    def test_parser_target_data(self):
    4015          events = []
    4016          class Target(object):
    4017              def start(self, tag, attrib):
    4018                  events.append("start-" + tag)
    4019              def end(self, tag):
    4020                  events.append("end-" + tag)
    4021              def data(self, data):
    4022                  events.append("data-" + data)
    4023              def close(self):
    4024                  return "DONE"
    4025
    4026          parser = self.XMLParser(target=Target())
    4027
    4028          parser.feed('<root>A<sub/>B</root>')
    4029          done = parser.close()
    4030
    4031          self.assertEqual("DONE", done)
    4032          self.assertEqual(["start-root", "data-A", "start-sub",
    4033                             "end-sub", "data-B", "end-root"],
    4034                            events)
    4035
    4036 -    def test_parser_target_entity(self):
    4037          events = []
    4038          class Target(object):
    4039              def __init__(self):
    4040                  self._data = []
    4041              def _flush_data(self):
    4042                  if self._data:
    4043                      events.append("data-" + ''.join(self._data))
    4044                      del self._data[:]
    4045              def start(self, tag, attrib):
    4046                  self._flush_data()
    4047                  events.append("start-" + tag)
    4048              def end(self, tag):
    4049                  self._flush_data()
    4050                  events.append("end-" + tag)
    4051              def data(self, data):
    4052                  self._data.append(data)
    4053              def close(self):
    4054                  self._flush_data()
    4055                  return "DONE"
    4056
    4057          parser = self.XMLParser(target=Target())
    4058
    4059          dtd = '''
    4060              <!DOCTYPE root [
    4061              <!ELEMENT root (sub*)>
    4062              <!ELEMENT sub (#PCDATA)>
    4063              <!ENTITY ent "an entity">
    4064          ]>
    4065          '''
    4066          parser.feed(dtd+'<root><sub/><sub>this is &ent;</sub><sub/></root>')
    4067          done = parser.close()
    4068
    4069          self.assertEqual("DONE", done)
    4070          self.assertEqual(["start-root", "start-sub", "end-sub", "start-sub",
    4071                             "data-this is an entity",
    4072                             "end-sub", "start-sub", "end-sub", "end-root"],
    4073                            events)
    4074
    4075      required_versions_ET['test_parser_target_entity_unknown'] = (1,3)
    4076 -    def test_parser_target_entity_unknown(self):
    4077          events = []
    4078          class Target(object):
    4079              def __init__(self):
    4080                  self._data = []
    4081              def _flush_data(self):
    4082                  if self._data:
    4083                      events.append("data-" + ''.join(self._data))
    4084                      del self._data[:]
    4085              def start(self, tag, attrib):
    4086                  self._flush_data()
    4087                  events.append("start-" + tag)
    4088              def end(self, tag):
    4089                  self._flush_data()
    4090                  events.append("end-" + tag)
    4091              def data(self, data):
    4092                  self._data.append(data)
    4093              def close(self):
    4094                  self._flush_data()
    4095                  return "DONE"
    4096
    4097          parser = self.XMLParser(target=Target())
    4098
    4099          def feed():
    4100              parser.feed('<root><sub/><sub>some &ent;</sub><sub/></root>')
    4101              parser.close()
    4102
    4103          self.assertRaises(self.etree.ParseError, feed)
    4104
    4105      @et_needs_pyversion(3, 8, 0, 'alpha', 4)
    4106 -    def test_parser_target_start_end_ns(self):
    4107          class Builder(list):
    4108              def start(self, tag, attrib):
    4109                  self.append(("start", tag))
    4110              def end(self, tag):
    4111                  self.append(("end", tag))
    4112              def data(self, text):
    4113                  pass
    4114              def pi(self, target, data):
    4115                  self.append(("pi", target, data))
    4116              def comment(self, data):
    4117                  self.append(("comment", data))
    4118              def start_ns(self, prefix, uri):
    4119                  self.append(("start-ns", prefix, uri))
    4120              def end_ns(self, prefix):
    4121                  self.append(("end-ns", prefix))
    4122
    4123          builder = Builder()
    4124          parser = self.etree.XMLParser(target=builder)
    4125          parser.feed(textwrap.dedent("""\
    4126              <?pi data?>
    4127              <!-- comment -->
    4128              <root xmlns='namespace'>
    4129                 <element key='value'>text</element>
    4130                 <element>text</element>tail
    4131                 <empty-element/>
    4132              </root>
    4133              """))
    4134          self.assertEqual(builder, [
    4135                  ('pi', 'pi', 'data'),
    4136                  ('comment', ' comment '),
    4137                  ('start-ns', '', 'namespace'),
    4138                  ('start', '{namespace}root'),
    4139                  ('start', '{namespace}element'),
    4140                  ('end', '{namespace}element'),
    4141                  ('start', '{namespace}element'),
    4142                  ('end', '{namespace}element'),
    4143                  ('start', '{namespace}empty-element'),
    4144                  ('end', '{namespace}empty-element'),
    4145                  ('end', '{namespace}root'),
    4146                  ('end-ns', ''),
    4147              ])
    4148
    4149      @et_needs_pyversion(3, 8, 0, 'alpha', 4)
    4150 -    def test_parser_target_end_ns(self):
    4151          class Builder(list):
    4152              def end_ns(self, prefix):
    4153                  self.append(("end-ns", prefix))
    4154
    4155          builder = Builder()
    4156          parser = self.etree.XMLParser(target=builder)
    4157          parser.feed(textwrap.dedent("""\
    4158              <?pi data?>
    4159              <!-- comment -->
    4160              <root xmlns='namespace' xmlns:p='pns'>
    4161                 <element key='value'>text</element>
    4162                 <p:element>text</p:element>tail
    4163                 <empty-element/>
    4164              </root>
    4165              """))
    4166          self.assertEqual(builder, [
    4167                  ('end-ns', 'p'),
    4168                  ('end-ns', ''),
    4169              ])
    4170
    4171 -    def test_treebuilder(self):
    4172          builder = self.etree.TreeBuilder()
    4173          el = builder.start("root", {'a':'A', 'b':'B'})
    4174          self.assertEqual("root", el.tag)
    4175          self.assertEqual({'a':'A', 'b':'B'}, el.attrib)
    4176          builder.data("ROOTTEXT")
    4177          el = builder.start("child", {'x':'X', 'y':'Y'})
    4178          self.assertEqual("child", el.tag)
    4179          self.assertEqual({'x':'X', 'y':'Y'}, el.attrib)
    4180          builder.data("CHILDTEXT")
    4181          el = builder.end("child")
    4182          self.assertEqual("child", el.tag)
    4183          self.assertEqual({'x':'X', 'y':'Y'}, el.attrib)
    4184          self.assertEqual("CHILDTEXT", el.text)
    4185          self.assertEqual(None, el.tail)
    4186          builder.data("CHILDTAIL")
    4187          root = builder.end("root")
    4188
    4189          self.assertEqual("root", root.tag)
    4190          self.assertEqual("ROOTTEXT", root.text)
    4191          self.assertEqual("CHILDTEXT", root[0].text)
    4192          self.assertEqual("CHILDTAIL", root[0].tail)
    4193
    4194 -    def test_treebuilder_target(self):
    4195          parser = self.XMLParser(target=self.etree.TreeBuilder())
    4196          parser.feed('<root>ROOTTEXT<child>CHILDTEXT</child>CHILDTAIL</root>')
    4197          root = parser.close()
    4198
    4199          self.assertEqual("root", root.tag)
    4200          self.assertEqual("ROOTTEXT", root.text)
    4201          self.assertEqual("CHILDTEXT", root[0].text)
    4202          self.assertEqual("CHILDTAIL", root[0].tail)
    4203
    4204      @et_needs_pyversion(3, 8, 0, 'alpha', 4)
    4205 -    def test_treebuilder_comment(self):
    4206          ET = self.etree
    4207          b = ET.TreeBuilder()
    4208          self.assertEqual(b.comment('ctext').tag, ET.Comment)
    4209          self.assertEqual(b.comment('ctext').text, 'ctext')
    4210
    4211          b = ET.TreeBuilder(comment_factory=ET.Comment)
    4212          self.assertEqual(b.comment('ctext').tag, ET.Comment)
    4213          self.assertEqual(b.comment('ctext').text, 'ctext')
    4214
    4215          #b = ET.TreeBuilder(comment_factory=len)
    4216          #self.assertEqual(b.comment('ctext'), len('ctext'))
    4217
    4218      @et_needs_pyversion(3, 8, 0, 'alpha', 4)
    4219 -    def test_treebuilder_pi(self):
    4220          ET = self.etree
    4221          is_lxml = ET.__name__ == 'lxml.etree'
    4222
    4223          b = ET.TreeBuilder()
    4224          self.assertEqual(b.pi('target', None).tag, ET.PI)
    4225          if is_lxml:
    4226              self.assertEqual(b.pi('target', None).target, 'target')
    4227          else:
    4228              self.assertEqual(b.pi('target', None).text, 'target')
    4229
    4230          b = ET.TreeBuilder(pi_factory=ET.PI)
    4231          self.assertEqual(b.pi('target').tag, ET.PI)
    4232          if is_lxml:
    4233              self.assertEqual(b.pi('target').target, "target")
    4234          else:
    4235              self.assertEqual(b.pi('target').text, "target")
    4236          self.assertEqual(b.pi('pitarget', ' text ').tag, ET.PI)
    4237          if is_lxml:
    4238              self.assertEqual(b.pi('pitarget', ' text ').target, "pitarget")
    4239              self.assertEqual(b.pi('pitarget', ' text ').text, " text ")
    4240          else:
    4241              self.assertEqual(b.pi('pitarget', ' text ').text, "pitarget  text ")
    4242
    4243          #b = ET.TreeBuilder(pi_factory=lambda target, text: (len(target), text))
    4244          #self.assertEqual(b.pi('target'), (len('target'), None))
    4245          #self.assertEqual(b.pi('pitarget', ' text '), (len('pitarget'), ' text '))
    4246
    4247 -    def test_late_tail(self):
    4248          # Issue #37399: The tail of an ignored comment could overwrite the text before it.
    4249          ET = self.etree
    4250          class TreeBuilderSubclass(ET.TreeBuilder):
    4251              pass
    4252
    4253          if ET.__name__ == 'lxml.etree':
    4254              def assert_content(a):
    4255                  self.assertEqual(a.text, "text")
    4256                  self.assertEqual(a[0].tail, "tail")
    4257          else:
    4258              def assert_content(a):
    4259                  self.assertEqual(a.text, "texttail")
    4260
    4261          xml = "<a>text<!-- comment -->tail</a>"
    4262          a = ET.fromstring(xml)
    4263          assert_content(a)
    4264
    4265          parser = ET.XMLParser(target=TreeBuilderSubclass())
    4266          parser.feed(xml)
    4267          a = parser.close()
    4268          assert_content(a)
    4269
    4270          xml = "<a>text<?pi data?>tail</a>"
    4271          a = ET.fromstring(xml)
    4272          assert_content(a)
    4273
    4274          xml = "<a>text<?pi data?>tail</a>"
    4275          parser = ET.XMLParser(target=TreeBuilderSubclass())
    4276          parser.feed(xml)
    4277          a = parser.close()
    4278          assert_content(a)
    4279
    4280      @et_needs_pyversion(3, 8, 0, 'alpha', 4)
    4281 -    def test_late_tail_mix_pi_comments(self):
    4282          # Issue #37399: The tail of an ignored comment could overwrite the text before it.
    4283          # Test appending tails to comments/pis.
    4284          ET = self.etree
    4285          class TreeBuilderSubclass(ET.TreeBuilder):
    4286              pass
    4287
    4288          xml = "<a>text<?pi1?> <!-- comment -->\n<?pi2?>tail</a>"
    4289          parser = ET.XMLParser(target=ET.TreeBuilder(insert_comments=True, insert_pis=False))
    4290          parser.feed(xml)
    4291          a = parser.close()
    4292          self.assertEqual(a[0].text, ' comment ')
    4293          self.assertEqual(a[0].tail, '\ntail')
    4294          self.assertEqual(a.text, "text ")
    4295
    4296          parser = ET.XMLParser(target=TreeBuilderSubclass(insert_comments=True, insert_pis=False))
    4297          parser.feed(xml)
    4298          a = parser.close()
    4299          self.assertEqual(a[0].text, ' comment ')
    4300          self.assertEqual(a[0].tail, '\ntail')
    4301          self.assertEqual(a.text, "text ")
    4302
    4303          xml = "<a>text<!-- comment -->\n<?pi data?>tail</a>"
    4304          parser = ET.XMLParser(target=ET.TreeBuilder(insert_pis=True, insert_comments=False))
    4305          parser.feed(xml)
    4306          a = parser.close()
    4307          self.assertEqual(a[0].text[-4:], 'data')
    4308          self.assertEqual(a[0].tail, 'tail')
    4309          self.assertEqual(a.text, "text\n")
    4310
    4311          parser = ET.XMLParser(target=TreeBuilderSubclass(insert_pis=True, insert_comments=False))
    4312          parser.feed(xml)
    4313          a = parser.close()
    4314          self.assertEqual(a[0].text[-4:], 'data')
    4315          self.assertEqual(a[0].tail, 'tail')
    4316          self.assertEqual(a.text, "text\n")
    4317
    4318      # helper methods
    4319
    4320 -    def _writeElement(self, element, encoding='us-ascii'):
    4321          """Write out element for comparison.
    4322          """
    4323          data = self.etree.tostring(element, encoding=encoding)
    4324          return canonicalize(data)
    4325
    4326 -    def _writeElementFile(self, element, encoding='us-ascii'):
    4327          """Write out element for comparison, using real file.
    4328          """
    4329          ElementTree = self.etree.ElementTree
    4330          with tmpfile() as filename:
    4331              with open(filename, 'wb') as f:
    4332                  tree = ElementTree(element=element)
    4333                  tree.write(f, encoding=encoding)
    4334              with open(filename, 'rb') as f:
    4335                  data = f.read()
    4336          return canonicalize(data)
    4337
    4338 -    def assertXML(self, expected, element, encoding='us-ascii'):
    4339          """Writes element out and checks whether it is expected.
    4340
    4341          Does this two ways; once using BytesIO, once using a real file.
    4342          """
    4343          if isinstance(expected, unicode):
    4344              expected = expected.encode(encoding)
    4345          self.assertEqual(expected, self._writeElement(element, encoding))
    4346          self.assertEqual(expected, self._writeElementFile(element, encoding))
    4347
    4348 -    def assertEncodingDeclaration(self, result, encoding):
    4349          "Checks if the result XML byte string specifies the encoding."
    4350          enc_re = r"<\?xml[^>]+ encoding=[\"']([^\"']+)[\"']"
    4351          if isinstance(result, str):
    4352              has_encoding = re.compile(enc_re).match
    4353          else:
    4354              has_encoding = re.compile(_bytes(enc_re)).match
    4355          self.assertTrue(has_encoding(result))
    4356          result_encoding = has_encoding(result).group(1)
    4357          self.assertEqual(result_encoding.upper(), encoding.upper())
    4358
    4359 -    def _rootstring(self, tree):
    4360          return self.etree.tostring(tree.getroot()).replace(
    4361              _bytes(' '), _bytes('')).replace(_bytes('\n'), _bytes(''))
    4362
    4363 -    def _check_element_tree(self, tree):
    4364          self._check_element(tree.getroot())
    4365
    4366 -    def _check_element(self, element):
    4367          self.assertTrue(hasattr(element, 'tag'))
    4368          self.assertTrue(hasattr(element, 'attrib'))
    4369          self.assertTrue(hasattr(element, 'text'))
    4370          self.assertTrue(hasattr(element, 'tail'))
    4371          self._check_string(element.tag)
    4372          self._check_mapping(element.attrib)
    4373          if element.text is not None:
    4374              self._check_string(element.text)
    4375          if element.tail is not None:
    4376              self._check_string(element.tail)
    4377
    4378 -    def _check_string(self, string):
    4379          len(string)
    4380          for char in string:
    4381              self.assertEqual(1, len(char))
    4382          new_string = string + ""
    4383          new_string = string + " "
    4384          string[:0]
    4385
    4386 -    def _check_mapping(self, mapping):
    4387          len(mapping)
    4388          keys = mapping.keys()
    4389          values = mapping.values()
    4390          items = mapping.items()
    4391          for key in keys:
    4392              item = mapping[key]
    4393          mapping["key"] = "value"
    4394          self.assertEqual("value", mapping["key"])
    4395
    4396
    4397 -class _ElementSlicingTest(unittest.TestCase):
    4398      etree = None
    4399
    4400 -    def _elem_tags(self, elemlist):
    4401          return [e.tag for e in elemlist]
    4402
    4403 -    def _subelem_tags(self, elem):
    4404          return self._elem_tags(list(elem))
    4405
    4406 -    def _make_elem_with_children(self, numchildren):
    4407          """Create an Element with a tag 'a', with the given amount of children
    4408             named 'a0', 'a1' ... and so on.
    4409
    4410          """
    4411          e = self.etree.Element('a')
    4412          for i in range(numchildren):
    4413              self.etree.SubElement(e, 'a%s' % i)
    4414          return e
    4415
    4416 -    def test_getslice_single_index(self):
    4417          e = self._make_elem_with_children(10)
    4418
    4419          self.assertEqual(e[1].tag, 'a1')
    4420          self.assertEqual(e[-2].tag, 'a8')
    4421
    4422          self.assertRaises(IndexError, lambda: e[12])
    4423          self.assertRaises(IndexError, lambda: e[-12])
    4424
    4425 -    def test_getslice_range(self):
    4426          e = self._make_elem_with_children(6)
    4427
    4428          self.assertEqual(self._elem_tags(e[3:]), ['a3', 'a4', 'a5'])
    4429          self.assertEqual(self._elem_tags(e[3:6]), ['a3', 'a4', 'a5'])
    4430          self.assertEqual(self._elem_tags(e[3:16]), ['a3', 'a4', 'a5'])
    4431          self.assertEqual(self._elem_tags(e[3:5]), ['a3', 'a4'])
    4432          self.assertEqual(self._elem_tags(e[3:-1]), ['a3', 'a4'])
    4433          self.assertEqual(self._elem_tags(e[:2]), ['a0', 'a1'])
    4434
    4435 -    def test_getslice_steps(self):
    4436          e = self._make_elem_with_children(10)
    4437
    4438          self.assertEqual(self._elem_tags(e[8:10:1]), ['a8', 'a9'])
    4439          self.assertEqual(self._elem_tags(e[::3]), ['a0', 'a3', 'a6', 'a9'])
    4440          self.assertEqual(self._elem_tags(e[::8]), ['a0', 'a8'])
    4441          self.assertEqual(self._elem_tags(e[1::8]), ['a1', 'a9'])
    4442          self.assertEqual(self._elem_tags(e[3::sys.maxsize]), ['a3'])
    4443          self.assertEqual(self._elem_tags(e[3::sys.maxsize<<64]), ['a3'])
    4444
    4445 -    def test_getslice_negative_steps(self):
    4446          e = self._make_elem_with_children(4)
    4447
    4448          self.assertEqual(self._elem_tags(e[::-1]), ['a3', 'a2', 'a1', 'a0'])
    4449          self.assertEqual(self._elem_tags(e[::-2]), ['a3', 'a1'])
    4450          self.assertEqual(self._elem_tags(e[3::-sys.maxsize]), ['a3'])
    4451          self.assertEqual(self._elem_tags(e[3::-sys.maxsize-1]), ['a3'])
    4452          self.assertEqual(self._elem_tags(e[3::-sys.maxsize<<64]), ['a3'])
    4453
    4454 -    def test_delslice(self):
    4455          e = self._make_elem_with_children(4)
    4456          del e[0:2]
    4457          self.assertEqual(self._subelem_tags(e), ['a2', 'a3'])
    4458
    4459          e = self._make_elem_with_children(4)
    4460          del e[0:]
    4461          self.assertEqual(self._subelem_tags(e), [])
    4462
    4463          e = self._make_elem_with_children(4)
    4464          del e[::-1]
    4465          self.assertEqual(self._subelem_tags(e), [])
    4466
    4467          e = self._make_elem_with_children(4)
    4468          del e[::-2]
    4469          self.assertEqual(self._subelem_tags(e), ['a0', 'a2'])
    4470
    4471          e = self._make_elem_with_children(4)
    4472          del e[1::2]
    4473          self.assertEqual(self._subelem_tags(e), ['a0', 'a2'])
    4474
    4475          e = self._make_elem_with_children(2)
    4476          del e[::2]
    4477          self.assertEqual(self._subelem_tags(e), ['a1'])
    4478
    4479 -    def test_setslice_single_index(self):
    4480          e = self._make_elem_with_children(4)
    4481          e[1] = self.etree.Element('b')
    4482          self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
    4483
    4484          e[-2] = self.etree.Element('c')
    4485          self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'c', 'a3'])
    4486
    4487          with self.assertRaises(IndexError):
    4488              e[5] = self.etree.Element('d')
    4489          with self.assertRaises(IndexError):
    4490              e[-5] = self.etree.Element('d')
    4491          self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'c', 'a3'])
    4492
    4493 -    def test_setslice_range(self):
    4494          e = self._make_elem_with_children(4)
    4495          e[1:3] = [self.etree.Element('b%s' % i) for i in range(2)]
    4496          self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'b1', 'a3'])
    4497
    4498          e = self._make_elem_with_children(4)
    4499          e[1:3] = [self.etree.Element('b')]
    4500          self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a3'])
    4501
    4502          e = self._make_elem_with_children(4)
    4503          e[1:3] = [self.etree.Element('b%s' % i) for i in range(3)]
    4504          self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'b1', 'b2', 'a3'])
    4505
    4506 -    def test_setslice_steps(self):
    4507          e = self._make_elem_with_children(6)
    4508          e[1:5:2] = [self.etree.Element('b%s' % i) for i in range(2)]
    4509          self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'a2', 'b1', 'a4', 'a5'])
    4510
    4511          e = self._make_elem_with_children(6)
    4512          with self.assertRaises(ValueError):
    4513              e[1:5:2] = [self.etree.Element('b')]
    4514          with self.assertRaises(ValueError):
    4515              e[1:5:2] = [self.etree.Element('b%s' % i) for i in range(3)]
    4516          with self.assertRaises(ValueError):
    4517              e[1:5:2] = []
    4518          self.assertEqual(self._subelem_tags(e), ['a0', 'a1', 'a2', 'a3', 'a4', 'a5'])
    4519
    4520          e = self._make_elem_with_children(4)
    4521          e[1::sys.maxsize] = [self.etree.Element('b')]
    4522          self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
    4523          e[1::sys.maxsize<<64] = [self.etree.Element('c')]
    4524          self.assertEqual(self._subelem_tags(e), ['a0', 'c', 'a2', 'a3'])
    4525
    4526 -    def test_setslice_negative_steps(self):
    4527          e = self._make_elem_with_children(4)
    4528          e[2:0:-1] = [self.etree.Element('b%s' % i) for i in range(2)]
    4529          self.assertEqual(self._subelem_tags(e), ['a0', 'b1', 'b0', 'a3'])
    4530
    4531          e = self._make_elem_with_children(4)
    4532          with self.assertRaises(ValueError):
    4533              e[2:0:-1] = [self.etree.Element('b')]
    4534          with self.assertRaises(ValueError):
    4535              e[2:0:-1] = [self.etree.Element('b%s' % i) for i in range(3)]
    4536          with self.assertRaises(ValueError):
    4537              e[2:0:-1] = []
    4538          self.assertEqual(self._subelem_tags(e), ['a0', 'a1', 'a2', 'a3'])
    4539
    4540          e = self._make_elem_with_children(4)
    4541          e[1::-sys.maxsize] = [self.etree.Element('b')]
    4542          self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
    4543          e[1::-sys.maxsize-1] = [self.etree.Element('c')]
    4544          self.assertEqual(self._subelem_tags(e), ['a0', 'c', 'a2', 'a3'])
    4545          e[1::-sys.maxsize<<64] = [self.etree.Element('d')]
    4546          self.assertEqual(self._subelem_tags(e), ['a0', 'd', 'a2', 'a3'])
    4547
    4548
    4549 -class _XMLPullParserTest(unittest.TestCase):
    4550      etree = None
    4551
    4552 -    def _close_and_return_root(self, parser):
    4553          if 'ElementTree' in self.etree.__name__:
    4554              # ElementTree's API is a bit unwieldy in Py3.4
    4555              root = parser._close_and_return_root()
    4556          else:
    4557              root = parser.close()
    4558          return root
    4559
    4560 -    def _feed(self, parser, data, chunk_size=None):
    4561          if chunk_size is None:
    4562              parser.feed(data)
    4563          else:
    4564              for i in range(0, len(data), chunk_size):
    4565                  parser.feed(data[i:i+chunk_size])
    4566
    4567 -    def assert_events(self, parser, expected, max_events=None):
    4568          self.assertEqual(
    4569              [(event, (elem.tag, elem.text))
    4570               for event, elem in islice(parser.read_events(), max_events)],
    4571              expected)
    4572
    4573 -    def assert_event_tuples(self, parser, expected, max_events=None):
    4574          self.assertEqual(
    4575              list(islice(parser.read_events(), max_events)),
    4576              expected)
    4577
    4578 -    def assert_event_tags(self, parser, expected, max_events=None):
    4579          events = islice(parser.read_events(), max_events)
    4580          self.assertEqual([(action, elem.tag) for action, elem in events],
    4581                           expected)
    4582
    4583 -    def test_simple_xml(self):
    4584          for chunk_size in (None, 1, 5):
    4585              #with self.subTest(chunk_size=chunk_size):
    4586                  parser = self.etree.XMLPullParser()
    4587                  self.assert_event_tags(parser, [])
    4588                  self._feed(parser, "<!-- comment -->\n", chunk_size)
    4589                  self.assert_event_tags(parser, [])
    4590                  self._feed(parser,
    4591                             "<root>\n  <element key='value'>text</element",
    4592                             chunk_size)
    4593                  self.assert_event_tags(parser, [])
    4594                  self._feed(parser, ">\n", chunk_size)
    4595                  self.assert_event_tags(parser, [('end', 'element')])
    4596                  self._feed(parser, "<element>text</element>tail\n", chunk_size)
    4597                  self._feed(parser, "<empty-element/>\n", chunk_size)
    4598                  self.assert_event_tags(parser, [
    4599                      ('end', 'element'),
    4600                      ('end', 'empty-element'),
    4601                      ])
    4602                  self._feed(parser, "</root>\n", chunk_size)
    4603                  self.assert_event_tags(parser, [('end', 'root')])
    4604                  root = self._close_and_return_root(parser)
    4605                  self.assertEqual(root.tag, 'root')
    4606
    4607 -    def test_feed_while_iterating(self):
    4608          parser = self.etree.XMLPullParser()
    4609          it = parser.read_events()
    4610          self._feed(parser, "<root>\n  <element key='value'>text</element>\n")
    4611          action, elem = next(it)
    4612          self.assertEqual((action, elem.tag), ('end', 'element'))
    4613          self._feed(parser, "</root>\n")
    4614          action, elem = next(it)
    4615          self.assertEqual((action, elem.tag), ('end', 'root'))
    4616          with self.assertRaises(StopIteration):
    4617              next(it)
    4618
    4619 -    def test_simple_xml_with_ns(self):
    4620          parser = self.etree.XMLPullParser()
    4621          self.assert_event_tags(parser, [])
    4622          self._feed(parser, "<!-- comment -->\n")
    4623          self.assert_event_tags(parser, [])
    4624          self._feed(parser, "<root xmlns='namespace'>\n")
    4625          self.assert_event_tags(parser, [])
    4626          self._feed(parser, "<element key='value'>text</element")
    4627          self.assert_event_tags(parser, [])
    4628          self._feed(parser, ">\n")
    4629          self.assert_event_tags(parser, [('end', '{namespace}element')])
    4630          self._feed(parser, "<element>text</element>tail\n")
    4631          self._feed(parser, "<empty-element/>\n")
    4632          self.assert_event_tags(parser, [
    4633              ('end', '{namespace}element'),
    4634              ('end', '{namespace}empty-element'),
    4635              ])
    4636          self._feed(parser, "</root>\n")
    4637          self.assert_event_tags(parser, [('end', '{namespace}root')])
    4638          root = self._close_and_return_root(parser)
    4639          self.assertEqual(root.tag, '{namespace}root')
    4640
    4641 -    def test_ns_events(self):
    4642          parser = self.etree.XMLPullParser(events=('start-ns', 'end-ns'))
    4643          self._feed(parser, "<!-- comment -->\n")
    4644          self._feed(parser, "<root xmlns='namespace'>\n")
    4645          self.assertEqual(
    4646              list(parser.read_events()),
    4647              [('start-ns', ('', 'namespace'))])
    4648          self._feed(parser, "<element key='value'>text</element")
    4649          self._feed(parser, ">\n")
    4650          self._feed(parser, "<element>text</element>tail\n")
    4651          self._feed(parser, "<empty-element/>\n")
    4652          self._feed(parser, "</root>\n")
    4653          self.assertEqual(list(parser.read_events()), [('end-ns', None)])
    4654          parser.close()
    4655
    4656 -    def test_ns_events_end_ns_only(self):
    4657          parser = self.etree.XMLPullParser(events=['end-ns'])
    4658          self._feed(parser, "<!-- comment -->\n")
    4659          self._feed(parser, "<root xmlns='namespace' xmlns:a='abc' xmlns:b='xyz'>\n")
    4660          self.assertEqual(list(parser.read_events()), [])
    4661          self._feed(parser, "<a:element key='value'>text</a:element")
    4662          self._feed(parser, ">\n")
    4663          self._feed(parser, "<b:element>text</b:element>tail\n")
    4664          self._feed(parser, "<empty-element/>\n")
    4665          self.assertEqual(list(parser.read_events()), [])
    4666          self._feed(parser, "</root>\n")
    4667          self.assertEqual(list(parser.read_events()), [
    4668              ('end-ns', None),
    4669              ('end-ns', None),
    4670              ('end-ns', None),
    4671          ])
    4672          parser.close()
    4673
    4674      @et_needs_pyversion(3,8)
    4675 -    def test_ns_events_start(self):
    4676          parser = self.etree.XMLPullParser(events=('start-ns', 'start', 'end'))
    4677          self._feed(parser, "<tag xmlns='abc' xmlns:p='xyz'>\n")
    4678          self.assert_event_tuples(parser, [
    4679              ('start-ns', ('', 'abc')),
    4680              ('start-ns', ('p', 'xyz')),
    4681          ], max_events=2)
    4682          self.assert_event_tags(parser, [
    4683              ('start', '{abc}tag'),
    4684          ], max_events=1)
    4685
    4686          self._feed(parser, "<child />\n")
    4687          self.assert_event_tags(parser, [
    4688              ('start', '{abc}child'),
    4689              ('end', '{abc}child'),
    4690          ])
    4691
    4692          self._feed(parser, "</tag>\n")
    4693          parser.close()
    4694          self.assert_event_tags(parser, [
    4695              ('end', '{abc}tag'),
    4696          ])
    4697
    4698      @et_needs_pyversion(3,8)
    4699 -    def test_ns_events_start_end(self):
    4700          parser = self.etree.XMLPullParser(events=('start-ns', 'start', 'end', 'end-ns'))
    4701          self._feed(parser, "<tag xmlns='abc' xmlns:p='xyz'>\n")
    4702          self.assert_event_tuples(parser, [
    4703              ('start-ns', ('', 'abc')),
    4704              ('start-ns', ('p', 'xyz')),
    4705          ], max_events=2)
    4706          self.assert_event_tags(parser, [
    4707              ('start', '{abc}tag'),
    4708          ], max_events=1)
    4709
    4710          self._feed(parser, "<child />\n")
    4711          self.assert_event_tags(parser, [
    4712              ('start', '{abc}child'),
    4713              ('end', '{abc}child'),
    4714          ])
    4715
    4716          self._feed(parser, "</tag>\n")
    4717          parser.close()
    4718          self.assert_event_tags(parser, [
    4719              ('end', '{abc}tag'),
    4720          ], max_events=1)
    4721          self.assert_event_tuples(parser, [
    4722              ('end-ns', None),
    4723              ('end-ns', None),
    4724          ])
    4725
    4726 -    def test_events(self):
    4727          parser = self.etree.XMLPullParser(events=())
    4728          self._feed(parser, "<root/>\n")
    4729          self.assert_event_tags(parser, [])
    4730
    4731          parser = self.etree.XMLPullParser(events=('start', 'end'))
    4732          self._feed(parser, "<!-- text here -->\n")
    4733          self.assert_events(parser, [])
    4734
    4735          parser = self.etree.XMLPullParser(events=('start', 'end'))
    4736          self._feed(parser, "<root>\n")
    4737          self.assert_event_tags(parser, [('start', 'root')])
    4738          self._feed(parser, "<element key='value'>text</element")
    4739          self.assert_event_tags(parser, [('start', 'element')])
    4740          self._feed(parser, ">\n")
    4741          self.assert_event_tags(parser, [('end', 'element')])
    4742          self._feed(parser,
    4743                     "<element xmlns='foo'>text<empty-element/></element>tail\n")
    4744          self.assert_event_tags(parser, [
    4745              ('start', '{foo}element'),
    4746              ('start', '{foo}empty-element'),
    4747              ('end', '{foo}empty-element'),
    4748              ('end', '{foo}element'),
    4749              ])
    4750          self._feed(parser, "</root>")
    4751          root = self._close_and_return_root(parser)
    4752          self.assert_event_tags(parser, [('end', 'root')])
    4753          self.assertEqual(root.tag, 'root')
    4754
    4755          parser = self.etree.XMLPullParser(events=('start',))
    4756          self._feed(parser, "<!-- comment -->\n")
    4757          self.assert_event_tags(parser, [])
    4758          self._feed(parser, "<root>\n")
    4759          self.assert_event_tags(parser, [('start', 'root')])
    4760          self._feed(parser, "<element key='value'>text</element")
    4761          self.assert_event_tags(parser, [('start', 'element')])
    4762          self._feed(parser, ">\n")
    4763          self.assert_event_tags(parser, [])
    4764          self._feed(parser,
    4765                     "<element xmlns='foo'>text<empty-element/></element>tail\n")
    4766          self.assert_event_tags(parser, [
    4767              ('start', '{foo}element'),
    4768              ('start', '{foo}empty-element'),
    4769              ])
    4770          self._feed(parser, "</root>")
    4771          root = self._close_and_return_root(parser)
    4772          self.assertEqual(root.tag, 'root')
    4773
    4774      @et_needs_pyversion(3, 8, 0, 'alpha', 4)
    4775 -    def test_events_comment(self):
    4776          parser = self.etree.XMLPullParser(events=('start', 'comment', 'end'))
    4777          self._feed(parser, "<!-- text here -->\n")
    4778          self.assert_events(parser, [('comment', (self.etree.Comment, ' text here '))])
    4779          self._feed(parser, "<!-- more text here -->\n")
    4780          self.assert_events(parser, [('comment', (self.etree.Comment, ' more text here '))])
    4781          self._feed(parser, "<root-tag>text")
    4782          self.assert_event_tags(parser, [('start', 'root-tag')])
    4783          self._feed(parser, "<!-- inner comment-->\n")
    4784          self.assert_events(parser, [('comment', (self.etree.Comment, ' inner comment'))])
    4785          self._feed(parser, "</root-tag>\n")
    4786          self.assert_event_tags(parser, [('end', 'root-tag')])
    4787          self._feed(parser, "<!-- outer comment -->\n")
    4788          self.assert_events(parser, [('comment', (self.etree.Comment, ' outer comment '))])
    4789
    4790          parser = self.etree.XMLPullParser(events=('comment',))
    4791          self._feed(parser, "<!-- text here -->\n")
    4792          self.assert_events(parser, [('comment', (self.etree.Comment, ' text here '))])
    4793
    4794      @et_needs_pyversion(3, 8, 0, 'alpha', 4)
    4795 -    def test_events_pi(self):
    4796          # Note: lxml's PIs have target+text, ET's PIs have both in "text"
    4797          parser = self.etree.XMLPullParser(events=('start', 'pi', 'end'))
    4798          self._feed(parser, "<?pitarget?>\n")
    4799          self.assert_event_tags(parser, [('pi', self.etree.PI)])
    4800          parser = self.etree.XMLPullParser(events=('pi',))
    4801          self._feed(parser, "<?pitarget some text ?>\n")
    4802          self.assert_event_tags(parser, [('pi', self.etree.PI)])
    4803
    4804 -    def test_events_sequence(self):
    4805          # Test that events can be some sequence that's not just a tuple or list
    4806          eventset = {'end', 'start'}
    4807          parser = self.etree.XMLPullParser(events=eventset)
    4808          self._feed(parser, "<foo>bar</foo>")
    4809          self.assert_event_tags(parser, [('start', 'foo'), ('end', 'foo')])
    4810
    4811          class DummyIter(object):
    4812              def __init__(self):
    4813                  self.events = iter(['start', 'end', 'start-ns'])
    4814              def __iter__(self):
    4815                  return self
    4816              def __next__(self):
    4817                  return next(self.events)
    4818              def next(self):
    4819                  return next(self.events)
    4820
    4821          parser = self.etree.XMLPullParser(events=DummyIter())
    4822          self._feed(parser, "<foo>bar</foo>")
    4823          self.assert_event_tags(parser, [('start', 'foo'), ('end', 'foo')])
    4824
    4825 -    def test_unknown_event(self):
    4826          with self.assertRaises(ValueError):
    4827              self.etree.XMLPullParser(events=('start', 'end', 'bogus'))
    4828
    4829
    4830 -class _C14NTest(unittest.TestCase):
    4831      etree = None
    4832      maxDiff = None
    4833
    4834      if not hasattr(unittest.TestCase, 'subTest'):
    4835          @contextmanager
    4836 -        def subTest(self, name, **kwargs):
    4837              try:
    4838                  yield
    4839              except unittest.SkipTest:
    4840                  raise
    4841              except Exception as e:
    4842                  print("Subtest {} failed: {}".format(name, e))
    4843                  raise
    4844
    4845 -    def _canonicalize(self, input_file, **options):
    4846          return self.etree.canonicalize(from_file=input_file, **options)
    4847
    4848      #
    4849      # simple roundtrip tests (from c14n.py)
    4850
    4851 -    def c14n_roundtrip(self, xml, **options):
    4852          return self.etree.canonicalize(xml, **options)
    4853
    4854 -    def test_simple_roundtrip(self):
    4855          c14n_roundtrip = self.c14n_roundtrip
    4856          # Basics
    4857          self.assertEqual(c14n_roundtrip("<doc/>"), '<doc></doc>')
    4858          self.assertEqual(c14n_roundtrip("<doc xmlns='uri'/>"), # FIXME
    4859                  '<doc xmlns="uri"></doc>')
    4860          self.assertEqual(c14n_roundtrip("<prefix:doc xmlns:prefix='uri'/>"),
    4861              '<prefix:doc xmlns:prefix="uri"></prefix:doc>')
    4862          self.assertEqual(c14n_roundtrip("<doc xmlns:prefix='uri'><prefix:bar/></doc>"),
    4863              '<doc><prefix:bar xmlns:prefix="uri"></prefix:bar></doc>')
    4864          self.assertEqual(c14n_roundtrip("<elem xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' />"),
    4865              '<elem></elem>')
    4866
    4867          # C14N spec
    4868          self.assertEqual(c14n_roundtrip("<doc>Hello, world!<!-- Comment 1 --></doc>"),
    4869              '<doc>Hello, world!</doc>')
    4870          self.assertEqual(c14n_roundtrip("<value>&#x32;</value>"),
    4871              '<value>2</value>')
    4872          self.assertEqual(c14n_roundtrip('<compute><![CDATA[value>"0" && value<"10" ?"valid":"error"]]></compute>'),
    4873              '<compute>value&gt;"0" &amp;&amp; value&lt;"10" ?"valid":"error"</compute>')
    4874          self.assertEqual(c14n_roundtrip('''<compute expr='value>"0" &amp;&amp; value&lt;"10" ?"valid":"error"'>valid</compute>'''),
    4875              '<compute expr="value>&quot;0&quot; &amp;&amp; value&lt;&quot;10&quot; ?&quot;valid&quot;:&quot;error&quot;">valid</compute>')
    4876          self.assertEqual(c14n_roundtrip("<norm attr=' &apos;   &#x20;&#13;&#xa;&#9;   &apos; '/>"),
    4877              '<norm attr=" \'    &#xD;&#xA;&#x9;   \' "></norm>')
    4878          self.assertEqual(c14n_roundtrip("<normNames attr='   A   &#x20;&#13;&#xa;&#9;   B   '/>"),
    4879              '<normNames attr="   A    &#xD;&#xA;&#x9;   B   "></normNames>')
    4880          self.assertEqual(c14n_roundtrip("<normId id=' &apos;   &#x20;&#13;&#xa;&#9;   &apos; '/>"),
    4881              '<normId id=" \'    &#xD;&#xA;&#x9;   \' "></normId>')
    4882
    4883          # fragments from PJ's tests
    4884          #self.assertEqual(c14n_roundtrip("<doc xmlns:x='http://example.com/x' xmlns='http://example.com/default'><b y:a1='1' xmlns='http://example.com/default' a3='3' xmlns:y='http://example.com/y' y:a2='2'/></doc>"),
    4885          #'<doc xmlns:x="http://example.com/x"><b xmlns:y="http://example.com/y" a3="3" y:a1="1" y:a2="2"></b></doc>')
    4886
    4887 -    def test_c14n_exclusion(self):
    4888          c14n_roundtrip = self.c14n_roundtrip
    4889          xml = textwrap.dedent("""\
    4890          <root xmlns:x="http://example.com/x">
    4891              <a x:attr="attrx">
    4892                  <b>abtext</b>
    4893              </a>
    4894              <b>btext</b>
    4895              <c>
    4896                  <x:d>dtext</x:d>
    4897              </c>
    4898          </root>
    4899          """)
    4900          self.assertEqual(
    4901              c14n_roundtrip(xml, strip_text=True),
    4902              '<root>'
    4903              '<a xmlns:x="http://example.com/x" x:attr="attrx"><b>abtext</b></a>'
    4904              '<b>btext</b>'
    4905              '<c><x:d xmlns:x="http://example.com/x">dtext</x:d></c>'
    4906              '</root>')
    4907          self.assertEqual(
    4908              c14n_roundtrip(xml, strip_text=True, exclude_attrs=['{http://example.com/x}attr']),
    4909              '<root>'
    4910              '<a><b>abtext</b></a>'
    4911              '<b>btext</b>'
    4912              '<c><x:d xmlns:x="http://example.com/x">dtext</x:d></c>'
    4913              '</root>')
    4914          self.assertEqual(
    4915              c14n_roundtrip(xml, strip_text=True, exclude_tags=['{http://example.com/x}d']),
    4916              '<root>'
    4917              '<a xmlns:x="http://example.com/x" x:attr="attrx"><b>abtext</b></a>'
    4918              '<b>btext</b>'
    4919              '<c></c>'
    4920              '</root>')
    4921          self.assertEqual(
    4922              c14n_roundtrip(xml, strip_text=True, exclude_attrs=['{http://example.com/x}attr'],
    4923                             exclude_tags=['{http://example.com/x}d']),
    4924              '<root>'
    4925              '<a><b>abtext</b></a>'
    4926              '<b>btext</b>'
    4927              '<c></c>'
    4928              '</root>')
    4929          self.assertEqual(
    4930              c14n_roundtrip(xml, strip_text=True, exclude_tags=['a', 'b']),
    4931              '<root>'
    4932              '<c><x:d xmlns:x="http://example.com/x">dtext</x:d></c>'
    4933              '</root>')
    4934          self.assertEqual(
    4935              c14n_roundtrip(xml, exclude_tags=['a', 'b']),
    4936              '<root>\n'
    4937              '    \n'
    4938              '    \n'
    4939              '    <c>\n'
    4940              '        <x:d xmlns:x="http://example.com/x">dtext</x:d>\n'
    4941              '    </c>\n'
    4942              '</root>')
    4943          self.assertEqual(
    4944              c14n_roundtrip(xml, strip_text=True, exclude_tags=['{http://example.com/x}d', 'b']),
    4945              '<root>'
    4946              '<a xmlns:x="http://example.com/x" x:attr="attrx"></a>'
    4947              '<c></c>'
    4948              '</root>')
    4949          self.assertEqual(
    4950              c14n_roundtrip(xml, exclude_tags=['{http://example.com/x}d', 'b']),
    4951              '<root>\n'
    4952              '    <a xmlns:x="http://example.com/x" x:attr="attrx">\n'
    4953              '        \n'
    4954              '    </a>\n'
    4955              '    \n'
    4956              '    <c>\n'
    4957              '        \n'
    4958              '    </c>\n'
    4959              '</root>')
    4960
    4961      #
    4962      # basic method=c14n tests from the c14n 2.0 specification.  uses
    4963      # test files under xmltestdata/c14n-20.
    4964
    4965      # note that this uses generated C14N versions of the standard ET.write
    4966      # output, not roundtripped C14N (see above).
    4967
    4968 -    def test_xml_c14n2(self):
    4969          datadir = os.path.join(os.path.dirname(__file__), "c14n-20")
    4970          full_path = partial(os.path.join, datadir)
    4971
    4972          files = [filename[:-4] for filename in sorted(os.listdir(datadir))
    4973                   if filename.endswith('.xml')]
    4974          input_files = [
    4975              filename for filename in files
    4976              if filename.startswith('in')
    4977          ]
    4978          configs = {
    4979              filename: {
    4980                  # <c14n2:PrefixRewrite>sequential</c14n2:PrefixRewrite>
    4981                  option.tag.split('}')[-1]: ((option.text or '').strip(), option)
    4982                  for option in self.etree.parse(full_path(filename) + ".xml").getroot()
    4983              }
    4984              for filename in files
    4985              if filename.startswith('c14n')
    4986          }
    4987
    4988          tests = {
    4989              input_file: [
    4990                  (filename, configs[filename.rsplit('_', 1)[-1]])
    4991                  for filename in files
    4992                  if filename.startswith('out_%s_' % input_file)
    4993                  and filename.rsplit('_', 1)[-1] in configs
    4994              ]
    4995              for input_file in input_files
    4996          }
    4997
    4998          # Make sure we found all test cases.
    4999          self.assertEqual(30, len([
    5000              output_file for output_files in tests.values()
    5001              for output_file in output_files]))
    5002
    5003          def get_option(config, option_name, default=None):
    5004              return config.get(option_name, (default, ()))[0]
    5005
    5006          for input_file, output_files in tests.items():
    5007              for output_file, config in output_files:
    5008                  keep_comments = get_option(
    5009                      config, 'IgnoreComments') == 'true'  # no, it's right :)
    5010                  strip_text = get_option(
    5011                      config, 'TrimTextNodes') == 'true'
    5012                  rewrite_prefixes = get_option(
    5013                      config, 'PrefixRewrite') == 'sequential'
    5014                  if 'QNameAware' in config:
    5015                      qattrs = [
    5016                          "{%s}%s" % (el.get('NS'), el.get('Name'))
    5017                          for el in config['QNameAware'][1].findall(
    5018                              '{http://www.w3.org/2010/xml-c14n2}QualifiedAttr')
    5019                      ]
    5020                      qtags = [
    5021                          "{%s}%s" % (el.get('NS'), el.get('Name'))
    5022                          for el in config['QNameAware'][1].findall(
    5023                              '{http://www.w3.org/2010/xml-c14n2}Element')
    5024                      ]
    5025                  else:
    5026                      qtags = qattrs = None
    5027
    5028                  # Build subtest description from config.
    5029                  config_descr = ','.join(
    5030                      "%s=%s" % (name, value or ','.join(c.tag.split('}')[-1] for c in children))
    5031                      for name, (value, children) in sorted(config.items())
    5032                  )
    5033
    5034                  with self.subTest("{}({})".format(output_file, config_descr)):
    5035                      if input_file == 'inNsRedecl' and not rewrite_prefixes:
    5036                          self.skipTest(
    5037                              "Redeclared namespace handling is not supported in {}".format(
    5038                                  output_file))
    5039                      if input_file == 'inNsSuperfluous' and not rewrite_prefixes:
    5040                          self.skipTest(
    5041                              "Redeclared namespace handling is not supported in {}".format(
    5042                                  output_file))
    5043                      if 'QNameAware' in config and config['QNameAware'][1].find(
    5044                              '{http://www.w3.org/2010/xml-c14n2}XPathElement') is not None:
    5045                          self.skipTest(
    5046                              "QName rewriting in XPath text is not supported in {}".format(
    5047                                  output_file))
    5048
    5049                      f = full_path(input_file + ".xml")
    5050                      if input_file == 'inC14N5':
    5051                          # Hack: avoid setting up external entity resolution in the parser.
    5052                          with open(full_path('world.txt'), 'rb') as entity_file:
    5053                              with open(f, 'rb') as f:
    5054                                  f = io.BytesIO(f.read().replace(b'&ent2;', entity_file.read().strip()))
    5055
    5056                      text = self._canonicalize(
    5057                          f,
    5058                          with_comments=keep_comments,
    5059                          strip_text=strip_text,
    5060                          rewrite_prefixes=rewrite_prefixes,
    5061                          qname_aware_tags=qtags, qname_aware_attrs=qattrs)
    5062
    5063                      with io.open(full_path(output_file + ".xml"), 'r', encoding='utf8') as f:
    5064                          expected = f.read()
    5065                      if input_file == 'inC14N3' and self.etree is not etree:
    5066                          # FIXME: cET resolves default attributes but ET does not!
    5067                          expected = expected.replace(' attr="default"', '')
    5068                          text = text.replace(' attr="default"', '')
    5069                      self.assertEqual(expected, text)
    5070
    5071
    5072  if etree:
    5073 -    class ETreeTestCase(_ETreeTestCaseBase):
    5074          etree = etree
    5075
    5076 -    class ETreePullTestCase(_XMLPullParserTest):
    5077          etree = etree
    5078
    5079 -    class ETreeElementSlicingTest(_ElementSlicingTest):
    5080          etree = etree
    5081
    5082 -    class ETreeC14NTest(_C14NTest):
    5083          etree = etree
    5084
    5085 -    class ETreeC14N2WriteTest(ETreeC14NTest):
    5086 -        def _canonicalize(self, input_file, with_comments=True, strip_text=False,
    5087                            rewrite_prefixes=False, qname_aware_tags=None, qname_aware_attrs=None,
    5088                            **options):
    5089              if rewrite_prefixes or qname_aware_attrs or qname_aware_tags:
    5090                  self.skipTest("C14N 2.0 feature not supported with ElementTree.write()")
    5091
    5092              parser = self.etree.XMLParser(attribute_defaults=True, collect_ids=False)
    5093              tree = self.etree.parse(input_file, parser)
    5094              out = io.BytesIO()
    5095              tree.write(
    5096                  out, method='c14n2',
    5097                  with_comments=with_comments, strip_text=strip_text,
    5098                  **options)
    5099              return out.getvalue().decode('utf8')
    5100
    5101 -    class ETreeC14N2TostringTest(ETreeC14NTest):
    5102 -        def _canonicalize(self, input_file, with_comments=True, strip_text=False,
    5103                            rewrite_prefixes=False, qname_aware_tags=None, qname_aware_attrs=None,
    5104                            **options):
    5105              if rewrite_prefixes or qname_aware_attrs or qname_aware_tags:
    5106                  self.skipTest("C14N 2.0 feature not supported with ElementTree.tostring()")
    5107
    5108              parser = self.etree.XMLParser(attribute_defaults=True, collect_ids=False)
    5109              tree = self.etree.parse(input_file, parser)
    5110              return self.etree.tostring(
    5111                  tree, method='c14n2',
    5112                  with_comments=with_comments, strip_text=strip_text,
    5113                  **options).decode('utf8')
    5114
    5115
    5116  if ElementTree:
    5117 -    class ElementTreeTestCase(_ETreeTestCaseBase):
    5118          etree = ElementTree
    5119
    5120          @classmethod
    5121 -        def setUpClass(cls):
    5122              import warnings
    5123              # ElementTree warns about getiterator() in recent Pythons
    5124              warnings.filterwarnings(
    5125                  'ignore',
    5126                  r'This method will be removed.*\.iter\(\).*instead',
    5127                  PendingDeprecationWarning)
    5128
    5129      filter_by_version(
    5130          ElementTreeTestCase,
    5131          ElementTreeTestCase.required_versions_ET, ET_VERSION)
    5132
    5133      if hasattr(ElementTree, 'XMLPullParser'):
    5134 -        class ElementTreePullTestCase(_XMLPullParserTest):
    5135              etree = ElementTree
    5136      else:
    5137          ElementTreePullTestCase = None
    5138
    5139      if hasattr(ElementTree, 'canonicalize'):
    5140 -        class ElementTreeC14NTest(_C14NTest):
    5141              etree = ElementTree
    5142      else:
    5143          ElementTreeC14NTest = None
    5144
    5145 -    class ElementTreeElementSlicingTest(_ElementSlicingTest):
    5146          etree = ElementTree
    5147
    5148
    5149  if cElementTree:
    5150 -    class CElementTreeTestCase(_ETreeTestCaseBase):
    5151          etree = cElementTree
    5152
    5153      filter_by_version(
    5154          CElementTreeTestCase,
    5155          CElementTreeTestCase.required_versions_cET, CET_VERSION)
    5156
    5157 -    class CElementTreeElementSlicingTest(_ElementSlicingTest):
    5158          etree = cElementTree
    5159
    5160
    5161 -def test_suite():
    5162      suite = unittest.TestSuite()
    5163      if etree:
    5164          suite.addTests([unittest.makeSuite(ETreeTestCase)])
    5165          suite.addTests([unittest.makeSuite(ETreePullTestCase)])
    5166          suite.addTests([unittest.makeSuite(ETreeElementSlicingTest)])
    5167          suite.addTests([unittest.makeSuite(ETreeC14NTest)])
    5168          suite.addTests([unittest.makeSuite(ETreeC14N2WriteTest)])
    5169          suite.addTests([unittest.makeSuite(ETreeC14N2TostringTest)])
    5170      if ElementTree:
    5171          suite.addTests([unittest.makeSuite(ElementTreeTestCase)])
    5172          if ElementTreePullTestCase:
    5173              suite.addTests([unittest.makeSuite(ElementTreePullTestCase)])
    5174          if ElementTreeC14NTest:
    5175              suite.addTests([unittest.makeSuite(ElementTreeC14NTest)])
    5176          suite.addTests([unittest.makeSuite(ElementTreeElementSlicingTest)])
    5177      if cElementTree:
    5178          suite.addTests([unittest.makeSuite(CElementTreeTestCase)])
    5179          suite.addTests([unittest.makeSuite(CElementTreeElementSlicingTest)])
    5180      return suite
    5181
    5182  if __name__ == '__main__':
    5183      print('to test use test.py %s' % __file__)
    5184