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

# Source Code for Module lxml.tests.test_etree

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