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  import copy
      12  import io
      13  import operator
      14  import os
      15  import re
      16  import sys
      17  import textwrap
      18  import unittest
      19  from contextlib import contextmanager
      20  from functools import wraps, partial
      21  from itertools import islice
      22
      23  this_dir = os.path.dirname(__file__)
      24  if this_dir not in sys.path:
      25      sys.path.insert(0, this_dir) # needed for Py3
      26
      27  from common_imports import BytesIO, etree, HelperTestCase
      28  from common_imports import ElementTree, cElementTree, ET_VERSION, CET_VERSION
      29  from common_imports import filter_by_version, fileInTestDir, canonicalize, tmpfile
      30  from common_imports import _str, _bytes, unicode, next, IS_PYTHON2
      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(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_clear(self):
    1703          Element = self.etree.Element
    1704
    1705          a = Element('a')
    1706          a.text = 'foo'
    1707          a.tail = 'bar'
    1708          a.set('hoi', 'dag')
    1709          a.clear()
    1710          self.assertEqual(None, a.text)
    1711          self.assertEqual(None, a.tail)
    1712          self.assertEqual(None, a.get('hoi'))
    1713          self.assertEqual('a', a.tag)
    1714
    1715 -    def test_clear_sub(self):
    1716          Element = self.etree.Element
    1717          SubElement = self.etree.SubElement
    1718
    1719          a = Element('a')
    1720          a.text = 'foo'
    1721          a.tail = 'bar'
    1722          a.set('hoi', 'dag')
    1723          b = SubElement(a, 'b')
    1724          c = SubElement(b, 'c')
    1725          a.clear()
    1726          self.assertEqual(None, a.text)
    1727          self.assertEqual(None, a.tail)
    1728          self.assertEqual(None, a.get('hoi'))
    1729          self.assertEqual('a', a.tag)
    1730          self.assertEqual(0, len(a))
    1731          self.assertXML(_bytes('<a></a>'),
    1732                         a)
    1733          self.assertXML(_bytes('<b><c></c></b>'),
    1734                         b)
    1735
    1736 -    def test_clear_tail(self):
    1737          ElementTree = self.etree.ElementTree
    1738          f = BytesIO('<a><b></b>B2<c></c>C2</a>')
    1739          doc = ElementTree(file=f)
    1740          a = doc.getroot()
    1741          a.clear()
    1742          self.assertXML(
    1743              _bytes('<a></a>'),
    1744              a)
    1745
    1746 -    def test_insert(self):
    1747          Element = self.etree.Element
    1748          SubElement = self.etree.SubElement
    1749
    1750          a = Element('a')
    1751          b = SubElement(a, 'b')
    1752          c = SubElement(a, 'c')
    1753          d = Element('d')
    1754          a.insert(0, d)
    1755
    1756          self.assertEqual(
    1757              d,
    1758              a[0])
    1759
    1760          self.assertXML(
    1761              _bytes('<a><d></d><b></b><c></c></a>'),
    1762              a)
    1763
    1764          e = Element('e')
    1765          a.insert(2, e)
    1766          self.assertEqual(
    1767              e,
    1768              a[2])
    1769          self.assertXML(
    1770              _bytes('<a><d></d><b></b><e></e><c></c></a>'),
    1771              a)
    1772
    1773 -    def test_insert_name_interning(self):
    1774          # See GH#268 / LP#1773749.
    1775          Element = self.etree.Element
    1776          SubElement = self.etree.SubElement
    1777
    1778          # Use unique names to make sure they are new in the tag name dict.
    1779          import uuid
    1780          names = dict((k, 'tag-' + str(uuid.uuid4())) for k in 'abcde')
    1781
    1782          a = Element(names['a'])
    1783          b = SubElement(a, names['b'])
    1784          c = SubElement(a, names['c'])
    1785          d = Element(names['d'])
    1786          a.insert(0, d)
    1787
    1788          self.assertEqual(
    1789              d,
    1790              a[0])
    1791
    1792          self.assertXML(
    1793              _bytes('<%(a)s><%(d)s></%(d)s><%(b)s></%(b)s><%(c)s></%(c)s></%(a)s>' % names),
    1794              a)
    1795
    1796          e = Element(names['e'])
    1797          a.insert(2, e)
    1798          self.assertEqual(
    1799              e,
    1800              a[2])
    1801          self.assertXML(
    1802              _bytes('<%(a)s><%(d)s></%(d)s><%(b)s></%(b)s><%(e)s></%(e)s><%(c)s></%(c)s></%(a)s>' % names),
    1803              a)
    1804
    1805 -    def test_insert_beyond_index(self):
    1806          Element = self.etree.Element
    1807          SubElement = self.etree.SubElement
    1808
    1809          a = Element('a')
    1810          b = SubElement(a, 'b')
    1811          c = Element('c')
    1812
    1813          a.insert(2, c)
    1814          self.assertEqual(
    1815              c,
    1816              a[1])
    1817          self.assertXML(
    1818              _bytes('<a><b></b><c></c></a>'),
    1819              a)
    1820
    1821 -    def test_insert_negative(self):
    1822          Element = self.etree.Element
    1823          SubElement = self.etree.SubElement
    1824
    1825          a = Element('a')
    1826          b = SubElement(a, 'b')
    1827          c = SubElement(a, 'c')
    1828
    1829          d = Element('d')
    1830          a.insert(-1, d)
    1831          self.assertEqual(
    1832              d,
    1833              a[-2])
    1834          self.assertXML(
    1835              _bytes('<a><b></b><d></d><c></c></a>'),
    1836              a)
    1837
    1838 -    def test_insert_tail(self):
    1839          Element = self.etree.Element
    1840          SubElement = self.etree.SubElement
    1841
    1842          a = Element('a')
    1843          b = SubElement(a, 'b')
    1844
    1845          c = Element('c')
    1846          c.tail = 'C2'
    1847
    1848          a.insert(0, c)
    1849          self.assertXML(
    1850              _bytes('<a><c></c>C2<b></b></a>'),
    1851              a)
    1852
    1853 -    def test_remove(self):
    1854          Element = self.etree.Element
    1855          SubElement = self.etree.SubElement
    1856
    1857          a = Element('a')
    1858          b = SubElement(a, 'b')
    1859          c = SubElement(a, 'c')
    1860
    1861          a.remove(b)
    1862          self.assertEqual(
    1863              c,
    1864              a[0])
    1865          self.assertXML(
    1866              _bytes('<a><c></c></a>'),
    1867              a)
    1868
    1869 -    def test_remove_ns(self):
    1870          Element = self.etree.Element
    1871          SubElement = self.etree.SubElement
    1872
    1873          a = Element('{http://test}a')
    1874          b = SubElement(a, '{http://test}b')
    1875          c = SubElement(a, '{http://test}c')
    1876
    1877          a.remove(b)
    1878          self.assertXML(
    1879              _bytes('<ns0:a xmlns:ns0="http://test"><ns0:c></ns0:c></ns0:a>'),
    1880              a)
    1881          self.assertXML(
    1882              _bytes('<ns0:b xmlns:ns0="http://test"></ns0:b>'),
    1883              b)
    1884
    1885 -    def test_remove_nonexisting(self):
    1886          Element = self.etree.Element
    1887          SubElement = self.etree.SubElement
    1888
    1889          a = Element('a')
    1890          b = SubElement(a, 'b')
    1891          c = SubElement(a, 'c')
    1892          d = Element('d')
    1893          self.assertRaises(
    1894              ValueError, a.remove, d)
    1895
    1896 -    def test_remove_tail(self):
    1897          Element = self.etree.Element
    1898          SubElement = self.etree.SubElement
    1899
    1900          a = Element('a')
    1901          b = SubElement(a, 'b')
    1902          b.tail = 'b2'
    1903          a.remove(b)
    1904          self.assertXML(
    1905              _bytes('<a></a>'),
    1906              a)
    1907          self.assertEqual('b2', b.tail)
    1908
    1909 -    def test_remove_while_iterating(self):
    1910          # There is no guarantee that this "works", but it should
    1911          # remove at least one child and not crash.
    1912          Element = self.etree.Element
    1913          SubElement = self.etree.SubElement
    1914
    1915          a = Element('a')
    1916          SubElement(a, 'b')
    1917          SubElement(a, 'c')
    1918          SubElement(a, 'd')
    1919          for el in a:
    1920              a.remove(el)
    1921          self.assertLess(len(a), 3)
    1922
    1923 -    def test_getchildren(self):
    1924          Element = self.etree.Element
    1925          SubElement = self.etree.SubElement
    1926
    1927          a = Element('a')
    1928          b = SubElement(a, 'b')
    1929          c = SubElement(a, 'c')
    1930          d = SubElement(b, 'd')
    1931          e = SubElement(c, 'e')
    1932          self.assertXML(
    1933              _bytes('<a><b><d></d></b><c><e></e></c></a>'),
    1934              a)
    1935          self.assertEqual(
    1936              [b, c],
    1937              a.getchildren())
    1938          self.assertEqual(
    1939              [d],
    1940              b.getchildren())
    1941          self.assertEqual(
    1942              [],
    1943              d.getchildren())
    1944
    1945 -    def test_makeelement(self):
    1946          Element = self.etree.Element
    1947
    1948          a = Element('a')
    1949          b = a.makeelement('c', {'hoi':'dag'})
    1950          self.assertXML(
    1951              _bytes('<c hoi="dag"></c>'),
    1952              b)
    1953
    1954      required_versions_ET['test_iter'] = (1,3)
    1955 -    def test_iter(self):
    1956          Element = self.etree.Element
    1957          SubElement = self.etree.SubElement
    1958
    1959          a = Element('a')
    1960          b = SubElement(a, 'b')
    1961          c = SubElement(a, 'c')
    1962          d = SubElement(b, 'd')
    1963          e = SubElement(c, 'e')
    1964
    1965          self.assertEqual(
    1966              [a, b, d, c, e],
    1967              list(a.iter()))
    1968          self.assertEqual(
    1969              [d],
    1970              list(d.iter()))
    1971
    1972 -    def test_iter_remove_tail(self):
    1973          Element = self.etree.Element
    1974          SubElement = self.etree.SubElement
    1975
    1976          a = Element('a')
    1977          a.text = 'a'
    1978          a.tail = 'a1' * 100
    1979          b = SubElement(a, 'b')
    1980          b.text = 'b'
    1981          b.tail = 'b1' * 100
    1982          c = SubElement(a, 'c')
    1983          c.text = 'c'
    1984          c.tail = 'c1' * 100
    1985          d = SubElement(b, 'd')
    1986          d.text = 'd'
    1987          d.tail = 'd1' * 100
    1988          e = SubElement(c, 'e')
    1989          e.text = 'e'
    1990          e.tail = 'e1' * 100
    1991
    1992          for el in a.iter():
    1993              el.tail = None
    1994          el = None
    1995
    1996          self.assertEqual(
    1997              [None] * 5,
    1998              [el.tail for el in a.iter()])
    1999
    2000 -    def test_getiterator(self):
    2001          Element = self.etree.Element
    2002          SubElement = self.etree.SubElement
    2003
    2004          a = Element('a')
    2005          b = SubElement(a, 'b')
    2006          c = SubElement(a, 'c')
    2007          d = SubElement(b, 'd')
    2008          e = SubElement(c, 'e')
    2009
    2010          self.assertEqual(
    2011              [a, b, d, c, e],
    2012              list(a.getiterator()))
    2013          self.assertEqual(
    2014              [d],
    2015              list(d.getiterator()))
    2016
    2017 -    def test_getiterator_empty(self):
    2018          Element = self.etree.Element
    2019          SubElement = self.etree.SubElement
    2020
    2021          a = Element('a')
    2022          b = SubElement(a, 'b')
    2023          c = SubElement(a, 'c')
    2024          d = SubElement(b, 'd')
    2025          e = SubElement(c, 'e')
    2026
    2027          self.assertEqual(
    2028              [],
    2029              list(a.getiterator('none')))
    2030          self.assertEqual(
    2031              [],
    2032              list(e.getiterator('none')))
    2033          self.assertEqual(
    2034              [e],
    2035              list(e.getiterator()))
    2036
    2037 -    def test_getiterator_filter(self):
    2038          Element = self.etree.Element
    2039          SubElement = self.etree.SubElement
    2040
    2041          a = Element('a')
    2042          b = SubElement(a, 'b')
    2043          c = SubElement(a, 'c')
    2044          d = SubElement(b, 'd')
    2045          e = SubElement(c, 'e')
    2046
    2047          self.assertEqual(
    2048              [a],
    2049              list(a.getiterator('a')))
    2050          a2 = SubElement(e, 'a')
    2051          self.assertEqual(
    2052              [a, a2],
    2053              list(a.getiterator('a')))
    2054          self.assertEqual(
    2055              [a2],
    2056              list(c.getiterator('a')))
    2057
    2058 -    def test_getiterator_filter_all(self):
    2059          Element = self.etree.Element
    2060          SubElement = self.etree.SubElement
    2061
    2062          a = Element('a')
    2063          b = SubElement(a, 'b')
    2064          c = SubElement(a, 'c')
    2065          d = SubElement(b, 'd')
    2066          e = SubElement(c, 'e')
    2067
    2068          self.assertEqual(
    2069              [a, b, d, c, e],
    2070              list(a.getiterator('*')))
    2071
    2072 -    def test_getiterator_filter_comment(self):
    2073          Element = self.etree.Element
    2074          Comment = self.etree.Comment
    2075          SubElement = self.etree.SubElement
    2076
    2077          a = Element('a')
    2078          b = SubElement(a, 'b')
    2079          comment_b = Comment("TEST-b")
    2080          b.append(comment_b)
    2081
    2082          self.assertEqual(
    2083              [comment_b],
    2084              list(a.getiterator(Comment)))
    2085
    2086          comment_a = Comment("TEST-a")
    2087          a.append(comment_a)
    2088
    2089          self.assertEqual(
    2090              [comment_b, comment_a],
    2091              list(a.getiterator(Comment)))
    2092
    2093          self.assertEqual(
    2094              [comment_b],
    2095              list(b.getiterator(Comment)))
    2096
    2097 -    def test_getiterator_filter_pi(self):
    2098          Element = self.etree.Element
    2099          PI = self.etree.ProcessingInstruction
    2100          SubElement = self.etree.SubElement
    2101
    2102          a = Element('a')
    2103          b = SubElement(a, 'b')
    2104          pi_b = PI("TEST-b")
    2105          b.append(pi_b)
    2106
    2107          self.assertEqual(
    2108              [pi_b],
    2109              list(a.getiterator(PI)))
    2110
    2111          pi_a = PI("TEST-a")
    2112          a.append(pi_a)
    2113
    2114          self.assertEqual(
    2115              [pi_b, pi_a],
    2116              list(a.getiterator(PI)))
    2117
    2118          self.assertEqual(
    2119              [pi_b],
    2120              list(b.getiterator(PI)))
    2121
    2122 -    def test_getiterator_with_text(self):
    2123          Element = self.etree.Element
    2124          SubElement = self.etree.SubElement
    2125
    2126          a = Element('a')
    2127          a.text = 'a'
    2128          b = SubElement(a, 'b')
    2129          b.text = 'b'
    2130          b.tail = 'b1'
    2131          c = SubElement(a, 'c')
    2132          c.text = 'c'
    2133          c.tail = 'c1'
    2134          d = SubElement(b, 'd')
    2135          d.text = 'd'
    2136          d.tail = 'd1'
    2137          e = SubElement(c, 'e')
    2138          e.text = 'e'
    2139          e.tail = 'e1'
    2140
    2141          self.assertEqual(
    2142              [a, b, d, c, e],
    2143              list(a.getiterator()))
    2144          #self.assertEqual(
    2145          #    [d],
    2146          #    list(d.getiterator()))
    2147
    2148 -    def test_getiterator_filter_with_text(self):
    2149          Element = self.etree.Element
    2150          SubElement = self.etree.SubElement
    2151
    2152          a = Element('a')
    2153          a.text = 'a'
    2154          b = SubElement(a, 'b')
    2155          b.text = 'b'
    2156          b.tail = 'b1'
    2157          c = SubElement(a, 'c')
    2158          c.text = 'c'
    2159          c.tail = 'c1'
    2160          d = SubElement(b, 'd')
    2161          d.text = 'd'
    2162          d.tail = 'd1'
    2163          e = SubElement(c, 'e')
    2164          e.text = 'e'
    2165          e.tail = 'e1'
    2166
    2167          self.assertEqual(
    2168              [a],
    2169              list(a.getiterator('a')))
    2170          a2 = SubElement(e, 'a')
    2171          self.assertEqual(
    2172              [a, a2],
    2173              list(a.getiterator('a')))
    2174          self.assertEqual(
    2175              [a2],
    2176              list(e.getiterator('a')))
    2177
    2178 -    def test_getslice(self):
    2179          Element = self.etree.Element
    2180          SubElement = self.etree.SubElement
    2181
    2182          a = Element('a')
    2183          b = SubElement(a, 'b')
    2184          c = SubElement(a, 'c')
    2185          d = SubElement(a, 'd')
    2186
    2187          self.assertEqual(
    2188              [b, c],
    2189              a[0:2])
    2190          self.assertEqual(
    2191              [b, c, d],
    2192              a[:])
    2193          self.assertEqual(
    2194              [b, c, d],
    2195              a[:10])
    2196          self.assertEqual(
    2197              [b],
    2198              a[0:1])
    2199          self.assertEqual(
    2200              [],
    2201              a[10:12])
    2202
    2203 -    def test_getslice_negative(self):
    2204          Element = self.etree.Element
    2205          SubElement = self.etree.SubElement
    2206
    2207          a = Element('a')
    2208          b = SubElement(a, 'b')
    2209          c = SubElement(a, 'c')
    2210          d = SubElement(a, 'd')
    2211
    2212          self.assertEqual(
    2213              [d],
    2214              a[-1:])
    2215          self.assertEqual(
    2216              [c, d],
    2217              a[-2:])
    2218          self.assertEqual(
    2219              [c],
    2220              a[-2:-1])
    2221          self.assertEqual(
    2222              [b, c],
    2223              a[-3:-1])
    2224          self.assertEqual(
    2225              [b, c],
    2226              a[-3:2])
    2227
    2228 -    def test_getslice_step(self):
    2229          Element = self.etree.Element
    2230          SubElement = self.etree.SubElement
    2231
    2232          a = Element('a')
    2233          b = SubElement(a, 'b')
    2234          c = SubElement(a, 'c')
    2235          d = SubElement(a, 'd')
    2236          e = SubElement(a, 'e')
    2237
    2238          self.assertEqual(
    2239              [e,d,c,b],
    2240              a[::-1])
    2241          self.assertEqual(
    2242              [b,d],
    2243              a[::2])
    2244          self.assertEqual(
    2245              [e,c],
    2246              a[::-2])
    2247          self.assertEqual(
    2248              [d,c],
    2249              a[-2:0:-1])
    2250          self.assertEqual(
    2251              [e],
    2252              a[:1:-2])
    2253
    2254 -    def test_getslice_text(self):
    2255          ElementTree = self.etree.ElementTree
    2256
    2257          f = BytesIO('<a><b>B</b>B1<c>C</c>C1</a>')
    2258          doc = ElementTree(file=f)
    2259          a = doc.getroot()
    2260          b = a[0]
    2261          c = a[1]
    2262          self.assertEqual(
    2263              [b, c],
    2264              a[:])
    2265          self.assertEqual(
    2266              [b],
    2267              a[0:1])
    2268          self.assertEqual(
    2269              [c],
    2270              a[1:])
    2271
    2272 -    def test_comment_getitem_getslice(self):
    2273          Element = self.etree.Element
    2274          Comment = self.etree.Comment
    2275          SubElement = self.etree.SubElement
    2276
    2277          a = Element('a')
    2278          b = SubElement(a, 'b')
    2279          foo = Comment('foo')
    2280          a.append(foo)
    2281          c = SubElement(a, 'c')
    2282          self.assertEqual(
    2283              [b, foo, c],
    2284              a[:])
    2285          self.assertEqual(
    2286              foo,
    2287              a[1])
    2288          a[1] = new = Element('new')
    2289          self.assertEqual(
    2290              new,
    2291              a[1])
    2292          self.assertXML(
    2293              _bytes('<a><b></b><new></new><c></c></a>'),
    2294              a)
    2295
    2296 -    def test_delslice(self):
    2297          Element = self.etree.Element
    2298          SubElement = self.etree.SubElement
    2299
    2300          a = Element('a')
    2301          b = SubElement(a, 'b')
    2302          c = SubElement(a, 'c')
    2303          d = SubElement(a, 'd')
    2304          e = SubElement(a, 'e')
    2305
    2306          del a[1:3]
    2307          self.assertEqual(
    2308              [b, e],
    2309              list(a))
    2310
    2311 -    def test_delslice_negative1(self):
    2312          Element = self.etree.Element
    2313          SubElement = self.etree.SubElement
    2314
    2315          a = Element('a')
    2316          b = SubElement(a, 'b')
    2317          c = SubElement(a, 'c')
    2318          d = SubElement(a, 'd')
    2319          e = SubElement(a, 'e')
    2320
    2321          del a[1:-1]
    2322          self.assertEqual(
    2323              [b, e],
    2324              list(a))
    2325
    2326 -    def test_delslice_negative2(self):
    2327          Element = self.etree.Element
    2328          SubElement = self.etree.SubElement
    2329
    2330          a = Element('a')
    2331          b = SubElement(a, 'b')
    2332          c = SubElement(a, 'c')
    2333          d = SubElement(a, 'd')
    2334          e = SubElement(a, 'e')
    2335
    2336          del a[-3:-1]
    2337          self.assertEqual(
    2338              [b, e],
    2339              list(a))
    2340
    2341 -    def test_delslice_step(self):
    2342          Element = self.etree.Element
    2343          SubElement = self.etree.SubElement
    2344
    2345          a = Element('a')
    2346          b = SubElement(a, 'b')
    2347          c = SubElement(a, 'c')
    2348          d = SubElement(a, 'd')
    2349          e = SubElement(a, 'e')
    2350
    2351          del a[1::2]
    2352          self.assertEqual(
    2353              [b, d],
    2354              list(a))
    2355
    2356 -    def test_delslice_step_negative(self):
    2357          Element = self.etree.Element
    2358          SubElement = self.etree.SubElement
    2359
    2360          a = Element('a')
    2361          b = SubElement(a, 'b')
    2362          c = SubElement(a, 'c')
    2363          d = SubElement(a, 'd')
    2364          e = SubElement(a, 'e')
    2365
    2366          del a[::-1]
    2367          self.assertEqual(
    2368              [],
    2369              list(a))
    2370
    2371 -    def test_delslice_step_negative2(self):
    2372          Element = self.etree.Element
    2373          SubElement = self.etree.SubElement
    2374
    2375          a = Element('a')
    2376          b = SubElement(a, 'b')
    2377          c = SubElement(a, 'c')
    2378          d = SubElement(a, 'd')
    2379          e = SubElement(a, 'e')
    2380
    2381          del a[::-2]
    2382          self.assertEqual(
    2383              [b, d],
    2384              list(a))
    2385
    2386 -    def test_delslice_child_tail(self):
    2387          ElementTree = self.etree.ElementTree
    2388          f = BytesIO('<a><b></b>B2<c></c>C2<d></d>D2<e></e>E2</a>')
    2389          doc = ElementTree(file=f)
    2390          a = doc.getroot()
    2391          del a[1:3]
    2392          self.assertXML(
    2393              _bytes('<a><b></b>B2<e></e>E2</a>'),
    2394              a)
    2395
    2396 -    def test_delslice_tail(self):
    2397          XML = self.etree.XML
    2398          a = XML(_bytes('<a><b></b>B2<c></c>C2</a>'))
    2399          b, c = a
    2400
    2401          del a[:]
    2402
    2403          self.assertEqual("B2", b.tail)
    2404          self.assertEqual("C2", c.tail)
    2405
    2406 -    def test_delslice_memory(self):
    2407          # this could trigger a crash
    2408          Element = self.etree.Element
    2409          SubElement = self.etree.SubElement
    2410          a = Element('a')
    2411          b = SubElement(a, 'b')
    2412          c = SubElement(b, 'c')
    2413          del b # no more reference to b
    2414          del a[:]
    2415          self.assertEqual('c', c.tag)
    2416
    2417 -    def test_setslice(self):
    2418          Element = self.etree.Element
    2419          SubElement = self.etree.SubElement
    2420
    2421          a = Element('a')
    2422          b = SubElement(a, 'b')
    2423          c = SubElement(a, 'c')
    2424          d = SubElement(a, 'd')
    2425
    2426          e = Element('e')
    2427          f = Element('f')
    2428          g = Element('g')
    2429
    2430          s = [e, f, g]
    2431          a[1:2] = s
    2432          self.assertEqual(
    2433              [b, e, f, g, d],
    2434              list(a))
    2435
    2436 -    def test_setslice_all(self):
    2437          Element = self.etree.Element
    2438          SubElement = self.etree.SubElement
    2439
    2440          a = Element('a')
    2441          b = SubElement(a, 'b')
    2442          c = SubElement(a, 'c')
    2443
    2444          e = Element('e')
    2445          f = Element('f')
    2446          g = Element('g')
    2447
    2448          s = [e, f, g]
    2449          a[:] = s
    2450          self.assertEqual(
    2451              [e, f, g],
    2452              list(a))
    2453
    2454 -    def test_setslice_all_empty(self):
    2455          Element = self.etree.Element
    2456          SubElement = self.etree.SubElement
    2457
    2458          a = Element('a')
    2459
    2460          e = Element('e')
    2461          f = Element('f')
    2462          g = Element('g')
    2463
    2464          s = [e, f, g]
    2465          a[:] = s
    2466          self.assertEqual(
    2467              [e, f, g],
    2468              list(a))
    2469
    2470 -    def test_setslice_all_replace(self):
    2471          Element = self.etree.Element
    2472          SubElement = self.etree.SubElement
    2473
    2474          a = Element('a')
    2475          b = SubElement(a, 'b')
    2476          c = SubElement(a, 'c')
    2477          d = SubElement(a, 'd')
    2478
    2479          s = [b, c, d]
    2480          a[:] = s
    2481          self.assertEqual(
    2482              [b, c, d],
    2483              list(a))
    2484
    2485 -    def test_setslice_all_replace_reversed(self):
    2486          Element = self.etree.Element
    2487          SubElement = self.etree.SubElement
    2488
    2489          a = Element('a')
    2490          b = SubElement(a, 'b')
    2491          c = SubElement(a, 'c')
    2492          d = SubElement(a, 'd')
    2493
    2494          s = [d, c, b]
    2495          a[:] = s
    2496          self.assertEqual(
    2497              [d, c, b],
    2498              list(a))
    2499
    2500 -    def test_setslice_all_replace_reversed_ns1(self):
    2501          Element = self.etree.Element
    2502          SubElement = self.etree.SubElement
    2503
    2504          a = Element('{ns}a')
    2505          b = SubElement(a, '{ns}b', {'{ns1}a1': 'test'})
    2506          c = SubElement(a, '{ns}c', {'{ns2}a2': 'test'})
    2507          d = SubElement(a, '{ns}d', {'{ns3}a3': 'test'})
    2508
    2509          s = [d, c, b]
    2510          a[:] = s
    2511          self.assertEqual(
    2512              [d, c, b],
    2513              list(a))
    2514          self.assertEqual(
    2515              ['{ns}d', '{ns}c', '{ns}b'],
    2516              [ child.tag for child in a ])
    2517
    2518          self.assertEqual(
    2519              [['{ns3}a3'], ['{ns2}a2'], ['{ns1}a1']],
    2520              [ list(child.attrib.keys()) for child in a ])
    2521
    2522 -    def test_setslice_all_replace_reversed_ns2(self):
    2523          Element = self.etree.Element
    2524          SubElement = self.etree.SubElement
    2525
    2526          a = Element('{ns}a')
    2527          b = SubElement(a, '{ns1}b', {'{ns}a1': 'test'})
    2528          c = SubElement(a, '{ns2}c', {'{ns}a2': 'test'})
    2529          d = SubElement(a, '{ns3}d', {'{ns}a3': 'test'})
    2530
    2531          s = [d, c, b]
    2532          a[:] = s
    2533          self.assertEqual(
    2534              [d, c, b],
    2535              list(a))
    2536          self.assertEqual(
    2537              ['{ns3}d', '{ns2}c', '{ns1}b'],
    2538              [ child.tag for child in a ])
    2539
    2540          self.assertEqual(
    2541              [['{ns}a3'], ['{ns}a2'], ['{ns}a1']],
    2542              [ list(child.attrib.keys()) for child in a ])
    2543
    2544 -    def test_setslice_end(self):
    2545          Element = self.etree.Element
    2546          SubElement = self.etree.SubElement
    2547
    2548          a = Element('a')
    2549          b = SubElement(a, 'b')
    2550          c = SubElement(a, 'c')
    2551
    2552          e = Element('e')
    2553          f = Element('f')
    2554          g = Element('g')
    2555          h = Element('h')
    2556
    2557          s = [e, f]
    2558          a[99:] = s
    2559          self.assertEqual(
    2560              [b, c, e, f],
    2561              list(a))
    2562
    2563          s = [g, h]
    2564          a[:0] = s
    2565          self.assertEqual(
    2566              [g, h, b, c, e, f],
    2567              list(a))
    2568
    2569 -    def test_setslice_end_exact(self):
    2570          Element = self.etree.Element
    2571          SubElement = self.etree.SubElement
    2572
    2573          a = Element('a')
    2574          b = SubElement(a, 'b')
    2575          c = SubElement(a, 'c')
    2576          d = SubElement(a, 'd')
    2577
    2578          e = Element('e')
    2579          f = Element('f')
    2580          g = Element('g')
    2581
    2582          s = [e, f, g]
    2583          a[3:] = s
    2584          self.assertEqual(
    2585              [b, c, d, e, f, g],
    2586              list(a))
    2587
    2588 -    def test_setslice_single(self):
    2589          Element = self.etree.Element
    2590          SubElement = self.etree.SubElement
    2591
    2592          a = Element('a')
    2593          b = SubElement(a, 'b')
    2594          c = SubElement(a, 'c')
    2595
    2596          e = Element('e')
    2597          f = Element('f')
    2598
    2599          s = [e]
    2600          a[0:1] = s
    2601          self.assertEqual(
    2602              [e, c],
    2603              list(a))
    2604
    2605          s = [f]
    2606          a[1:2] = s
    2607          self.assertEqual(
    2608              [e, f],
    2609              list(a))
    2610
    2611 -    def test_setslice_tail(self):
    2612          ElementTree = self.etree.ElementTree
    2613          Element = self.etree.Element
    2614          f = BytesIO('<a><b></b>B2<c></c>C2<d></d>D2<e></e>E2</a>')
    2615          doc = ElementTree(file=f)
    2616          a = doc.getroot()
    2617          x = Element('x')
    2618          y = Element('y')
    2619          z = Element('z')
    2620          x.tail = 'X2'
    2621          y.tail = 'Y2'
    2622          z.tail = 'Z2'
    2623          a[1:3] = [x, y, z]
    2624          self.assertXML(
    2625              _bytes('<a><b></b>B2<x></x>X2<y></y>Y2<z></z>Z2<e></e>E2</a>'),
    2626              a)
    2627
    2628 -    def test_setslice_negative(self):
    2629          Element = self.etree.Element
    2630          SubElement = self.etree.SubElement
    2631
    2632          a = Element('a')
    2633          b = SubElement(a, 'b')
    2634          c = SubElement(a, 'c')
    2635          d = SubElement(a, 'd')
    2636
    2637          x = Element('x')
    2638          y = Element('y')
    2639
    2640          a[1:-1] = [x, y]
    2641          self.assertEqual(
    2642              [b, x, y, d],
    2643              list(a))
    2644
    2645 -    def test_setslice_negative2(self):
    2646          Element = self.etree.Element
    2647          SubElement = self.etree.SubElement
    2648
    2649          a = Element('a')
    2650          b = SubElement(a, 'b')
    2651          c = SubElement(a, 'c')
    2652          d = SubElement(a, 'd')
    2653
    2654          x = Element('x')
    2655          y = Element('y')
    2656
    2657          a[1:-2] = [x, y]
    2658          self.assertEqual(
    2659              [b, x, y, c, d],
    2660              list(a))
    2661
    2662 -    def test_setslice_empty(self):
    2663          Element = self.etree.Element
    2664
    2665          a = Element('a')
    2666
    2667          b = Element('b')
    2668          c = Element('c')
    2669
    2670          a[:] = [b, c]
    2671          self.assertEqual(
    2672              [b, c],
    2673              list(a))
    2674
    2675 -    def test_tail_elementtree_root(self):
    2676          Element = self.etree.Element
    2677          ElementTree = self.etree.ElementTree
    2678
    2679          a = Element('a')
    2680          a.tail = 'A2'
    2681          t = ElementTree(element=a)
    2682          self.assertEqual('A2',
    2683                            a.tail)
    2684
    2685 -    def test_elementtree_getiterator(self):
    2686          Element = self.etree.Element
    2687          SubElement = self.etree.SubElement
    2688          ElementTree = self.etree.ElementTree
    2689
    2690          a = Element('a')
    2691          b = SubElement(a, 'b')
    2692          c = SubElement(a, 'c')
    2693          d = SubElement(b, 'd')
    2694          e = SubElement(c, 'e')
    2695          t = ElementTree(element=a)
    2696
    2697          self.assertEqual(
    2698              [a, b, d, c, e],
    2699              list(t.getiterator()))
    2700
    2701 -    def test_elementtree_getiterator_filter(self):
    2702          Element = self.etree.Element
    2703          SubElement = self.etree.SubElement
    2704          ElementTree = self.etree.ElementTree
    2705          a = Element('a')
    2706          b = SubElement(a, 'b')
    2707          c = SubElement(a, 'c')
    2708          d = SubElement(b, 'd')
    2709          e = SubElement(c, 'e')
    2710          t = ElementTree(element=a)
    2711
    2712          self.assertEqual(
    2713              [a],
    2714              list(t.getiterator('a')))
    2715          a2 = SubElement(e, 'a')
    2716          self.assertEqual(
    2717              [a, a2],
    2718              list(t.getiterator('a')))
    2719
    2720 -    def test_ns_access(self):
    2721          ElementTree = self.etree.ElementTree
    2722          ns = 'http://xml.infrae.com/1'
    2723          f = BytesIO('<x:a xmlns:x="%s"><x:b></x:b></x:a>' % ns)
    2724          t = ElementTree(file=f)
    2725          a = t.getroot()
    2726          self.assertEqual('{%s}a' % ns,
    2727                            a.tag)
    2728          self.assertEqual('{%s}b' % ns,
    2729                            a[0].tag)
    2730
    2731 -    def test_ns_access2(self):
    2732          ElementTree = self.etree.ElementTree
    2733          ns = 'http://xml.infrae.com/1'
    2734          ns2 = 'http://xml.infrae.com/2'
    2735          f = BytesIO('<x:a xmlns:x="%s" xmlns:y="%s"><x:b></x:b><y:b></y:b></x:a>' % (ns, ns2))
    2736          t = ElementTree(file=f)
    2737          a = t.getroot()
    2738          self.assertEqual('{%s}a' % ns,
    2739                            a.tag)
    2740          self.assertEqual('{%s}b' % ns,
    2741                            a[0].tag)
    2742          self.assertEqual('{%s}b' % ns2,
    2743                            a[1].tag)
    2744
    2745 -    def test_ns_setting(self):
    2746          Element = self.etree.Element
    2747          SubElement = self.etree.SubElement
    2748          ns = 'http://xml.infrae.com/1'
    2749          ns2 = 'http://xml.infrae.com/2'
    2750          a = Element('{%s}a' % ns)
    2751          b = SubElement(a, '{%s}b' % ns2)
    2752          c = SubElement(a, '{%s}c' % ns)
    2753          self.assertEqual('{%s}a' % ns,
    2754                            a.tag)
    2755          self.assertEqual('{%s}b' % ns2,
    2756                            b.tag)
    2757          self.assertEqual('{%s}c' % ns,
    2758                            c.tag)
    2759          self.assertEqual('{%s}a' % ns,
    2760                            a.tag)
    2761          self.assertEqual('{%s}b' % ns2,
    2762                            b.tag)
    2763          self.assertEqual('{%s}c' % ns,
    2764                            c.tag)
    2765
    2766 -    def test_ns_tag_parse(self):
    2767          Element = self.etree.Element
    2768          SubElement = self.etree.SubElement
    2769          ElementTree = self.etree.ElementTree
    2770
    2771          ns = 'http://xml.infrae.com/1'
    2772          ns2 = 'http://xml.infrae.com/2'
    2773          f = BytesIO('<a xmlns="%s" xmlns:x="%s"><x:b></x:b><b></b></a>' % (ns, ns2))
    2774          t = ElementTree(file=f)
    2775
    2776          a = t.getroot()
    2777          self.assertEqual('{%s}a' % ns,
    2778                            a.tag)
    2779          self.assertEqual('{%s}b' % ns2,
    2780                            a[0].tag)
    2781          self.assertEqual('{%s}b' % ns,
    2782                            a[1].tag)
    2783
    2784 -    def test_ns_attr(self):
    2785          Element = self.etree.Element
    2786          ns = 'http://xml.infrae.com/1'
    2787          ns2 = 'http://xml.infrae.com/2'
    2788          a = Element('a')
    2789          a.set('{%s}foo' % ns, 'Foo')
    2790          a.set('{%s}bar' % ns2, 'Bar')
    2791          self.assertEqual(
    2792              'Foo',
    2793              a.get('{%s}foo' % ns))
    2794          self.assertEqual(
    2795              'Bar',
    2796              a.get('{%s}bar' % ns2))
    2797          try:
    2798              self.assertXML(
    2799                  _bytes('<a xmlns:ns0="%s" xmlns:ns1="%s" ns0:foo="Foo" ns1:bar="Bar"></a>' % (ns, ns2)),
    2800                  a)
    2801          except AssertionError:
    2802              self.assertXML(
    2803                  _bytes('<a xmlns:ns0="%s" xmlns:ns1="%s" ns1:foo="Foo" ns0:bar="Bar"></a>' % (ns2, ns)),
    2804                  a)
    2805
    2806 -    def test_ns_move(self):
    2807          Element = self.etree.Element
    2808          one = self.etree.fromstring(
    2809              _bytes('<foo><bar xmlns:ns="http://a.b.c"><ns:baz/></bar></foo>'))
    2810          baz = one[0][0]
    2811
    2812          two = Element('root')
    2813          two.append(baz)
    2814          # removing the originating document could cause a crash/error before
    2815          # as namespace is not moved along with it
    2816          del one, baz
    2817          self.assertEqual('{http://a.b.c}baz', two[0].tag)
    2818
    2819 -    def test_ns_decl_tostring(self):
    2820          tostring = self.etree.tostring
    2821          root = self.etree.XML(
    2822              _bytes('<foo><bar xmlns:ns="http://a.b.c"><ns:baz/></bar></foo>'))
    2823          baz = root[0][0]
    2824
    2825          nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"),
    2826                              tostring(baz))
    2827          self.assertEqual([_bytes("http://a.b.c")], nsdecl)
    2828
    2829 -    def test_ns_decl_tostring_default(self):
    2830          tostring = self.etree.tostring
    2831          root = self.etree.XML(
    2832              _bytes('<foo><bar xmlns="http://a.b.c"><baz/></bar></foo>'))
    2833          baz = root[0][0]
    2834
    2835          nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"),
    2836                              tostring(baz))
    2837          self.assertEqual([_bytes("http://a.b.c")], nsdecl)
    2838
    2839 -    def test_ns_decl_tostring_root(self):
    2840          tostring = self.etree.tostring
    2841          root = self.etree.XML(
    2842              _bytes('<foo xmlns:ns="http://a.b.c"><bar><ns:baz/></bar></foo>'))
    2843          baz = root[0][0]
    2844
    2845          nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"),
    2846                              tostring(baz))
    2847
    2848          self.assertEqual([_bytes("http://a.b.c")], nsdecl)
    2849
    2850 -    def test_ns_decl_tostring_element(self):
    2851          Element = self.etree.Element
    2852          SubElement = self.etree.SubElement
    2853
    2854          root = Element("foo")
    2855          bar = SubElement(root, "{http://a.b.c}bar")
    2856          baz = SubElement(bar, "{http://a.b.c}baz")
    2857
    2858          nsdecl = re.findall(_bytes("xmlns(?::[a-z0-9]+)?=[\"']([^\"']+)[\"']"),
    2859                              self.etree.tostring(baz))
    2860
    2861          self.assertEqual([_bytes("http://a.b.c")], nsdecl)
    2862
    2863 -    def test_attribute_xmlns_move(self):
    2864          Element = self.etree.Element
    2865
    2866          root = Element('element')
    2867
    2868          subelement = Element('subelement',
    2869                               {"{http://www.w3.org/XML/1998/namespace}id": "foo"})
    2870          self.assertEqual(1, len(subelement.attrib))
    2871          self.assertEqual(
    2872              "foo",
    2873              subelement.get("{http://www.w3.org/XML/1998/namespace}id"))
    2874
    2875          root.append(subelement)
    2876          self.assertEqual(1, len(subelement.attrib))
    2877          self.assertEqual(
    2878              list({"{http://www.w3.org/XML/1998/namespace}id" : "foo"}.items()),
    2879              list(subelement.attrib.items()))
    2880          self.assertEqual(
    2881              "foo",
    2882              subelement.get("{http://www.w3.org/XML/1998/namespace}id"))
    2883
    2884 -    def test_namespaces_after_serialize(self):
    2885          parse = self.etree.parse
    2886          tostring = self.etree.tostring
    2887
    2888          ns_href = "http://a.b.c"
    2889          one = parse(
    2890              BytesIO('<foo><bar xmlns:ns="%s"><ns:baz/></bar></foo>' % ns_href))
    2891          baz = one.getroot()[0][0]
    2892
    2893          parsed = parse(BytesIO( tostring(baz) )).getroot()
    2894          self.assertEqual('{%s}baz' % ns_href, parsed.tag)
    2895
    2896 -    def test_attribute_namespace_roundtrip(self):
    2897          fromstring = self.etree.fromstring
    2898          tostring = self.etree.tostring
    2899
    2900          ns_href = "http://a.b.c"
    2901          xml = _bytes('<root xmlns="%s" xmlns:x="%s"><el x:a="test" /></root>' % (
    2902                  ns_href,ns_href))
    2903          root = fromstring(xml)
    2904          self.assertEqual('test', root[0].get('{%s}a' % ns_href))
    2905
    2906          xml2 = tostring(root)
    2907          self.assertTrue(_bytes(':a=') in xml2, xml2)
    2908
    2909          root2 = fromstring(xml2)
    2910          self.assertEqual('test', root2[0].get('{%s}a' % ns_href))
    2911
    2912 -    def test_attribute_namespace_roundtrip_replaced(self):
    2913          fromstring = self.etree.fromstring
    2914          tostring = self.etree.tostring
    2915
    2916          ns_href = "http://a.b.c"
    2917          xml = _bytes('<root xmlns="%s" xmlns:x="%s"><el x:a="test" /></root>' % (
    2918                  ns_href,ns_href))
    2919          root = fromstring(xml)
    2920          self.assertEqual('test', root[0].get('{%s}a' % ns_href))
    2921
    2922          root[0].set('{%s}a' % ns_href, 'TEST')
    2923
    2924          xml2 = tostring(root)
    2925          self.assertTrue(_bytes(':a=') in xml2, xml2)
    2926
    2927          root2 = fromstring(xml2)
    2928          self.assertEqual('TEST', root2[0].get('{%s}a' % ns_href))
    2929
    2930      required_versions_ET['test_register_namespace'] = (1,3)
    2931 -    def test_register_namespace(self):
    2932          # ET 1.3+
    2933          Element = self.etree.Element
    2934          prefix = 'TESTPREFIX'
    2935          namespace = 'http://seriously.unknown/namespace/URI'
    2936
    2937          el = Element('{%s}test' % namespace)
    2938          self.assertEqual(_bytes('<ns0:test xmlns:ns0="%s"></ns0:test>' % namespace),
    2939              self._writeElement(el))
    2940
    2941          self.etree.register_namespace(prefix, namespace)
    2942          el = Element('{%s}test' % namespace)
    2943          self.assertEqual(_bytes('<%s:test xmlns:%s="%s"></%s:test>' % (
    2944              prefix, prefix, namespace, prefix)),
    2945              self._writeElement(el))
    2946
    2947          self.assertRaises(ValueError, self.etree.register_namespace, 'ns25', namespace)
    2948
    2949 -    def test_tostring(self):
    2950          tostring = self.etree.tostring
    2951          Element = self.etree.Element
    2952          SubElement = self.etree.SubElement
    2953
    2954          a = Element('a')
    2955          b = SubElement(a, 'b')
    2956          c = SubElement(a, 'c')
    2957
    2958          self.assertEqual(_bytes('<a><b></b><c></c></a>'),
    2959                            canonicalize(tostring(a)))
    2960
    2961 -    def test_tostring_element(self):
    2962          tostring = self.etree.tostring
    2963          Element = self.etree.Element
    2964          SubElement = self.etree.SubElement
    2965
    2966          a = Element('a')
    2967          b = SubElement(a, 'b')
    2968          c = SubElement(a, 'c')
    2969          d = SubElement(c, 'd')
    2970          self.assertEqual(_bytes('<b></b>'),
    2971                            canonicalize(tostring(b)))
    2972          self.assertEqual(_bytes('<c><d></d></c>'),
    2973                            canonicalize(tostring(c)))
    2974
    2975 -    def test_tostring_element_tail(self):
    2976          tostring = self.etree.tostring
    2977          Element = self.etree.Element
    2978          SubElement = self.etree.SubElement
    2979
    2980          a = Element('a')
    2981          b = SubElement(a, 'b')
    2982          c = SubElement(a, 'c')
    2983          d = SubElement(c, 'd')
    2984          b.tail = 'Foo'
    2985
    2986          self.assertTrue(tostring(b) == _bytes('<b/>Foo') or
    2987                       tostring(b) == _bytes('<b />Foo'))
    2988
    2989      required_versions_ET['test_tostring_method_html'] = (1,3)
    2990 -    def test_tostring_method_html(self):
    2991          tostring = self.etree.tostring
    2992          Element = self.etree.Element
    2993          SubElement = self.etree.SubElement
    2994
    2995          html = Element('html')
    2996          body = SubElement(html, 'body')
    2997          p = SubElement(body, 'p')
    2998          p.text = "html"
    2999          SubElement(p, 'br').tail = "test"
    3000
    3001          self.assertEqual(_bytes('<html><body><p>html<br>test</p></body></html>'),
    3002                            tostring(html, method="html"))
    3003
    3004      required_versions_ET['test_tostring_method_text'] = (1,3)
    3005 -    def test_tostring_method_text(self):
    3006          tostring = self.etree.tostring
    3007          Element = self.etree.Element
    3008          SubElement = self.etree.SubElement
    3009
    3010          a = Element('a')
    3011          a.text = "A"
    3012          a.tail = "tail"
    3013          b = SubElement(a, 'b')
    3014          b.text = "B"
    3015          b.tail = "TAIL"
    3016          c = SubElement(a, 'c')
    3017          c.text = "C"
    3018
    3019          self.assertEqual(_bytes('ABTAILCtail'),
    3020                            tostring(a, method="text"))
    3021
    3022 -    def test_iterparse(self):
    3023          iterparse = self.etree.iterparse
    3024          f = BytesIO('<a><b></b><c/></a>')
    3025
    3026          iterator = iterparse(f)
    3027          self.assertEqual(None,
    3028                            iterator.root)
    3029          events = list(iterator)
    3030          root = iterator.root
    3031          self.assertEqual(
    3032              [('end', root[0]), ('end', root[1]), ('end', root)],
    3033              events)
    3034
    3035 -    def test_iterparse_incomplete(self):
    3036          iterparse = self.etree.iterparse
    3037          f = BytesIO('<a><b></b><c/></a>')
    3038
    3039          iterator = iterparse(f)
    3040          self.assertEqual(None,
    3041                            iterator.root)
    3042          event, element = next(iter(iterator))
    3043          self.assertEqual('end', event)
    3044          self.assertEqual('b', element.tag)
    3045
    3046 -    def test_iterparse_file(self):
    3047          iterparse = self.etree.iterparse
    3048          iterator = iterparse(fileInTestDir("test.xml"))
    3049          self.assertEqual(None,
    3050                            iterator.root)
    3051          events = list(iterator)
    3052          root = iterator.root
    3053          self.assertEqual(
    3054              [('end', root[0]), ('end', root)],
    3055              events)
    3056
    3057 -    def test_iterparse_start(self):
    3058          iterparse = self.etree.iterparse
    3059          f = BytesIO('<a><b></b><c/></a>')
    3060
    3061          iterator = iterparse(f, events=('start',))
    3062          events = list(iterator)
    3063          root = iterator.root
    3064          self.assertEqual(
    3065              [('start', root), ('start', root[0]), ('start', root[1])],
    3066              events)
    3067
    3068 -    def test_iterparse_start_end(self):
    3069          iterparse = self.etree.iterparse
    3070          f = BytesIO('<a><b></b><c/></a>')
    3071
    3072          iterator = iterparse(f, events=('start','end'))
    3073          events = list(iterator)
    3074          root = iterator.root
    3075          self.assertEqual(
    3076              [('start', root), ('start', root[0]), ('end', root[0]),
    3077               ('start', root[1]), ('end', root[1]), ('end', root)],
    3078              events)
    3079
    3080 -    def test_iterparse_clear(self):
    3081          iterparse = self.etree.iterparse
    3082          f = BytesIO('<a><b></b><c/></a>')
    3083
    3084          iterator = iterparse(f)
    3085          for event, elem in iterator:
    3086              elem.clear()
    3087
    3088          root = iterator.root
    3089          self.assertEqual(0,
    3090                            len(root))
    3091
    3092 -    def test_iterparse_large(self):
    3093          iterparse = self.etree.iterparse
    3094          CHILD_COUNT = 12345
    3095          f = BytesIO('<a>%s</a>' % ('<b>test</b>'*CHILD_COUNT))
    3096
    3097          i = 0
    3098          for key in iterparse(f):
    3099              event, element = key
    3100              i += 1
    3101          self.assertEqual(i, CHILD_COUNT + 1)
    3102
    3103 -    def test_iterparse_set_ns_attribute(self):
    3104          iterparse = self.etree.iterparse
    3105          f = BytesIO('<a xmlns="http://ns1/"><b><c xmlns="http://ns2/"/></b></a>')
    3106
    3107          attr_name = '{http://testns/}bla'
    3108          events = []
    3109          iterator = iterparse(f, events=('start','end','start-ns','end-ns'))
    3110          for event, elem in iterator:
    3111              events.append(event)
    3112              if event == 'start':
    3113                  if elem.tag != '{http://ns1/}a':
    3114                      elem.set(attr_name, 'value')
    3115
    3116          self.assertEqual(
    3117              ['start-ns', 'start', 'start', 'start-ns', 'start',
    3118               'end', 'end-ns', 'end', 'end', 'end-ns'],
    3119              events)
    3120
    3121          root = iterator.root
    3122          self.assertEqual(
    3123              None,
    3124              root.get(attr_name))
    3125          self.assertEqual(
    3126              'value',
    3127              root[0].get(attr_name))
    3128
    3129 -    def test_iterparse_only_end_ns(self):
    3130          iterparse = self.etree.iterparse
    3131          f = BytesIO('<a xmlns="http://ns1/"><b><c xmlns="http://ns2/"/></b></a>')
    3132
    3133          attr_name = '{http://testns/}bla'
    3134          events = []
    3135          iterator = iterparse(f, events=('start','end','start-ns','end-ns'))
    3136          for event, elem in iterator:
    3137              events.append(event)
    3138              if event == 'start':
    3139                  if elem.tag != '{http://ns1/}a':
    3140                      elem.set(attr_name, 'value')
    3141
    3142          self.assertEqual(
    3143              ['start-ns', 'start', 'start', 'start-ns', 'start',
    3144               'end', 'end-ns', 'end', 'end', 'end-ns'],
    3145              events)
    3146
    3147          root = iterator.root
    3148          self.assertEqual(
    3149              None,
    3150              root.get(attr_name))
    3151          self.assertEqual(
    3152              'value',
    3153              root[0].get(attr_name))
    3154
    3155 -    def test_iterparse_getiterator(self):
    3156          iterparse = self.etree.iterparse
    3157          f = BytesIO('<a><b><d/></b><c/></a>')
    3158
    3159          counts = []
    3160          for event, elem in iterparse(f):
    3161              counts.append(len(list(elem.getiterator())))
    3162          self.assertEqual(
    3163              [1,2,1,4],
    3164              counts)
    3165
    3166 -    def test_iterparse_move_elements(self):
    3167          iterparse = self.etree.iterparse
    3168          f = BytesIO('<a><b><d/></b><c/></a>')
    3169
    3170          for event, node in etree.iterparse(f): pass
    3171
    3172          root = etree.Element('new_root', {})
    3173          root[:] = node[:]
    3174
    3175          self.assertEqual(
    3176              ['b', 'c'],
    3177              [ el.tag for el in root ])
    3178
    3179 -    def test_iterparse_cdata(self):
    3180          tostring = self.etree.tostring
    3181          f = BytesIO('<root><![CDATA[test]]></root>')
    3182          context = self.etree.iterparse(f)
    3183          content = [ el.text for event,el in context ]
    3184
    3185          self.assertEqual(['test'], content)
    3186          self.assertEqual(_bytes('<root>test</root>'),
    3187                            tostring(context.root))
    3188
    3189 -    def test_parse_file(self):
    3190          parse = self.etree.parse
    3191          # from file
    3192          tree = parse(fileInTestDir('test.xml'))
    3193          self.assertXML(
    3194              _bytes('<a><b></b></a>'),
    3195              tree.getroot())
    3196
    3197 -    def test_parse_file_nonexistent(self):
    3198          parse = self.etree.parse
    3199          self.assertRaises(IOError, parse, fileInTestDir('notthere.xml'))
    3200
    3201 -    def test_parse_error_none(self):
    3202          parse = self.etree.parse
    3203          self.assertRaises(TypeError, parse, None)
    3204
    3205      required_versions_ET['test_parse_error'] = (1,3)
    3206 -    def test_parse_error(self):
    3207          # ET < 1.3 raises ExpatError
    3208          parse = self.etree.parse
    3209          f = BytesIO('<a><b></c></b></a>')
    3210          self.assertRaises(SyntaxError, parse, f)
    3211          f.close()
    3212
    3213      required_versions_ET['test_parse_error_from_file'] = (1,3)
    3214 -    def test_parse_error_from_file(self):
    3215          parse = self.etree.parse
    3216          # from file
    3217          f = open(fileInTestDir('test_broken.xml'), 'rb')
    3218          self.assertRaises(SyntaxError, parse, f)
    3219          f.close()
    3220
    3221 -    def test_parse_file_object(self):
    3222          parse = self.etree.parse
    3223          # from file object
    3224          f = open(fileInTestDir('test.xml'), 'rb')
    3225          tree = parse(f)
    3226          f.close()
    3227          self.assertXML(
    3228              _bytes('<a><b></b></a>'),
    3229              tree.getroot())
    3230
    3231 -    def test_parse_stringio(self):
    3232          parse = self.etree.parse
    3233          f = BytesIO('<a><b></b></a>')
    3234          tree = parse(f)
    3235          f.close()
    3236          self.assertXML(
    3237              _bytes('<a><b></b></a>'),
    3238              tree.getroot()
    3239             )
    3240
    3241 -    def test_parse_cdata(self):
    3242          tostring = self.etree.tostring
    3243          root = self.etree.XML(_bytes('<root><![CDATA[test]]></root>'))
    3244
    3245          self.assertEqual('test', root.text)
    3246          self.assertEqual(_bytes('<root>test</root>'),
    3247                            tostring(root))
    3248
    3249 -    def test_parse_with_encoding(self):
    3250          # this can fail in libxml2 <= 2.6.22
    3251          parse = self.etree.parse
    3252          tree = parse(BytesIO('<?xml version="1.0" encoding="ascii"?><html/>'))
    3253          self.assertXML(_bytes('<html></html>'),
    3254                         tree.getroot())
    3255
    3256 -    def test_encoding(self):
    3257          Element = self.etree.Element
    3258
    3259          a = Element('a')
    3260          a.text = _str('Søk på nettet')
    3261          self.assertXML(
    3262              _str('<a>Søk på nettet</a>').encode('UTF-8'),
    3263              a, 'utf-8')
    3264
    3265 -    def test_encoding_exact(self):
    3266          ElementTree = self.etree.ElementTree
    3267          Element = self.etree.Element
    3268
    3269          a = Element('a')
    3270          a.text = _str('Søk på nettet')
    3271
    3272          f = BytesIO()
    3273          tree = ElementTree(element=a)
    3274          tree.write(f, encoding='utf-8')
    3275          self.assertEqual(_str('<a>Søk på nettet</a>').encode('UTF-8'),
    3276                            f.getvalue().replace(_bytes('\n'),_bytes('')))
    3277
    3278 -    def test_parse_file_encoding(self):
    3279          parse = self.etree.parse
    3280          # from file
    3281          tree = parse(fileInTestDir('test-string.xml'))
    3282          self.assertXML(
    3283              _str('<a>Søk på nettet</a>').encode('UTF-8'),
    3284              tree.getroot(), 'UTF-8')
    3285
    3286 -    def test_parse_file_object_encoding(self):
    3287          parse = self.etree.parse
    3288          # from file object
    3289          f = open(fileInTestDir('test-string.xml'), 'rb')
    3290          tree = parse(f)
    3291          f.close()
    3292          self.assertXML(
    3293              _str('<a>Søk på nettet</a>').encode('UTF-8'),
    3294              tree.getroot(), 'UTF-8')
    3295
    3296 -    def test_encoding_8bit_latin1(self):
    3297          ElementTree = self.etree.ElementTree
    3298          Element = self.etree.Element
    3299
    3300          a = Element('a')
    3301          a.text = _str('Søk på nettet')
    3302
    3303          f = BytesIO()
    3304          tree = ElementTree(element=a)
    3305          tree.write(f, encoding='iso-8859-1')
    3306          result = f.getvalue()
    3307          declaration = _bytes("<?xml version=\'1.0\' encoding=\'iso-8859-1\'?>")
    3308          self.assertEncodingDeclaration(result, _bytes('iso-8859-1'))
    3309          result = result.split(_bytes('?>'), 1)[-1].replace(_bytes('\n'),_bytes(''))
    3310          self.assertEqual(_str('<a>Søk på nettet</a>').encode('iso-8859-1'),
    3311                            result)
    3312
    3313      required_versions_ET['test_parse_encoding_8bit_explicit'] = (1,3)
    3314 -    def test_parse_encoding_8bit_explicit(self):
    3315          XMLParser = self.XMLParser
    3316
    3317          text = _str('Søk på nettet')
    3318          xml_latin1 = (_str('<a>%s</a>') % text).encode('iso-8859-1')
    3319
    3320          self.assertRaises(self.etree.ParseError,
    3321                            self.etree.parse,
    3322                            BytesIO(xml_latin1))
    3323
    3324          tree = self.etree.parse(BytesIO(xml_latin1),
    3325                                  XMLParser(encoding="iso-8859-1"))
    3326          a = tree.getroot()
    3327          self.assertEqual(a.text, text)
    3328
    3329      required_versions_ET['test_parse_encoding_8bit_override'] = (1,3)
    3330 -    def test_parse_encoding_8bit_override(self):
    3331          XMLParser = self.XMLParser
    3332
    3333          text = _str('Søk på nettet')
    3334          wrong_declaration = _str("<?xml version='1.0' encoding='UTF-8'?>")
    3335          xml_latin1 = (_str('%s<a>%s</a>') % (wrong_declaration, text)
    3336                        ).encode('iso-8859-1')
    3337
    3338          self.assertRaises(self.etree.ParseError,
    3339                            self.etree.parse,
    3340                            BytesIO(xml_latin1))
    3341
    3342          tree = self.etree.parse(BytesIO(xml_latin1),
    3343                                  XMLParser(encoding="iso-8859-1"))
    3344          a = tree.getroot()
    3345          self.assertEqual(a.text, text)
    3346
    3347 -    def _test_wrong_unicode_encoding(self):
    3348          # raise error on wrong encoding declaration in unicode strings
    3349          XML = self.etree.XML
    3350          test_utf = (_str('<?xml version="1.0" encoding="iso-8859-1"?>') +
    3351                      _str('<a>Søk på nettet</a>'))
    3352          self.assertRaises(SyntaxError, XML, test_utf)
    3353
    3354 -    def test_encoding_write_default_encoding(self):
    3355          ElementTree = self.etree.ElementTree
    3356          Element = self.etree.Element
    3357
    3358          a = Element('a')
    3359          a.text = _str('Søk på nettet')
    3360
    3361          f = BytesIO()
    3362          tree = ElementTree(element=a)
    3363          tree.write(f)
    3364          data = f.getvalue().replace(_bytes('\n'),_bytes(''))
    3365          self.assertEqual(
    3366              _str('<a>Søk på nettet</a>').encode('ASCII', 'xmlcharrefreplace'),
    3367              data)
    3368
    3369 -    def test_encoding_tostring(self):
    3370          Element = self.etree.Element
    3371          tostring = self.etree.tostring
    3372
    3373          a = Element('a')
    3374          a.text = _str('Søk på nettet')
    3375          self.assertEqual(_str('<a>Søk på nettet</a>').encode('UTF-8'),
    3376                           tostring(a, encoding='utf-8'))
    3377
    3378 -    def test_encoding_tostring_unknown(self):
    3379          Element = self.etree.Element
    3380          tostring = self.etree.tostring
    3381
    3382          a = Element('a')
    3383          a.text = _str('Søk på nettet')
    3384          self.assertRaises(LookupError, tostring, a,
    3385                            encoding='Invalid Encoding')
    3386
    3387 -    def test_encoding_tostring_sub(self):
    3388          Element = self.etree.Element
    3389          SubElement = self.etree.SubElement
    3390          tostring = self.etree.tostring
    3391
    3392          a = Element('a')
    3393          b = SubElement(a, 'b')
    3394          b.text = _str('Søk på nettet')
    3395          self.assertEqual(_str('<b>Søk på nettet</b>').encode('UTF-8'),
    3396                           tostring(b, encoding='utf-8'))
    3397
    3398 -    def test_encoding_tostring_sub_tail(self):
    3399          Element = self.etree.Element
    3400          SubElement = self.etree.SubElement
    3401          tostring = self.etree.tostring
    3402
    3403          a = Element('a')
    3404          b = SubElement(a, 'b')
    3405          b.text = _str('Søk på nettet')
    3406          b.tail = _str('Søk')
    3407          self.assertEqual(_str('<b>Søk på nettet</b>Søk').encode('UTF-8'),
    3408                           tostring(b, encoding='utf-8'))
    3409
    3410 -    def test_encoding_tostring_default_encoding(self):
    3411          Element = self.etree.Element
    3412          SubElement = self.etree.SubElement
    3413          tostring = self.etree.tostring
    3414
    3415          a = Element('a')
    3416          a.text = _str('Søk på nettet')
    3417
    3418          expected = _bytes('<a>S&#248;k p&#229; nettet</a>')
    3419          self.assertEqual(
    3420              expected,
    3421              tostring(a))
    3422
    3423 -    def test_encoding_sub_tostring_default_encoding(self):
    3424          Element = self.etree.Element
    3425          SubElement = self.etree.SubElement
    3426          tostring = self.etree.tostring
    3427
    3428          a = Element('a')
    3429          b = SubElement(a, 'b')
    3430          b.text = _str('Søk på nettet')
    3431
    3432          expected = _bytes('<b>S&#248;k p&#229; nettet</b>')
    3433          self.assertEqual(
    3434              expected,
    3435              tostring(b))
    3436
    3437 -    def test_encoding_8bit_xml(self):
    3438          utext = _str('Søk på nettet')
    3439          uxml = _str('<p>%s</p>') % utext
    3440          prologue = _bytes('<?xml version="1.0" encoding="iso-8859-1" ?>')
    3441          isoxml = prologue + uxml.encode('iso-8859-1')
    3442          tree = self.etree.XML(isoxml)
    3443          self.assertEqual(utext, tree.text)
    3444
    3445 -    def test_encoding_utf8_bom(self):
    3446          utext = _str('Søk på nettet')
    3447          uxml = (_str('<?xml version="1.0" encoding="UTF-8"?>') +
    3448                  _str('<p>%s</p>') % utext)
    3449          bom = _bytes('\\xEF\\xBB\\xBF').decode("unicode_escape").encode("latin1")
    3450          xml = bom + uxml.encode("utf-8")
    3451          tree = etree.XML(xml)
    3452          self.assertEqual(utext, tree.text)
    3453
    3454 -    def test_encoding_8bit_parse_stringio(self):
    3455          utext = _str('Søk på nettet')
    3456          uxml = _str('<p>%s</p>') % utext
    3457          prologue = _bytes('<?xml version="1.0" encoding="iso-8859-1" ?>')
    3458          isoxml = prologue + uxml.encode('iso-8859-1')
    3459          el = self.etree.parse(BytesIO(isoxml)).getroot()
    3460          self.assertEqual(utext, el.text)
    3461
    3462 -    def test_deepcopy_elementtree(self):
    3463          Element = self.etree.Element
    3464          ElementTree = self.etree.ElementTree
    3465
    3466          a = Element('a')
    3467          a.text = "Foo"
    3468          atree = ElementTree(a)
    3469
    3470          btree = copy.deepcopy(atree)
    3471          self.assertEqual("Foo", atree.getroot().text)
    3472          self.assertEqual("Foo", btree.getroot().text)
    3473          self.assertFalse(btree is atree)
    3474          self.assertFalse(btree.getroot() is atree.getroot())
    3475
    3476 -    def test_deepcopy(self):
    3477          Element = self.etree.Element
    3478
    3479          a = Element('a')
    3480          a.text = 'Foo'
    3481
    3482          b = copy.deepcopy(a)
    3483          self.assertEqual('Foo', b.text)
    3484
    3485          b.text = 'Bar'
    3486          self.assertEqual('Bar', b.text)
    3487          self.assertEqual('Foo', a.text)
    3488
    3489          del a
    3490          self.assertEqual('Bar', b.text)
    3491
    3492 -    def test_deepcopy_tail(self):
    3493          Element = self.etree.Element
    3494
    3495          a = Element('a')
    3496          a.tail = 'Foo'
    3497
    3498          b = copy.deepcopy(a)
    3499          self.assertEqual('Foo', b.tail)
    3500
    3501          b.tail = 'Bar'
    3502          self.assertEqual('Bar', b.tail)
    3503          self.assertEqual('Foo', a.tail)
    3504
    3505          del a
    3506          self.assertEqual('Bar', b.tail)
    3507
    3508 -    def test_deepcopy_subelement(self):
    3509          Element = self.etree.Element
    3510          SubElement = self.etree.SubElement
    3511
    3512          root = Element('root')
    3513          a = SubElement(root, 'a')
    3514          a.text = 'FooText'
    3515          a.tail = 'FooTail'
    3516
    3517          b = copy.deepcopy(a)
    3518          self.assertEqual('FooText', b.text)
    3519          self.assertEqual('FooTail', b.tail)
    3520
    3521          b.text = 'BarText'
    3522          b.tail = 'BarTail'
    3523          self.assertEqual('BarTail', b.tail)
    3524          self.assertEqual('FooTail', a.tail)
    3525          self.assertEqual('BarText', b.text)
    3526          self.assertEqual('FooText', a.text)
    3527
    3528          del a
    3529          self.assertEqual('BarTail', b.tail)
    3530          self.assertEqual('BarText', b.text)
    3531
    3532 -    def test_deepcopy_namespaces(self):
    3533          root = self.etree.XML(_bytes('''<doc xmlns="dns" xmlns:t="tns">
    3534          <parent><node t:foo="bar" /></parent>
    3535          </doc>'''))
    3536          self.assertEqual(
    3537              root[0][0].get('{tns}foo'),
    3538              copy.deepcopy(root[0])[0].get('{tns}foo') )
    3539          self.assertEqual(
    3540              root[0][0].get('{tns}foo'),
    3541              copy.deepcopy(root[0][0]).get('{tns}foo') )
    3542
    3543 -    def test_deepcopy_append(self):
    3544          # previously caused a crash
    3545          Element = self.etree.Element
    3546          tostring = self.etree.tostring
    3547
    3548          a = Element('a')
    3549          b = copy.deepcopy(a)
    3550          a.append( Element('C') )
    3551          b.append( Element('X') )
    3552
    3553          self.assertEqual(_bytes('<a><C/></a>'),
    3554                            tostring(a).replace(_bytes(' '), _bytes('')))
    3555          self.assertEqual(_bytes('<a><X/></a>'),
    3556                            tostring(b).replace(_bytes(' '), _bytes('')))
    3557
    3558 -    def test_deepcopy_comment(self):
    3559          # previously caused a crash
    3560          # not supported by ET < 1.3!
    3561          Comment = self.etree.Comment
    3562
    3563          a = Comment("ONE")
    3564          b = copy.deepcopy(a)
    3565          b.text = "ANOTHER"
    3566
    3567          self.assertEqual('ONE',     a.text)
    3568          self.assertEqual('ANOTHER', b.text)
    3569
    3570 -    def test_shallowcopy(self):
    3571          Element = self.etree.Element
    3572
    3573          a = Element('a')
    3574          a.text = 'Foo'
    3575
    3576          b = copy.copy(a)
    3577          self.assertEqual('Foo', b.text)
    3578
    3579          b.text = 'Bar'
    3580          self.assertEqual('Bar', b.text)
    3581          self.assertEqual('Foo', a.text)
    3582          # XXX ElementTree will share nodes, but lxml.etree won't..
    3583
    3584 -    def test_shallowcopy_elementtree(self):
    3585          Element = self.etree.Element
    3586          ElementTree = self.etree.ElementTree
    3587
    3588          a = Element('a')
    3589          a.text = 'Foo'
    3590          atree = ElementTree(a)
    3591
    3592          btree = copy.copy(atree)
    3593          self.assertFalse(btree is atree)
    3594          self.assertTrue(btree.getroot() is atree.getroot())
    3595          self.assertEqual('Foo', atree.getroot().text)
    3596
    3597 -    def _test_element_boolean(self):
    3598          # deprecated as of ET 1.3/lxml 2.0
    3599          etree = self.etree
    3600          e = etree.Element('foo')
    3601          self.assertEqual(False, bool(e))
    3602          etree.SubElement(e, 'bar')
    3603          self.assertEqual(True, bool(e))
    3604          e = etree.Element('foo')
    3605          e.text = 'hey'
    3606          self.assertEqual(False, bool(e))
    3607          e = etree.Element('foo')
    3608          e.tail = 'bar'
    3609          self.assertEqual(False, bool(e))
    3610          e = etree.Element('foo')
    3611          e.set('bar', 'Bar')
    3612          self.assertEqual(False, bool(e))
    3613
    3614 -    def test_multiple_elementrees(self):
    3615          etree = self.etree
    3616
    3617          a = etree.Element('a')
    3618          b = etree.SubElement(a, 'b')
    3619
    3620          t = etree.ElementTree(a)
    3621          self.assertEqual(self._rootstring(t), _bytes('<a><b/></a>'))
    3622
    3623          t1 = etree.ElementTree(a)
    3624          self.assertEqual(self._rootstring(t1), _bytes('<a><b/></a>'))
    3625          self.assertEqual(self._rootstring(t),  _bytes('<a><b/></a>'))
    3626
    3627          t2 = etree.ElementTree(b)
    3628          self.assertEqual(self._rootstring(t2), _bytes('<b/>'))
    3629          self.assertEqual(self._rootstring(t1), _bytes('<a><b/></a>'))
    3630          self.assertEqual(self._rootstring(t),  _bytes('<a><b/></a>'))
    3631
    3632 -    def test_qname(self):
    3633          etree = self.etree
    3634          qname = etree.QName('myns', 'a')
    3635          a1 = etree.Element(qname)
    3636          a2 = etree.SubElement(a1, qname)
    3637          self.assertEqual(a1.tag, "{myns}a")
    3638          self.assertEqual(a2.tag, "{myns}a")
    3639
    3640 -    def test_qname_cmp(self):
    3641          etree = self.etree
    3642          qname1 = etree.QName('myns', 'a')
    3643          qname2 = etree.QName('myns', 'a')
    3644          self.assertEqual(qname1, "{myns}a")
    3645          self.assertEqual("{myns}a", qname2)
    3646          self.assertEqual(qname1, qname1)
    3647          self.assertEqual(qname1, qname2)
    3648
    3649 -    def test_qname_attribute_getset(self):
    3650          etree = self.etree
    3651          qname = etree.QName('myns', 'a')
    3652
    3653          a = etree.Element(qname)
    3654          a.set(qname, "value")
    3655
    3656          self.assertEqual(a.get(qname), "value")
    3657          self.assertEqual(a.get("{myns}a"), "value")
    3658
    3659 -    def test_qname_attrib(self):
    3660          etree = self.etree
    3661          qname = etree.QName('myns', 'a')
    3662
    3663          a = etree.Element(qname)
    3664          a.attrib[qname] = "value"
    3665
    3666          self.assertEqual(a.attrib[qname], "value")
    3667          self.assertEqual(a.attrib.get(qname), "value")
    3668
    3669          self.assertEqual(a.attrib["{myns}a"], "value")
    3670          self.assertEqual(a.attrib.get("{myns}a"), "value")
    3671
    3672 -    def test_qname_attribute_resolve(self):
    3673          etree = self.etree
    3674          qname = etree.QName('http://myns', 'a')
    3675          a = etree.Element(qname)
    3676          a.set(qname, qname)
    3677
    3678          self.assertXML(
    3679              _bytes('<ns0:a xmlns:ns0="http://myns" ns0:a="ns0:a"></ns0:a>'),
    3680              a)
    3681
    3682 -    def test_qname_attribute_resolve_new(self):
    3683          etree = self.etree
    3684          qname = etree.QName('http://myns', 'a')
    3685          a = etree.Element('a')
    3686          a.set('a', qname)
    3687
    3688          self.assertXML(
    3689              _bytes('<a xmlns:ns0="http://myns" a="ns0:a"></a>'),
    3690              a)
    3691
    3692 -    def test_qname_attrib_resolve(self):
    3693          etree = self.etree
    3694          qname = etree.QName('http://myns', 'a')
    3695          a = etree.Element(qname)
    3696          a.attrib[qname] = qname
    3697
    3698          self.assertXML(
    3699              _bytes('<ns0:a xmlns:ns0="http://myns" ns0:a="ns0:a"></ns0:a>'),
    3700              a)
    3701
    3702 -    def test_parser_version(self):
    3703          etree = self.etree
    3704          parser = etree.XMLParser()
    3705          if hasattr(parser, "version"):
    3706              # ElementTree 1.3+, cET
    3707              self.assertTrue(re.match("[^ ]+ [0-9.]+", parser.version))
    3708
    3709      # feed parser interface
    3710
    3711 -    def test_feed_parser_bytes(self):
    3712          parser = self.XMLParser()
    3713
    3714          parser.feed(_bytes('<?xml version='))
    3715          parser.feed(_bytes('"1.0"?><ro'))
    3716          parser.feed(_bytes('ot><'))
    3717          parser.feed(_bytes('a test="works"/'))
    3718          parser.feed(_bytes('></root'))
    3719          parser.feed(_bytes('>'))
    3720
    3721          root = parser.close()
    3722
    3723          self.assertEqual(root.tag, "root")
    3724          self.assertEqual(root[0].tag, "a")
    3725          self.assertEqual(root[0].get("test"), "works")
    3726
    3727 -    def test_feed_parser_unicode(self):
    3728          parser = self.XMLParser()
    3729
    3730          parser.feed(_str('<ro'))
    3731          parser.feed(_str('ot><'))
    3732          parser.feed(_str('a test="works"/'))
    3733          parser.feed(_str('></root'))
    3734          parser.feed(_str('>'))
    3735
    3736          root = parser.close()
    3737
    3738          self.assertEqual(root.tag, "root")
    3739          self.assertEqual(root[0].tag, "a")
    3740          self.assertEqual(root[0].get("test"), "works")
    3741
    3742      required_versions_ET['test_feed_parser_error_close_empty'] = (1,3)
    3743 -    def test_feed_parser_error_close_empty(self):
    3744          ParseError = self.etree.ParseError
    3745          parser = self.XMLParser()
    3746          self.assertRaises(ParseError, parser.close)
    3747
    3748      required_versions_ET['test_feed_parser_error_close_incomplete'] = (1,3)
    3749 -    def test_feed_parser_error_close_incomplete(self):
    3750          ParseError = self.etree.ParseError
    3751          parser = self.XMLParser()
    3752
    3753          parser.feed('<?xml version=')
    3754          parser.feed('"1.0"?><ro')
    3755
    3756          self.assertRaises(ParseError, parser.close)
    3757
    3758      required_versions_ET['test_feed_parser_error_broken'] = (1,3)
    3759 -    def test_feed_parser_error_broken(self):
    3760          ParseError = self.etree.ParseError
    3761          parser = self.XMLParser()
    3762
    3763          parser.feed('<?xml version=')
    3764          parser.feed('"1.0"?><ro')
    3765          try:
    3766              parser.feed('<><><><><><><')
    3767          except ParseError:
    3768              # can raise, but not required before close()
    3769              pass
    3770
    3771          self.assertRaises(ParseError, parser.close)
    3772
    3773      required_versions_ET['test_feed_parser_error_position'] = (1,3)
    3774 -    def test_feed_parser_error_position(self):
    3775          ParseError = self.etree.ParseError
    3776          parser = self.XMLParser()
    3777          try:
    3778              parser.close()
    3779          except ParseError:
    3780              e = sys.exc_info()[1]
    3781              self.assertNotEqual(None, e.code)
    3782              self.assertNotEqual(0, e.code)
    3783              self.assertTrue(isinstance(e.position, tuple))
    3784              self.assertTrue(e.position >= (0, 0))
    3785
    3786      # parser target interface
    3787
    3788      required_versions_ET['test_parser_target_property'] = (1,3)
    3789 -    def test_parser_target_property(self):
    3790          class Target(object):
    3791              pass
    3792
    3793          target = Target()
    3794          parser = self.XMLParser(target=target)
    3795
    3796          self.assertEqual(target, parser.target)
    3797
    3798 -    def test_parser_target_tag(self):
    3799          assertEqual = self.assertEqual
    3800          assertFalse  = self.assertFalse
    3801
    3802          events = []
    3803          class Target(object):
    3804              def start(self, tag, attrib):
    3805                  events.append("start")
    3806                  assertFalse(attrib)
    3807                  assertEqual("TAG", tag)
    3808              def end(self, tag):
    3809                  events.append("end")
    3810                  assertEqual("TAG", tag)
    3811              def close(self):
    3812                  return "DONE"
    3813
    3814          parser = self.XMLParser(target=Target())
    3815
    3816          parser.feed("<TAG/>")
    3817          done = parser.close()
    3818
    3819          self.assertEqual("DONE", done)
    3820          self.assertEqual(["start", "end"], events)
    3821
    3822 -    def test_parser_target_error_in_start(self):
    3823          assertEqual = self.assertEqual
    3824
    3825          events = []
    3826          class Target(object):
    3827              def start(self, tag, attrib):
    3828                  events.append("start")
    3829                  assertEqual("TAG", tag)
    3830                  raise ValueError("TEST")
    3831              def end(self, tag):
    3832                  events.append("end")
    3833                  assertEqual("TAG", tag)
    3834              def close(self):
    3835                  return "DONE"
    3836
    3837          parser = self.XMLParser(target=Target())
    3838
    3839          try:
    3840              parser.feed("<TAG/>")
    3841          except ValueError:
    3842              self.assertTrue('TEST' in str(sys.exc_info()[1]))
    3843          else:
    3844              self.assertTrue(False)
    3845          if 'lxml' in self.etree.__name__:
    3846              self.assertEqual(["start"], events)
    3847          else:
    3848              # cElementTree calls end() as well
    3849              self.assertTrue("start" in events)
    3850
    3851 -    def test_parser_target_error_in_end(self):
    3852          assertEqual = self.assertEqual
    3853
    3854          events = []
    3855          class Target(object):
    3856              def start(self, tag, attrib):
    3857                  events.append("start")
    3858                  assertEqual("TAG", tag)
    3859              def end(self, tag):
    3860                  events.append("end")
    3861                  assertEqual("TAG", tag)
    3862                  raise ValueError("TEST")
    3863              def close(self):
    3864                  return "DONE"
    3865
    3866          parser = self.XMLParser(target=Target())
    3867
    3868          try:
    3869              parser.feed("<TAG/>")
    3870          except ValueError:
    3871              self.assertTrue('TEST' in str(sys.exc_info()[1]))
    3872          else:
    3873              self.assertTrue(False)
    3874          self.assertEqual(["start", "end"], events)
    3875
    3876 -    def test_parser_target_error_in_close(self):
    3877          assertEqual = self.assertEqual
    3878
    3879          events = []
    3880          class Target(object):
    3881              def start(self, tag, attrib):
    3882                  events.append("start")
    3883                  assertEqual("TAG", tag)
    3884              def end(self, tag):
    3885                  events.append("end")
    3886                  assertEqual("TAG", tag)
    3887              def close(self):
    3888                  raise ValueError("TEST")
    3889
    3890          parser = self.XMLParser(target=Target())
    3891
    3892          try:
    3893              parser.feed("<TAG/>")
    3894              parser.close()
    3895          except ValueError:
    3896              self.assertTrue('TEST' in str(sys.exc_info()[1]))
    3897          else:
    3898              self.assertTrue(False)
    3899          self.assertEqual(["start", "end"], events)
    3900
    3901 -    def test_parser_target_error_in_start_and_close(self):
    3902          assertEqual = self.assertEqual
    3903
    3904          events = []
    3905          class Target(object):
    3906              def start(self, tag, attrib):
    3907                  events.append("start")
    3908                  assertEqual("TAG", tag)
    3909                  raise IndexError("TEST-IE")
    3910              def end(self, tag):
    3911                  events.append("end")
    3912                  assertEqual("TAG", tag)
    3913              def close(self):
    3914                  raise ValueError("TEST-VE")
    3915
    3916          parser = self.XMLParser(target=Target())
    3917
    3918          try:
    3919              parser.feed("<TAG/>")
    3920              parser.close()
    3921          except IndexError:
    3922              if 'lxml' in self.etree.__name__:
    3923                  # we try not to swallow the initial exception in Py2
    3924                  self.assertTrue(sys.version_info[0] < 3)
    3925              self.assertTrue('TEST-IE' in str(sys.exc_info()[1]))
    3926          except ValueError:
    3927              if 'lxml' in self.etree.__name__:
    3928                  self.assertTrue(sys.version_info[0] >= 3)
    3929              self.assertTrue('TEST-VE' in str(sys.exc_info()[1]))
    3930          else:
    3931              self.assertTrue(False)
    3932
    3933          if 'lxml' in self.etree.__name__:
    3934              self.assertEqual(["start"], events)
    3935          else:
    3936              # cElementTree calls end() as well
    3937              self.assertTrue("start" in events)
    3938
    3939 -    def test_elementtree_parser_target(self):
    3940          assertEqual = self.assertEqual
    3941          assertFalse  = self.assertFalse
    3942          Element = self.etree.Element
    3943
    3944          events = []
    3945          class Target(object):
    3946              def start(self, tag, attrib):
    3947                  events.append("start")
    3948                  assertFalse(attrib)
    3949                  assertEqual("TAG", tag)
    3950              def end(self, tag):
    3951                  events.append("end")
    3952                  assertEqual("TAG", tag)
    3953              def close(self):
    3954                  return Element("DONE")
    3955
    3956          parser = self.XMLParser(target=Target())
    3957          tree = self.etree.ElementTree()
    3958          tree.parse(BytesIO("<TAG/>"), parser=parser)
    3959
    3960          self.assertEqual("DONE", tree.getroot().tag)
    3961          self.assertEqual(["start", "end"], events)
    3962
    3963 -    def test_parser_target_attrib(self):
    3964          assertEqual = self.assertEqual
    3965
    3966          events = []
    3967          class Target(object):
    3968              def start(self, tag, attrib):
    3969                  events.append("start-" + tag)
    3970                  for name, value in attrib.items():
    3971                      assertEqual(tag + name, value)
    3972              def end(self, tag):
    3973                  events.append("end-" + tag)
    3974              def close(self):
    3975                  return "DONE"
    3976
    3977          parser = self.XMLParser(target=Target())
    3978
    3979          parser.feed('<root a="roota" b="rootb"><sub c="subc"/></root>')
    3980          done = parser.close()
    3981
    3982          self.assertEqual("DONE", done)
    3983          self.assertEqual(["start-root", "start-sub", "end-sub", "end-root"],
    3984                            events)
    3985
    3986 -    def test_parser_target_data(self):
    3987          events = []
    3988          class Target(object):
    3989              def start(self, tag, attrib):
    3990                  events.append("start-" + tag)
    3991              def end(self, tag):
    3992                  events.append("end-" + tag)
    3993              def data(self, data):
    3994                  events.append("data-" + data)
    3995              def close(self):
    3996                  return "DONE"
    3997
    3998          parser = self.XMLParser(target=Target())
    3999
    4000          parser.feed('<root>A<sub/>B</root>')
    4001          done = parser.close()
    4002
    4003          self.assertEqual("DONE", done)
    4004          self.assertEqual(["start-root", "data-A", "start-sub",
    4005                             "end-sub", "data-B", "end-root"],
    4006                            events)
    4007
    4008 -    def test_parser_target_entity(self):
    4009          events = []
    4010          class Target(object):
    4011              def __init__(self):
    4012                  self._data = []
    4013              def _flush_data(self):
    4014                  if self._data:
    4015                      events.append("data-" + ''.join(self._data))
    4016                      del self._data[:]
    4017              def start(self, tag, attrib):
    4018                  self._flush_data()
    4019                  events.append("start-" + tag)
    4020              def end(self, tag):
    4021                  self._flush_data()
    4022                  events.append("end-" + tag)
    4023              def data(self, data):
    4024                  self._data.append(data)
    4025              def close(self):
    4026                  self._flush_data()
    4027                  return "DONE"
    4028
    4029          parser = self.XMLParser(target=Target())
    4030
    4031          dtd = '''
    4032              <!DOCTYPE root [
    4033              <!ELEMENT root (sub*)>
    4034              <!ELEMENT sub (#PCDATA)>
    4035              <!ENTITY ent "an entity">
    4036          ]>
    4037          '''
    4038          parser.feed(dtd+'<root><sub/><sub>this is &ent;</sub><sub/></root>')
    4039          done = parser.close()
    4040
    4041          self.assertEqual("DONE", done)
    4042          self.assertEqual(["start-root", "start-sub", "end-sub", "start-sub",
    4043                             "data-this is an entity",
    4044                             "end-sub", "start-sub", "end-sub", "end-root"],
    4045                            events)
    4046
    4047      required_versions_ET['test_parser_target_entity_unknown'] = (1,3)
    4048 -    def test_parser_target_entity_unknown(self):
    4049          events = []
    4050          class Target(object):
    4051              def __init__(self):
    4052                  self._data = []
    4053              def _flush_data(self):
    4054                  if self._data:
    4055                      events.append("data-" + ''.join(self._data))
    4056                      del self._data[:]
    4057              def start(self, tag, attrib):
    4058                  self._flush_data()
    4059                  events.append("start-" + tag)
    4060              def end(self, tag):
    4061                  self._flush_data()
    4062                  events.append("end-" + tag)
    4063              def data(self, data):
    4064                  self._data.append(data)
    4065              def close(self):
    4066                  self._flush_data()
    4067                  return "DONE"
    4068
    4069          parser = self.XMLParser(target=Target())
    4070
    4071          def feed():
    4072              parser.feed('<root><sub/><sub>some &ent;</sub><sub/></root>')
    4073              parser.close()
    4074
    4075          self.assertRaises(self.etree.ParseError, feed)
    4076
    4077      @et_needs_pyversion(3, 8, 0, 'alpha', 4)
    4078 -    def test_parser_target_start_end_ns(self):
    4079          class Builder(list):
    4080              def start(self, tag, attrib):
    4081                  self.append(("start", tag))
    4082              def end(self, tag):
    4083                  self.append(("end", tag))
    4084              def data(self, text):
    4085                  pass
    4086              def pi(self, target, data):
    4087                  self.append(("pi", target, data))
    4088              def comment(self, data):
    4089                  self.append(("comment", data))
    4090              def start_ns(self, prefix, uri):
    4091                  self.append(("start-ns", prefix, uri))
    4092              def end_ns(self, prefix):
    4093                  self.append(("end-ns", prefix))
    4094
    4095          builder = Builder()
    4096          parser = self.etree.XMLParser(target=builder)
    4097          parser.feed(textwrap.dedent("""\
    4098              <?pi data?>
    4099              <!-- comment -->
    4100              <root xmlns='namespace'>
    4101                 <element key='value'>text</element>
    4102                 <element>text</element>tail
    4103                 <empty-element/>
    4104              </root>
    4105              """))
    4106          self.assertEqual(builder, [
    4107                  ('pi', 'pi', 'data'),
    4108                  ('comment', ' comment '),
    4109                  ('start-ns', '', 'namespace'),
    4110                  ('start', '{namespace}root'),
    4111                  ('start', '{namespace}element'),
    4112                  ('end', '{namespace}element'),
    4113                  ('start', '{namespace}element'),
    4114                  ('end', '{namespace}element'),
    4115                  ('start', '{namespace}empty-element'),
    4116                  ('end', '{namespace}empty-element'),
    4117                  ('end', '{namespace}root'),
    4118                  ('end-ns', ''),
    4119              ])
    4120
    4121      @et_needs_pyversion(3, 8, 0, 'alpha', 4)
    4122 -    def test_parser_target_end_ns(self):
    4123          class Builder(list):
    4124              def end_ns(self, prefix):
    4125                  self.append(("end-ns", prefix))
    4126
    4127          builder = Builder()
    4128          parser = self.etree.XMLParser(target=builder)
    4129          parser.feed(textwrap.dedent("""\
    4130              <?pi data?>
    4131              <!-- comment -->
    4132              <root xmlns='namespace' xmlns:p='pns'>
    4133                 <element key='value'>text</element>
    4134                 <p:element>text</p:element>tail
    4135                 <empty-element/>
    4136              </root>
    4137              """))
    4138          self.assertEqual(builder, [
    4139                  ('end-ns', 'p'),
    4140                  ('end-ns', ''),
    4141              ])
    4142
    4143 -    def test_treebuilder(self):
    4144          builder = self.etree.TreeBuilder()
    4145          el = builder.start("root", {'a':'A', 'b':'B'})
    4146          self.assertEqual("root", el.tag)
    4147          self.assertEqual({'a':'A', 'b':'B'}, el.attrib)
    4148          builder.data("ROOTTEXT")
    4149          el = builder.start("child", {'x':'X', 'y':'Y'})
    4150          self.assertEqual("child", el.tag)
    4151          self.assertEqual({'x':'X', 'y':'Y'}, el.attrib)
    4152          builder.data("CHILDTEXT")
    4153          el = builder.end("child")
    4154          self.assertEqual("child", el.tag)
    4155          self.assertEqual({'x':'X', 'y':'Y'}, el.attrib)
    4156          self.assertEqual("CHILDTEXT", el.text)
    4157          self.assertEqual(None, el.tail)
    4158          builder.data("CHILDTAIL")
    4159          root = builder.end("root")
    4160
    4161          self.assertEqual("root", root.tag)
    4162          self.assertEqual("ROOTTEXT", root.text)
    4163          self.assertEqual("CHILDTEXT", root[0].text)
    4164          self.assertEqual("CHILDTAIL", root[0].tail)
    4165
    4166 -    def test_treebuilder_target(self):
    4167          parser = self.XMLParser(target=self.etree.TreeBuilder())
    4168          parser.feed('<root>ROOTTEXT<child>CHILDTEXT</child>CHILDTAIL</root>')
    4169          root = parser.close()
    4170
    4171          self.assertEqual("root", root.tag)
    4172          self.assertEqual("ROOTTEXT", root.text)
    4173          self.assertEqual("CHILDTEXT", root[0].text)
    4174          self.assertEqual("CHILDTAIL", root[0].tail)
    4175
    4176      @et_needs_pyversion(3, 8, 0, 'alpha', 4)
    4177 -    def test_treebuilder_comment(self):
    4178          ET = self.etree
    4179          b = ET.TreeBuilder()
    4180          self.assertEqual(b.comment('ctext').tag, ET.Comment)
    4181          self.assertEqual(b.comment('ctext').text, 'ctext')
    4182
    4183          b = ET.TreeBuilder(comment_factory=ET.Comment)
    4184          self.assertEqual(b.comment('ctext').tag, ET.Comment)
    4185          self.assertEqual(b.comment('ctext').text, 'ctext')
    4186
    4187          #b = ET.TreeBuilder(comment_factory=len)
    4188          #self.assertEqual(b.comment('ctext'), len('ctext'))
    4189
    4190      @et_needs_pyversion(3, 8, 0, 'alpha', 4)
    4191 -    def test_treebuilder_pi(self):
    4192          ET = self.etree
    4193          is_lxml = ET.__name__ == 'lxml.etree'
    4194
    4195          b = ET.TreeBuilder()
    4196          self.assertEqual(b.pi('target', None).tag, ET.PI)
    4197          if is_lxml:
    4198              self.assertEqual(b.pi('target', None).target, 'target')
    4199          else:
    4200              self.assertEqual(b.pi('target', None).text, 'target')
    4201
    4202          b = ET.TreeBuilder(pi_factory=ET.PI)
    4203          self.assertEqual(b.pi('target').tag, ET.PI)
    4204          if is_lxml:
    4205              self.assertEqual(b.pi('target').target, "target")
    4206          else:
    4207              self.assertEqual(b.pi('target').text, "target")
    4208          self.assertEqual(b.pi('pitarget', ' text ').tag, ET.PI)
    4209          if is_lxml:
    4210              self.assertEqual(b.pi('pitarget', ' text ').target, "pitarget")
    4211              self.assertEqual(b.pi('pitarget', ' text ').text, " text ")
    4212          else:
    4213              self.assertEqual(b.pi('pitarget', ' text ').text, "pitarget  text ")
    4214
    4215          #b = ET.TreeBuilder(pi_factory=lambda target, text: (len(target), text))
    4216          #self.assertEqual(b.pi('target'), (len('target'), None))
    4217          #self.assertEqual(b.pi('pitarget', ' text '), (len('pitarget'), ' text '))
    4218
    4219 -    def test_late_tail(self):
    4220          # Issue #37399: The tail of an ignored comment could overwrite the text before it.
    4221          ET = self.etree
    4222          class TreeBuilderSubclass(ET.TreeBuilder):
    4223              pass
    4224
    4225          if ET.__name__ == 'lxml.etree':
    4226              def assert_content(a):
    4227                  self.assertEqual(a.text, "text")
    4228                  self.assertEqual(a[0].tail, "tail")
    4229          else:
    4230              def assert_content(a):
    4231                  self.assertEqual(a.text, "texttail")
    4232
    4233          xml = "<a>text<!-- comment -->tail</a>"
    4234          a = ET.fromstring(xml)
    4235          assert_content(a)
    4236
    4237          parser = ET.XMLParser(target=TreeBuilderSubclass())
    4238          parser.feed(xml)
    4239          a = parser.close()
    4240          assert_content(a)
    4241
    4242          xml = "<a>text<?pi data?>tail</a>"
    4243          a = ET.fromstring(xml)
    4244          assert_content(a)
    4245
    4246          xml = "<a>text<?pi data?>tail</a>"
    4247          parser = ET.XMLParser(target=TreeBuilderSubclass())
    4248          parser.feed(xml)
    4249          a = parser.close()
    4250          assert_content(a)
    4251
    4252      @et_needs_pyversion(3, 8, 0, 'alpha', 4)
    4253 -    def test_late_tail_mix_pi_comments(self):
    4254          # Issue #37399: The tail of an ignored comment could overwrite the text before it.
    4255          # Test appending tails to comments/pis.
    4256          ET = self.etree
    4257          class TreeBuilderSubclass(ET.TreeBuilder):
    4258              pass
    4259
    4260          xml = "<a>text<?pi1?> <!-- comment -->\n<?pi2?>tail</a>"
    4261          parser = ET.XMLParser(target=ET.TreeBuilder(insert_comments=True, insert_pis=False))
    4262          parser.feed(xml)
    4263          a = parser.close()
    4264          self.assertEqual(a[0].text, ' comment ')
    4265          self.assertEqual(a[0].tail, '\ntail')
    4266          self.assertEqual(a.text, "text ")
    4267
    4268          parser = ET.XMLParser(target=TreeBuilderSubclass(insert_comments=True, insert_pis=False))
    4269          parser.feed(xml)
    4270          a = parser.close()
    4271          self.assertEqual(a[0].text, ' comment ')
    4272          self.assertEqual(a[0].tail, '\ntail')
    4273          self.assertEqual(a.text, "text ")
    4274
    4275          xml = "<a>text<!-- comment -->\n<?pi data?>tail</a>"
    4276          parser = ET.XMLParser(target=ET.TreeBuilder(insert_pis=True, insert_comments=False))
    4277          parser.feed(xml)
    4278          a = parser.close()
    4279          self.assertEqual(a[0].text[-4:], 'data')
    4280          self.assertEqual(a[0].tail, 'tail')
    4281          self.assertEqual(a.text, "text\n")
    4282
    4283          parser = ET.XMLParser(target=TreeBuilderSubclass(insert_pis=True, insert_comments=False))
    4284          parser.feed(xml)
    4285          a = parser.close()
    4286          self.assertEqual(a[0].text[-4:], 'data')
    4287          self.assertEqual(a[0].tail, 'tail')
    4288          self.assertEqual(a.text, "text\n")
    4289
    4290      # helper methods
    4291
    4292 -    def _writeElement(self, element, encoding='us-ascii'):
    4293          """Write out element for comparison.
    4294          """
    4295          data = self.etree.tostring(element, encoding=encoding)
    4296          return canonicalize(data)
    4297
    4298 -    def _writeElementFile(self, element, encoding='us-ascii'):
    4299          """Write out element for comparison, using real file.
    4300          """
    4301          ElementTree = self.etree.ElementTree
    4302          with tmpfile() as filename:
    4303              with open(filename, 'wb') as f:
    4304                  tree = ElementTree(element=element)
    4305                  tree.write(f, encoding=encoding)
    4306              with open(filename, 'rb') as f:
    4307                  data = f.read()
    4308          return canonicalize(data)
    4309
    4310 -    def assertXML(self, expected, element, encoding='us-ascii'):
    4311          """Writes element out and checks whether it is expected.
    4312
    4313          Does this two ways; once using BytesIO, once using a real file.
    4314          """
    4315          if isinstance(expected, unicode):
    4316              expected = expected.encode(encoding)
    4317          self.assertEqual(expected, self._writeElement(element, encoding))
    4318          self.assertEqual(expected, self._writeElementFile(element, encoding))
    4319
    4320 -    def assertEncodingDeclaration(self, result, encoding):
    4321          "Checks if the result XML byte string specifies the encoding."
    4322          enc_re = r"<\?xml[^>]+ encoding=[\"']([^\"']+)[\"']"
    4323          if isinstance(result, str):
    4324              has_encoding = re.compile(enc_re).match
    4325          else:
    4326              has_encoding = re.compile(_bytes(enc_re)).match
    4327          self.assertTrue(has_encoding(result))
    4328          result_encoding = has_encoding(result).group(1)
    4329          self.assertEqual(result_encoding.upper(), encoding.upper())
    4330
    4331 -    def _rootstring(self, tree):
    4332          return self.etree.tostring(tree.getroot()).replace(
    4333              _bytes(' '), _bytes('')).replace(_bytes('\n'), _bytes(''))
    4334
    4335 -    def _check_element_tree(self, tree):
    4336          self._check_element(tree.getroot())
    4337
    4338 -    def _check_element(self, element):
    4339          self.assertTrue(hasattr(element, 'tag'))
    4340          self.assertTrue(hasattr(element, 'attrib'))
    4341          self.assertTrue(hasattr(element, 'text'))
    4342          self.assertTrue(hasattr(element, 'tail'))
    4343          self._check_string(element.tag)
    4344          self._check_mapping(element.attrib)
    4345          if element.text is not None:
    4346              self._check_string(element.text)
    4347          if element.tail is not None:
    4348              self._check_string(element.tail)
    4349
    4350 -    def _check_string(self, string):
    4351          len(string)
    4352          for char in string:
    4353              self.assertEqual(1, len(char))
    4354          new_string = string + ""
    4355          new_string = string + " "
    4356          string[:0]
    4357
    4358 -    def _check_mapping(self, mapping):
    4359          len(mapping)
    4360          keys = mapping.keys()
    4361          values = mapping.values()
    4362          items = mapping.items()
    4363          for key in keys:
    4364              item = mapping[key]
    4365          mapping["key"] = "value"
    4366          self.assertEqual("value", mapping["key"])
    4367
    4368
    4369 -class _ElementSlicingTest(unittest.TestCase):
    4370      etree = None
    4371
    4372 -    def _elem_tags(self, elemlist):
    4373          return [e.tag for e in elemlist]
    4374
    4375 -    def _subelem_tags(self, elem):
    4376          return self._elem_tags(list(elem))
    4377
    4378 -    def _make_elem_with_children(self, numchildren):
    4379          """Create an Element with a tag 'a', with the given amount of children
    4380             named 'a0', 'a1' ... and so on.
    4381
    4382          """
    4383          e = self.etree.Element('a')
    4384          for i in range(numchildren):
    4385              self.etree.SubElement(e, 'a%s' % i)
    4386          return e
    4387
    4388 -    def test_getslice_single_index(self):
    4389          e = self._make_elem_with_children(10)
    4390
    4391          self.assertEqual(e[1].tag, 'a1')
    4392          self.assertEqual(e[-2].tag, 'a8')
    4393
    4394          self.assertRaises(IndexError, lambda: e[12])
    4395          self.assertRaises(IndexError, lambda: e[-12])
    4396
    4397 -    def test_getslice_range(self):
    4398          e = self._make_elem_with_children(6)
    4399
    4400          self.assertEqual(self._elem_tags(e[3:]), ['a3', 'a4', 'a5'])
    4401          self.assertEqual(self._elem_tags(e[3:6]), ['a3', 'a4', 'a5'])
    4402          self.assertEqual(self._elem_tags(e[3:16]), ['a3', 'a4', 'a5'])
    4403          self.assertEqual(self._elem_tags(e[3:5]), ['a3', 'a4'])
    4404          self.assertEqual(self._elem_tags(e[3:-1]), ['a3', 'a4'])
    4405          self.assertEqual(self._elem_tags(e[:2]), ['a0', 'a1'])
    4406
    4407 -    def test_getslice_steps(self):
    4408          e = self._make_elem_with_children(10)
    4409
    4410          self.assertEqual(self._elem_tags(e[8:10:1]), ['a8', 'a9'])
    4411          self.assertEqual(self._elem_tags(e[::3]), ['a0', 'a3', 'a6', 'a9'])
    4412          self.assertEqual(self._elem_tags(e[::8]), ['a0', 'a8'])
    4413          self.assertEqual(self._elem_tags(e[1::8]), ['a1', 'a9'])
    4414          self.assertEqual(self._elem_tags(e[3::sys.maxsize]), ['a3'])
    4415          self.assertEqual(self._elem_tags(e[3::sys.maxsize<<64]), ['a3'])
    4416
    4417 -    def test_getslice_negative_steps(self):
    4418          e = self._make_elem_with_children(4)
    4419
    4420          self.assertEqual(self._elem_tags(e[::-1]), ['a3', 'a2', 'a1', 'a0'])
    4421          self.assertEqual(self._elem_tags(e[::-2]), ['a3', 'a1'])
    4422          self.assertEqual(self._elem_tags(e[3::-sys.maxsize]), ['a3'])
    4423          self.assertEqual(self._elem_tags(e[3::-sys.maxsize-1]), ['a3'])
    4424          self.assertEqual(self._elem_tags(e[3::-sys.maxsize<<64]), ['a3'])
    4425
    4426 -    def test_delslice(self):
    4427          e = self._make_elem_with_children(4)
    4428          del e[0:2]
    4429          self.assertEqual(self._subelem_tags(e), ['a2', 'a3'])
    4430
    4431          e = self._make_elem_with_children(4)
    4432          del e[0:]
    4433          self.assertEqual(self._subelem_tags(e), [])
    4434
    4435          e = self._make_elem_with_children(4)
    4436          del e[::-1]
    4437          self.assertEqual(self._subelem_tags(e), [])
    4438
    4439          e = self._make_elem_with_children(4)
    4440          del e[::-2]
    4441          self.assertEqual(self._subelem_tags(e), ['a0', 'a2'])
    4442
    4443          e = self._make_elem_with_children(4)
    4444          del e[1::2]
    4445          self.assertEqual(self._subelem_tags(e), ['a0', 'a2'])
    4446
    4447          e = self._make_elem_with_children(2)
    4448          del e[::2]
    4449          self.assertEqual(self._subelem_tags(e), ['a1'])
    4450
    4451 -    def test_setslice_single_index(self):
    4452          e = self._make_elem_with_children(4)
    4453          e[1] = self.etree.Element('b')
    4454          self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
    4455
    4456          e[-2] = self.etree.Element('c')
    4457          self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'c', 'a3'])
    4458
    4459          with self.assertRaises(IndexError):
    4460              e[5] = self.etree.Element('d')
    4461          with self.assertRaises(IndexError):
    4462              e[-5] = self.etree.Element('d')
    4463          self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'c', 'a3'])
    4464
    4465 -    def test_setslice_range(self):
    4466          e = self._make_elem_with_children(4)
    4467          e[1:3] = [self.etree.Element('b%s' % i) for i in range(2)]
    4468          self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'b1', 'a3'])
    4469
    4470          e = self._make_elem_with_children(4)
    4471          e[1:3] = [self.etree.Element('b')]
    4472          self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a3'])
    4473
    4474          e = self._make_elem_with_children(4)
    4475          e[1:3] = [self.etree.Element('b%s' % i) for i in range(3)]
    4476          self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'b1', 'b2', 'a3'])
    4477
    4478 -    def test_setslice_steps(self):
    4479          e = self._make_elem_with_children(6)
    4480          e[1:5:2] = [self.etree.Element('b%s' % i) for i in range(2)]
    4481          self.assertEqual(self._subelem_tags(e), ['a0', 'b0', 'a2', 'b1', 'a4', 'a5'])
    4482
    4483          e = self._make_elem_with_children(6)
    4484          with self.assertRaises(ValueError):
    4485              e[1:5:2] = [self.etree.Element('b')]
    4486          with self.assertRaises(ValueError):
    4487              e[1:5:2] = [self.etree.Element('b%s' % i) for i in range(3)]
    4488          with self.assertRaises(ValueError):
    4489              e[1:5:2] = []
    4490          self.assertEqual(self._subelem_tags(e), ['a0', 'a1', 'a2', 'a3', 'a4', 'a5'])
    4491
    4492          e = self._make_elem_with_children(4)
    4493          e[1::sys.maxsize] = [self.etree.Element('b')]
    4494          self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
    4495          e[1::sys.maxsize<<64] = [self.etree.Element('c')]
    4496          self.assertEqual(self._subelem_tags(e), ['a0', 'c', 'a2', 'a3'])
    4497
    4498 -    def test_setslice_negative_steps(self):
    4499          e = self._make_elem_with_children(4)
    4500          e[2:0:-1] = [self.etree.Element('b%s' % i) for i in range(2)]
    4501          self.assertEqual(self._subelem_tags(e), ['a0', 'b1', 'b0', 'a3'])
    4502
    4503          e = self._make_elem_with_children(4)
    4504          with self.assertRaises(ValueError):
    4505              e[2:0:-1] = [self.etree.Element('b')]
    4506          with self.assertRaises(ValueError):
    4507              e[2:0:-1] = [self.etree.Element('b%s' % i) for i in range(3)]
    4508          with self.assertRaises(ValueError):
    4509              e[2:0:-1] = []
    4510          self.assertEqual(self._subelem_tags(e), ['a0', 'a1', 'a2', 'a3'])
    4511
    4512          e = self._make_elem_with_children(4)
    4513          e[1::-sys.maxsize] = [self.etree.Element('b')]
    4514          self.assertEqual(self._subelem_tags(e), ['a0', 'b', 'a2', 'a3'])
    4515          e[1::-sys.maxsize-1] = [self.etree.Element('c')]
    4516          self.assertEqual(self._subelem_tags(e), ['a0', 'c', 'a2', 'a3'])
    4517          e[1::-sys.maxsize<<64] = [self.etree.Element('d')]
    4518          self.assertEqual(self._subelem_tags(e), ['a0', 'd', 'a2', 'a3'])
    4519
    4520
    4521 -class _XMLPullParserTest(unittest.TestCase):
    4522      etree = None
    4523
    4524 -    def _close_and_return_root(self, parser):
    4525          if 'ElementTree' in self.etree.__name__:
    4526              # ElementTree's API is a bit unwieldy in Py3.4
    4527              root = parser._close_and_return_root()
    4528          else:
    4529              root = parser.close()
    4530          return root
    4531
    4532 -    def _feed(self, parser, data, chunk_size=None):
    4533          if chunk_size is None:
    4534              parser.feed(data)
    4535          else:
    4536              for i in range(0, len(data), chunk_size):
    4537                  parser.feed(data[i:i+chunk_size])
    4538
    4539 -    def assert_events(self, parser, expected, max_events=None):
    4540          self.assertEqual(
    4541              [(event, (elem.tag, elem.text))
    4542               for event, elem in islice(parser.read_events(), max_events)],
    4543              expected)
    4544
    4545 -    def assert_event_tuples(self, parser, expected, max_events=None):
    4546          self.assertEqual(
    4547              list(islice(parser.read_events(), max_events)),
    4548              expected)
    4549
    4550 -    def assert_event_tags(self, parser, expected, max_events=None):
    4551          events = islice(parser.read_events(), max_events)
    4552          self.assertEqual([(action, elem.tag) for action, elem in events],
    4553                           expected)
    4554
    4555 -    def test_simple_xml(self):
    4556          for chunk_size in (None, 1, 5):
    4557              #with self.subTest(chunk_size=chunk_size):
    4558                  parser = self.etree.XMLPullParser()
    4559                  self.assert_event_tags(parser, [])
    4560                  self._feed(parser, "<!-- comment -->\n", chunk_size)
    4561                  self.assert_event_tags(parser, [])
    4562                  self._feed(parser,
    4563                             "<root>\n  <element key='value'>text</element",
    4564                             chunk_size)
    4565                  self.assert_event_tags(parser, [])
    4566                  self._feed(parser, ">\n", chunk_size)
    4567                  self.assert_event_tags(parser, [('end', 'element')])
    4568                  self._feed(parser, "<element>text</element>tail\n", chunk_size)
    4569                  self._feed(parser, "<empty-element/>\n", chunk_size)
    4570                  self.assert_event_tags(parser, [
    4571                      ('end', 'element'),
    4572                      ('end', 'empty-element'),
    4573                      ])
    4574                  self._feed(parser, "</root>\n", chunk_size)
    4575                  self.assert_event_tags(parser, [('end', 'root')])
    4576                  root = self._close_and_return_root(parser)
    4577                  self.assertEqual(root.tag, 'root')
    4578
    4579 -    def test_feed_while_iterating(self):
    4580          parser = self.etree.XMLPullParser()
    4581          it = parser.read_events()
    4582          self._feed(parser, "<root>\n  <element key='value'>text</element>\n")
    4583          action, elem = next(it)
    4584          self.assertEqual((action, elem.tag), ('end', 'element'))
    4585          self._feed(parser, "</root>\n")
    4586          action, elem = next(it)
    4587          self.assertEqual((action, elem.tag), ('end', 'root'))
    4588          with self.assertRaises(StopIteration):
    4589              next(it)
    4590
    4591 -    def test_simple_xml_with_ns(self):
    4592          parser = self.etree.XMLPullParser()
    4593          self.assert_event_tags(parser, [])
    4594          self._feed(parser, "<!-- comment -->\n")
    4595          self.assert_event_tags(parser, [])
    4596          self._feed(parser, "<root xmlns='namespace'>\n")
    4597          self.assert_event_tags(parser, [])
    4598          self._feed(parser, "<element key='value'>text</element")
    4599          self.assert_event_tags(parser, [])
    4600          self._feed(parser, ">\n")
    4601          self.assert_event_tags(parser, [('end', '{namespace}element')])
    4602          self._feed(parser, "<element>text</element>tail\n")
    4603          self._feed(parser, "<empty-element/>\n")
    4604          self.assert_event_tags(parser, [
    4605              ('end', '{namespace}element'),
    4606              ('end', '{namespace}empty-element'),
    4607              ])
    4608          self._feed(parser, "</root>\n")
    4609          self.assert_event_tags(parser, [('end', '{namespace}root')])
    4610          root = self._close_and_return_root(parser)
    4611          self.assertEqual(root.tag, '{namespace}root')
    4612
    4613 -    def test_ns_events(self):
    4614          parser = self.etree.XMLPullParser(events=('start-ns', 'end-ns'))
    4615          self._feed(parser, "<!-- comment -->\n")
    4616          self._feed(parser, "<root xmlns='namespace'>\n")
    4617          self.assertEqual(
    4618              list(parser.read_events()),
    4619              [('start-ns', ('', 'namespace'))])
    4620          self._feed(parser, "<element key='value'>text</element")
    4621          self._feed(parser, ">\n")
    4622          self._feed(parser, "<element>text</element>tail\n")
    4623          self._feed(parser, "<empty-element/>\n")
    4624          self._feed(parser, "</root>\n")
    4625          self.assertEqual(list(parser.read_events()), [('end-ns', None)])
    4626          parser.close()
    4627
    4628 -    def test_ns_events_end_ns_only(self):
    4629          parser = self.etree.XMLPullParser(events=['end-ns'])
    4630          self._feed(parser, "<!-- comment -->\n")
    4631          self._feed(parser, "<root xmlns='namespace' xmlns:a='abc' xmlns:b='xyz'>\n")
    4632          self.assertEqual(list(parser.read_events()), [])
    4633          self._feed(parser, "<a:element key='value'>text</a:element")
    4634          self._feed(parser, ">\n")
    4635          self._feed(parser, "<b:element>text</b:element>tail\n")
    4636          self._feed(parser, "<empty-element/>\n")
    4637          self.assertEqual(list(parser.read_events()), [])
    4638          self._feed(parser, "</root>\n")
    4639          self.assertEqual(list(parser.read_events()), [
    4640              ('end-ns', None),
    4641              ('end-ns', None),
    4642              ('end-ns', None),
    4643          ])
    4644          parser.close()
    4645
    4646      @et_needs_pyversion(3,8)
    4647 -    def test_ns_events_start(self):
    4648          parser = self.etree.XMLPullParser(events=('start-ns', 'start', 'end'))
    4649          self._feed(parser, "<tag xmlns='abc' xmlns:p='xyz'>\n")
    4650          self.assert_event_tuples(parser, [
    4651              ('start-ns', ('', 'abc')),
    4652              ('start-ns', ('p', 'xyz')),
    4653          ], max_events=2)
    4654          self.assert_event_tags(parser, [
    4655              ('start', '{abc}tag'),
    4656          ], max_events=1)
    4657
    4658          self._feed(parser, "<child />\n")
    4659          self.assert_event_tags(parser, [
    4660              ('start', '{abc}child'),
    4661              ('end', '{abc}child'),
    4662          ])
    4663
    4664          self._feed(parser, "</tag>\n")
    4665          parser.close()
    4666          self.assert_event_tags(parser, [
    4667              ('end', '{abc}tag'),
    4668          ])
    4669
    4670      @et_needs_pyversion(3,8)
    4671 -    def test_ns_events_start_end(self):
    4672          parser = self.etree.XMLPullParser(events=('start-ns', 'start', 'end', 'end-ns'))
    4673          self._feed(parser, "<tag xmlns='abc' xmlns:p='xyz'>\n")
    4674          self.assert_event_tuples(parser, [
    4675              ('start-ns', ('', 'abc')),
    4676              ('start-ns', ('p', 'xyz')),
    4677          ], max_events=2)
    4678          self.assert_event_tags(parser, [
    4679              ('start', '{abc}tag'),
    4680          ], max_events=1)
    4681
    4682          self._feed(parser, "<child />\n")
    4683          self.assert_event_tags(parser, [
    4684              ('start', '{abc}child'),
    4685              ('end', '{abc}child'),
    4686          ])
    4687
    4688          self._feed(parser, "</tag>\n")
    4689          parser.close()
    4690          self.assert_event_tags(parser, [
    4691              ('end', '{abc}tag'),
    4692          ], max_events=1)
    4693          self.assert_event_tuples(parser, [
    4694              ('end-ns', None),
    4695              ('end-ns', None),
    4696          ])
    4697
    4698 -    def test_events(self):
    4699          parser = self.etree.XMLPullParser(events=())
    4700          self._feed(parser, "<root/>\n")
    4701          self.assert_event_tags(parser, [])
    4702
    4703          parser = self.etree.XMLPullParser(events=('start', 'end'))
    4704          self._feed(parser, "<!-- text here -->\n")
    4705          self.assert_events(parser, [])
    4706
    4707          parser = self.etree.XMLPullParser(events=('start', 'end'))
    4708          self._feed(parser, "<root>\n")
    4709          self.assert_event_tags(parser, [('start', 'root')])
    4710          self._feed(parser, "<element key='value'>text</element")
    4711          self.assert_event_tags(parser, [('start', 'element')])
    4712          self._feed(parser, ">\n")
    4713          self.assert_event_tags(parser, [('end', 'element')])
    4714          self._feed(parser,
    4715                     "<element xmlns='foo'>text<empty-element/></element>tail\n")
    4716          self.assert_event_tags(parser, [
    4717              ('start', '{foo}element'),
    4718              ('start', '{foo}empty-element'),
    4719              ('end', '{foo}empty-element'),
    4720              ('end', '{foo}element'),
    4721              ])
    4722          self._feed(parser, "</root>")
    4723          root = self._close_and_return_root(parser)
    4724          self.assert_event_tags(parser, [('end', 'root')])
    4725          self.assertEqual(root.tag, 'root')
    4726
    4727          parser = self.etree.XMLPullParser(events=('start',))
    4728          self._feed(parser, "<!-- comment -->\n")
    4729          self.assert_event_tags(parser, [])
    4730          self._feed(parser, "<root>\n")
    4731          self.assert_event_tags(parser, [('start', 'root')])
    4732          self._feed(parser, "<element key='value'>text</element")
    4733          self.assert_event_tags(parser, [('start', 'element')])
    4734          self._feed(parser, ">\n")
    4735          self.assert_event_tags(parser, [])
    4736          self._feed(parser,
    4737                     "<element xmlns='foo'>text<empty-element/></element>tail\n")
    4738          self.assert_event_tags(parser, [
    4739              ('start', '{foo}element'),
    4740              ('start', '{foo}empty-element'),
    4741              ])
    4742          self._feed(parser, "</root>")
    4743          root = self._close_and_return_root(parser)
    4744          self.assertEqual(root.tag, 'root')
    4745
    4746      @et_needs_pyversion(3, 8, 0, 'alpha', 4)
    4747 -    def test_events_comment(self):
    4748          parser = self.etree.XMLPullParser(events=('start', 'comment', 'end'))
    4749          self._feed(parser, "<!-- text here -->\n")
    4750          self.assert_events(parser, [('comment', (self.etree.Comment, ' text here '))])
    4751          self._feed(parser, "<!-- more text here -->\n")
    4752          self.assert_events(parser, [('comment', (self.etree.Comment, ' more text here '))])
    4753          self._feed(parser, "<root-tag>text")
    4754          self.assert_event_tags(parser, [('start', 'root-tag')])
    4755          self._feed(parser, "<!-- inner comment-->\n")
    4756          self.assert_events(parser, [('comment', (self.etree.Comment, ' inner comment'))])
    4757          self._feed(parser, "</root-tag>\n")
    4758          self.assert_event_tags(parser, [('end', 'root-tag')])
    4759          self._feed(parser, "<!-- outer comment -->\n")
    4760          self.assert_events(parser, [('comment', (self.etree.Comment, ' outer comment '))])
    4761
    4762          parser = self.etree.XMLPullParser(events=('comment',))
    4763          self._feed(parser, "<!-- text here -->\n")
    4764          self.assert_events(parser, [('comment', (self.etree.Comment, ' text here '))])
    4765
    4766      @et_needs_pyversion(3, 8, 0, 'alpha', 4)
    4767 -    def test_events_pi(self):
    4768          # Note: lxml's PIs have target+text, ET's PIs have both in "text"
    4769          parser = self.etree.XMLPullParser(events=('start', 'pi', 'end'))
    4770          self._feed(parser, "<?pitarget?>\n")
    4771          self.assert_event_tags(parser, [('pi', self.etree.PI)])
    4772          parser = self.etree.XMLPullParser(events=('pi',))
    4773          self._feed(parser, "<?pitarget some text ?>\n")
    4774          self.assert_event_tags(parser, [('pi', self.etree.PI)])
    4775
    4776 -    def test_events_sequence(self):
    4777          # Test that events can be some sequence that's not just a tuple or list
    4778          eventset = {'end', 'start'}
    4779          parser = self.etree.XMLPullParser(events=eventset)
    4780          self._feed(parser, "<foo>bar</foo>")
    4781          self.assert_event_tags(parser, [('start', 'foo'), ('end', 'foo')])
    4782
    4783          class DummyIter(object):
    4784              def __init__(self):
    4785                  self.events = iter(['start', 'end', 'start-ns'])
    4786              def __iter__(self):
    4787                  return self
    4788              def __next__(self):
    4789                  return next(self.events)
    4790              def next(self):
    4791                  return next(self.events)
    4792
    4793          parser = self.etree.XMLPullParser(events=DummyIter())
    4794          self._feed(parser, "<foo>bar</foo>")
    4795          self.assert_event_tags(parser, [('start', 'foo'), ('end', 'foo')])
    4796
    4797 -    def test_unknown_event(self):
    4798          with self.assertRaises(ValueError):
    4799              self.etree.XMLPullParser(events=('start', 'end', 'bogus'))
    4800
    4801
    4802 -class _C14NTest(unittest.TestCase):
    4803      etree = None
    4804      maxDiff = None
    4805
    4806      if not hasattr(unittest.TestCase, 'subTest'):
    4807          @contextmanager
    4808 -        def subTest(self, name, **kwargs):
    4809              try:
    4810                  yield
    4811              except unittest.SkipTest:
    4812                  raise
    4813              except Exception as e:
    4814                  print("Subtest {} failed: {}".format(name, e))
    4815                  raise
    4816
    4817 -    def _canonicalize(self, input_file, **options):
    4818          return self.etree.canonicalize(from_file=input_file, **options)
    4819
    4820      #
    4821      # simple roundtrip tests (from c14n.py)
    4822
    4823 -    def c14n_roundtrip(self, xml, **options):
    4824          return self.etree.canonicalize(xml, **options)
    4825
    4826 -    def test_simple_roundtrip(self):
    4827          c14n_roundtrip = self.c14n_roundtrip
    4828          # Basics
    4829          self.assertEqual(c14n_roundtrip("<doc/>"), '<doc></doc>')
    4830          self.assertEqual(c14n_roundtrip("<doc xmlns='uri'/>"), # FIXME
    4831                  '<doc xmlns="uri"></doc>')
    4832          self.assertEqual(c14n_roundtrip("<prefix:doc xmlns:prefix='uri'/>"),
    4833              '<prefix:doc xmlns:prefix="uri"></prefix:doc>')
    4834          self.assertEqual(c14n_roundtrip("<doc xmlns:prefix='uri'><prefix:bar/></doc>"),
    4835              '<doc><prefix:bar xmlns:prefix="uri"></prefix:bar></doc>')
    4836          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/' />"),
    4837              '<elem></elem>')
    4838
    4839          # C14N spec
    4840          self.assertEqual(c14n_roundtrip("<doc>Hello, world!<!-- Comment 1 --></doc>"),
    4841              '<doc>Hello, world!</doc>')
    4842          self.assertEqual(c14n_roundtrip("<value>&#x32;</value>"),
    4843              '<value>2</value>')
    4844          self.assertEqual(c14n_roundtrip('<compute><![CDATA[value>"0" && value<"10" ?"valid":"error"]]></compute>'),
    4845              '<compute>value&gt;"0" &amp;&amp; value&lt;"10" ?"valid":"error"</compute>')
    4846          self.assertEqual(c14n_roundtrip('''<compute expr='value>"0" &amp;&amp; value&lt;"10" ?"valid":"error"'>valid</compute>'''),
    4847              '<compute expr="value>&quot;0&quot; &amp;&amp; value&lt;&quot;10&quot; ?&quot;valid&quot;:&quot;error&quot;">valid</compute>')
    4848          self.assertEqual(c14n_roundtrip("<norm attr=' &apos;   &#x20;&#13;&#xa;&#9;   &apos; '/>"),
    4849              '<norm attr=" \'    &#xD;&#xA;&#x9;   \' "></norm>')
    4850          self.assertEqual(c14n_roundtrip("<normNames attr='   A   &#x20;&#13;&#xa;&#9;   B   '/>"),
    4851              '<normNames attr="   A    &#xD;&#xA;&#x9;   B   "></normNames>')
    4852          self.assertEqual(c14n_roundtrip("<normId id=' &apos;   &#x20;&#13;&#xa;&#9;   &apos; '/>"),
    4853              '<normId id=" \'    &#xD;&#xA;&#x9;   \' "></normId>')
    4854
    4855          # fragments from PJ's tests
    4856          #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>"),
    4857          #'<doc xmlns:x="http://example.com/x"><b xmlns:y="http://example.com/y" a3="3" y:a1="1" y:a2="2"></b></doc>')
    4858
    4859 -    def test_c14n_exclusion(self):
    4860          c14n_roundtrip = self.c14n_roundtrip
    4861          xml = textwrap.dedent("""\
    4862          <root xmlns:x="http://example.com/x">
    4863              <a x:attr="attrx">
    4864                  <b>abtext</b>
    4865              </a>
    4866              <b>btext</b>
    4867              <c>
    4868                  <x:d>dtext</x:d>
    4869              </c>
    4870          </root>
    4871          """)
    4872          self.assertEqual(
    4873              c14n_roundtrip(xml, strip_text=True),
    4874              '<root>'
    4875              '<a xmlns:x="http://example.com/x" x:attr="attrx"><b>abtext</b></a>'
    4876              '<b>btext</b>'
    4877              '<c><x:d xmlns:x="http://example.com/x">dtext</x:d></c>'
    4878              '</root>')
    4879          self.assertEqual(
    4880              c14n_roundtrip(xml, strip_text=True, exclude_attrs=['{http://example.com/x}attr']),
    4881              '<root>'
    4882              '<a><b>abtext</b></a>'
    4883              '<b>btext</b>'
    4884              '<c><x:d xmlns:x="http://example.com/x">dtext</x:d></c>'
    4885              '</root>')
    4886          self.assertEqual(
    4887              c14n_roundtrip(xml, strip_text=True, exclude_tags=['{http://example.com/x}d']),
    4888              '<root>'
    4889              '<a xmlns:x="http://example.com/x" x:attr="attrx"><b>abtext</b></a>'
    4890              '<b>btext</b>'
    4891              '<c></c>'
    4892              '</root>')
    4893          self.assertEqual(
    4894              c14n_roundtrip(xml, strip_text=True, exclude_attrs=['{http://example.com/x}attr'],
    4895                             exclude_tags=['{http://example.com/x}d']),
    4896              '<root>'
    4897              '<a><b>abtext</b></a>'
    4898              '<b>btext</b>'
    4899              '<c></c>'
    4900              '</root>')
    4901          self.assertEqual(
    4902              c14n_roundtrip(xml, strip_text=True, exclude_tags=['a', 'b']),
    4903              '<root>'
    4904              '<c><x:d xmlns:x="http://example.com/x">dtext</x:d></c>'
    4905              '</root>')
    4906          self.assertEqual(
    4907              c14n_roundtrip(xml, exclude_tags=['a', 'b']),
    4908              '<root>\n'
    4909              '    \n'
    4910              '    \n'
    4911              '    <c>\n'
    4912              '        <x:d xmlns:x="http://example.com/x">dtext</x:d>\n'
    4913              '    </c>\n'
    4914              '</root>')
    4915          self.assertEqual(
    4916              c14n_roundtrip(xml, strip_text=True, exclude_tags=['{http://example.com/x}d', 'b']),
    4917              '<root>'
    4918              '<a xmlns:x="http://example.com/x" x:attr="attrx"></a>'
    4919              '<c></c>'
    4920              '</root>')
    4921          self.assertEqual(
    4922              c14n_roundtrip(xml, exclude_tags=['{http://example.com/x}d', 'b']),
    4923              '<root>\n'
    4924              '    <a xmlns:x="http://example.com/x" x:attr="attrx">\n'
    4925              '        \n'
    4926              '    </a>\n'
    4927              '    \n'
    4928              '    <c>\n'
    4929              '        \n'
    4930              '    </c>\n'
    4931              '</root>')
    4932
    4933      #
    4934      # basic method=c14n tests from the c14n 2.0 specification.  uses
    4935      # test files under xmltestdata/c14n-20.
    4936
    4937      # note that this uses generated C14N versions of the standard ET.write
    4938      # output, not roundtripped C14N (see above).
    4939
    4940 -    def test_xml_c14n2(self):
    4941          datadir = os.path.join(os.path.dirname(__file__), "c14n-20")
    4942          full_path = partial(os.path.join, datadir)
    4943
    4944          files = [filename[:-4] for filename in sorted(os.listdir(datadir))
    4945                   if filename.endswith('.xml')]
    4946          input_files = [
    4947              filename for filename in files
    4948              if filename.startswith('in')
    4949          ]
    4950          configs = {
    4951              filename: {
    4952                  # <c14n2:PrefixRewrite>sequential</c14n2:PrefixRewrite>
    4953                  option.tag.split('}')[-1]: ((option.text or '').strip(), option)
    4954                  for option in self.etree.parse(full_path(filename) + ".xml").getroot()
    4955              }
    4956              for filename in files
    4957              if filename.startswith('c14n')
    4958          }
    4959
    4960          tests = {
    4961              input_file: [
    4962                  (filename, configs[filename.rsplit('_', 1)[-1]])
    4963                  for filename in files
    4964                  if filename.startswith('out_%s_' % input_file)
    4965                  and filename.rsplit('_', 1)[-1] in configs
    4966              ]
    4967              for input_file in input_files
    4968          }
    4969
    4970          # Make sure we found all test cases.
    4971          self.assertEqual(30, len([
    4972              output_file for output_files in tests.values()
    4973              for output_file in output_files]))
    4974
    4975          def get_option(config, option_name, default=None):
    4976              return config.get(option_name, (default, ()))[0]
    4977
    4978          for input_file, output_files in tests.items():
    4979              for output_file, config in output_files:
    4980                  keep_comments = get_option(
    4981                      config, 'IgnoreComments') == 'true'  # no, it's right :)
    4982                  strip_text = get_option(
    4983                      config, 'TrimTextNodes') == 'true'
    4984                  rewrite_prefixes = get_option(
    4985                      config, 'PrefixRewrite') == 'sequential'
    4986                  if 'QNameAware' in config:
    4987                      qattrs = [
    4988                          "{%s}%s" % (el.get('NS'), el.get('Name'))
    4989                          for el in config['QNameAware'][1].findall(
    4990                              '{http://www.w3.org/2010/xml-c14n2}QualifiedAttr')
    4991                      ]
    4992                      qtags = [
    4993                          "{%s}%s" % (el.get('NS'), el.get('Name'))
    4994                          for el in config['QNameAware'][1].findall(
    4995                              '{http://www.w3.org/2010/xml-c14n2}Element')
    4996                      ]
    4997                  else:
    4998                      qtags = qattrs = None
    4999
    5000                  # Build subtest description from config.
    5001                  config_descr = ','.join(
    5002                      "%s=%s" % (name, value or ','.join(c.tag.split('}')[-1] for c in children))
    5003                      for name, (value, children) in sorted(config.items())
    5004                  )
    5005
    5006                  with self.subTest("{}({})".format(output_file, config_descr)):
    5007                      if input_file == 'inNsRedecl' and not rewrite_prefixes:
    5008                          self.skipTest(
    5009                              "Redeclared namespace handling is not supported in {}".format(
    5010                                  output_file))
    5011                      if input_file == 'inNsSuperfluous' and not rewrite_prefixes:
    5012                          self.skipTest(
    5013                              "Redeclared namespace handling is not supported in {}".format(
    5014                                  output_file))
    5015                      if 'QNameAware' in config and config['QNameAware'][1].find(
    5016                              '{http://www.w3.org/2010/xml-c14n2}XPathElement') is not None:
    5017                          self.skipTest(
    5018                              "QName rewriting in XPath text is not supported in {}".format(
    5019                                  output_file))
    5020
    5021                      f = full_path(input_file + ".xml")
    5022                      if input_file == 'inC14N5':
    5023                          # Hack: avoid setting up external entity resolution in the parser.
    5024                          with open(full_path('world.txt'), 'rb') as entity_file:
    5025                              with open(f, 'rb') as f:
    5026                                  f = io.BytesIO(f.read().replace(b'&ent2;', entity_file.read().strip()))
    5027
    5028                      text = self._canonicalize(
    5029                          f,
    5030                          with_comments=keep_comments,
    5031                          strip_text=strip_text,
    5032                          rewrite_prefixes=rewrite_prefixes,
    5033                          qname_aware_tags=qtags, qname_aware_attrs=qattrs)
    5034
    5035                      with io.open(full_path(output_file + ".xml"), 'r', encoding='utf8') as f:
    5036                          expected = f.read()
    5037                      if input_file == 'inC14N3' and self.etree is not etree:
    5038                          # FIXME: cET resolves default attributes but ET does not!
    5039                          expected = expected.replace(' attr="default"', '')
    5040                          text = text.replace(' attr="default"', '')
    5041                      self.assertEqual(expected, text)
    5042
    5043
    5044  if etree:
    5045 -    class ETreeTestCase(_ETreeTestCaseBase):
    5046          etree = etree
    5047
    5048 -    class ETreePullTestCase(_XMLPullParserTest):
    5049          etree = etree
    5050
    5051 -    class ETreeElementSlicingTest(_ElementSlicingTest):
    5052          etree = etree
    5053
    5054 -    class ETreeC14NTest(_C14NTest):
    5055          etree = etree
    5056
    5057 -    class ETreeC14N2WriteTest(ETreeC14NTest):
    5058 -        def _canonicalize(self, input_file, with_comments=True, strip_text=False,
    5059                            rewrite_prefixes=False, qname_aware_tags=None, qname_aware_attrs=None,
    5060                            **options):
    5061              if rewrite_prefixes or qname_aware_attrs or qname_aware_tags:
    5062                  self.skipTest("C14N 2.0 feature not supported with ElementTree.write()")
    5063
    5064              parser = self.etree.XMLParser(attribute_defaults=True, collect_ids=False)
    5065              tree = self.etree.parse(input_file, parser)
    5066              out = io.BytesIO()
    5067              tree.write(
    5068                  out, method='c14n2',
    5069                  with_comments=with_comments, strip_text=strip_text,
    5070                  **options)
    5071              return out.getvalue().decode('utf8')
    5072
    5073 -    class ETreeC14N2TostringTest(ETreeC14NTest):
    5074 -        def _canonicalize(self, input_file, with_comments=True, strip_text=False,
    5075                            rewrite_prefixes=False, qname_aware_tags=None, qname_aware_attrs=None,
    5076                            **options):
    5077              if rewrite_prefixes or qname_aware_attrs or qname_aware_tags:
    5078                  self.skipTest("C14N 2.0 feature not supported with ElementTree.tostring()")
    5079
    5080              parser = self.etree.XMLParser(attribute_defaults=True, collect_ids=False)
    5081              tree = self.etree.parse(input_file, parser)
    5082              return self.etree.tostring(
    5083                  tree, method='c14n2',
    5084                  with_comments=with_comments, strip_text=strip_text,
    5085                  **options).decode('utf8')
    5086
    5087
    5088  if ElementTree:
    5089 -    class ElementTreeTestCase(_ETreeTestCaseBase):
    5090          etree = ElementTree
    5091
    5092          @classmethod
    5093 -        def setUpClass(cls):
    5094              import warnings
    5095              # ElementTree warns about getiterator() in recent Pythons
    5096              warnings.filterwarnings(
    5097                  'ignore',
    5098                  r'This method will be removed.*\.iter\(\).*instead',
    5099                  PendingDeprecationWarning)
    5100
    5101      filter_by_version(
    5102          ElementTreeTestCase,
    5103          ElementTreeTestCase.required_versions_ET, ET_VERSION)
    5104
    5105      if hasattr(ElementTree, 'XMLPullParser'):
    5106 -        class ElementTreePullTestCase(_XMLPullParserTest):
    5107              etree = ElementTree
    5108      else:
    5109          ElementTreePullTestCase = None
    5110
    5111      if hasattr(ElementTree, 'canonicalize'):
    5112 -        class ElementTreeC14NTest(_C14NTest):
    5113              etree = ElementTree
    5114      else:
    5115          ElementTreeC14NTest = None
    5116
    5117 -    class ElementTreeElementSlicingTest(_ElementSlicingTest):
    5118          etree = ElementTree
    5119
    5120
    5121  if cElementTree:
    5122 -    class CElementTreeTestCase(_ETreeTestCaseBase):
    5123          etree = cElementTree
    5124
    5125      filter_by_version(
    5126          CElementTreeTestCase,
    5127          CElementTreeTestCase.required_versions_cET, CET_VERSION)
    5128
    5129 -    class CElementTreeElementSlicingTest(_ElementSlicingTest):
    5130          etree = cElementTree
    5131
    5132
    5133 -def test_suite():
    5134      suite = unittest.TestSuite()
    5135      if etree:
    5136          suite.addTests([unittest.makeSuite(ETreeTestCase)])
    5137          suite.addTests([unittest.makeSuite(ETreePullTestCase)])
    5138          suite.addTests([unittest.makeSuite(ETreeElementSlicingTest)])
    5139          suite.addTests([unittest.makeSuite(ETreeC14NTest)])
    5140          suite.addTests([unittest.makeSuite(ETreeC14N2WriteTest)])
    5141          suite.addTests([unittest.makeSuite(ETreeC14N2TostringTest)])
    5142      if ElementTree:
    5143          suite.addTests([unittest.makeSuite(ElementTreeTestCase)])
    5144          if ElementTreePullTestCase:
    5145              suite.addTests([unittest.makeSuite(ElementTreePullTestCase)])
    5146          if ElementTreeC14NTest:
    5147              suite.addTests([unittest.makeSuite(ElementTreeC14NTest)])
    5148          suite.addTests([unittest.makeSuite(ElementTreeElementSlicingTest)])
    5149      if cElementTree:
    5150          suite.addTests([unittest.makeSuite(CElementTreeTestCase)])
    5151          suite.addTests([unittest.makeSuite(CElementTreeElementSlicingTest)])
    5152      return suite
    5153
    5154  if __name__ == '__main__':
    5155      print('to test use test.py %s' % __file__)
    5156