lxml.tests.test_elementtree

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

# Source Code for Module lxml.tests.test_elementtree

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